Değişken olarak tablo adı


171

Bu sorguyu yürütmeye çalışıyorum:

declare @tablename varchar(50)
set @tablename = 'test'
select * from @tablename

Bu, aşağıdaki hatayı üretir:

Msg 1087, Seviye 16, Durum 1, Hat 5

Tablo değişkeni "@tablename" bildirilmelidir.

Tablo adını dinamik olarak doldurmanın doğru yolu nedir?

Yanıtlar:


131

Sorunuzdaki gibi statik sorgular için, tablo adlarının ve sütun adlarının statik olması gerekir.

Dinamik sorgular için tam SQL'i dinamik olarak oluşturmalı ve yürütmek için sp_executesql kullanmalısınız.

Farklı veritabanlarının aynı tabloları arasındaki verileri karşılaştırmak için kullanılan bir komut dosyası örneği:

statik sorgu:

SELECT * FROM [DB_ONE].[dbo].[ACTY]
EXCEPT
SELECT * FROM [DB_TWO].[dbo].[ACTY]

çünkü kolayca tha adını değiştirmek istiyorum tableve schemaben bu dinamik sorgu oluşturduk:

declare @schema varchar(50)
declare @table varchar(50)
declare @query nvarchar(500)

set @schema = 'dbo'
set @table = 'ACTY'

set @query = 'SELECT * FROM [DB_ONE].['+ @schema +'].[' + @table + '] EXCEPT SELECT * FROM [DB_TWO].['+ @schema +'].[' + @table + ']'

EXEC sp_executesql @query

Dinamik sorgular dikkate alınması gereken birçok ayrıntıya sahip olduğundan ve bakımı zor olduğundan, okumanızı tavsiye ederim: Dinamik SQL'in laneti ve bereketleri


103

Son ifadenizi şu şekilde değiştirin:

EXEC('SELECT * FROM ' + @tablename)

Saklı bir prosedürde benimkini böyle yaparım. İlk blok değişkeni bildirir ve tablo adını geçerli yıl ve ay adına göre ayarlar, bu durumda TEST_2012OCTOBER. Daha sonra DB'de olup olmadığını kontrol ediyorum ve varsa kaldırıyorum. Daha sonra bir sonraki blok, tablo oluşturmak ve parametrelerle başka bir tablodaki kayıtlarla doldurmak için SELECT INTO Deyimi kullanır.

--DECLARE TABLE NAME VARIABLE DYNAMICALLY
DECLARE @table_name varchar(max)
SET @table_name = 
    (SELECT 'TEST_'
            + DATENAME(YEAR,GETDATE())
            + UPPER(DATENAME(MONTH,GETDATE())) )

--DROP THE TABLE IF IT ALREADY EXISTS
IF EXISTS(SELECT name 
          FROM sysobjects 
          WHERE name = @table_name AND xtype = 'U')

BEGIN
    EXEC('drop table ' +  @table_name)
END

--CREATES TABLE FROM DYNAMIC VARIABLE AND INSERTS ROWS FROM ANOTHER TABLE
EXEC('SELECT * INTO ' + @table_name + ' FROM dbo.MASTER WHERE STATUS_CD = ''A''')

Bu en iyi cevap.
ColinMac

Bu en iyi yanıttır, çünkü OP'nin mevcut kodu için en doğrudan uygulanabilir.
BH

37

Bir cevap için biraz geç ama başka birine yardım etmeli:

CREATE PROCEDURE [dbo].[GetByName]
    @TableName NVARCHAR(100)
    AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;
    DECLARE @sSQL nvarchar(500);

    SELECT @sSQL = N'SELECT * FROM' + QUOTENAME(@TableName);

    EXEC sp_executesql @sSQL



END

15
QUOTENAME güvenlik için önemlidir. Teşekkürler.
Cihan Yakar

3
Ama böyle bir sorgudan nasıl değer döndürülür? Örneğin COUNT(*)?
Suncatcher

35

Bir değişken için tablo adı kullanamazsınız, bunun yerine bunu yapmanız gerekir:

DECLARE @sqlCommand varchar(1000)
SET @sqlCommand = 'SELECT * from yourtable'
EXEC (@sqlCommand)

14

SQL'i dinamik olarak oluşturmanız gerekir:

declare @tablename varchar(50) 

set @tablename = 'test' 

declare @sql varchar(500)

set @sql = 'select * from ' + @tablename 

exec (@sql)

8

sp_executesqlHerhangi bir SQL'i yürütmek için kullanın , örn.

DECLARE @tbl    sysname,
        @sql    nvarchar(4000),
        @params nvarchar(4000),
        @count  int

DECLARE tblcur CURSOR STATIC LOCAL FOR
   SELECT object_name(id) FROM syscolumns WHERE name = 'LastUpdated'
   ORDER  BY 1
OPEN tblcur

WHILE 1 = 1
BEGIN
   FETCH tblcur INTO @tbl
   IF @@fetch_status <> 0
      BREAK

   SELECT @sql =
   N' SELECT @cnt = COUNT(*) FROM dbo.' + quotename(@tbl) +
   N' WHERE LastUpdated BETWEEN @fromdate AND ' +
   N'                           coalesce(@todate, ''99991231'')'
   SELECT @params = N'@fromdate datetime, ' +
                    N'@todate   datetime = NULL, ' +
                    N'@cnt      int      OUTPUT'
   EXEC sp_executesql @sql, @params, '20060101', @cnt = @count OUTPUT

   PRINT @tbl + ': ' + convert(varchar(10), @count) + ' modified rows.'
END

DEALLOCATE tblcur

bu örnek çok faydalıdır.
Downhillski

0

Ayrıca, bunu kullanabilirsiniz ...

DECLARE @SeqID varchar(150);
DECLARE @TableName varchar(150);  
SET @TableName = (Select TableName from Table);
SET @SeqID = 'SELECT NEXT VALUE FOR '+ @TableName + '_Data'
exec (@SeqID)

0
Declare  @tablename varchar(50) 
set @tablename = 'Your table Name' 
EXEC('select * from ' + @tablename)

1
Stack Overflow'a hoş geldiniz! Bu kod soruyu çözebilir, ancak bunun sorunun nasıl ve neden çözüldüğüne dair bir açıklama da dahil olmak üzere , yayınınızın kalitesini artırmaya yardımcı olabilir ve muhtemelen daha fazla oyla sonuçlanır. Sadece şimdi soran kişi için değil, gelecekte okuyucular için soruyu cevapladığınızı unutmayın. Lütfen açıklama eklemek için cevabınızı düzenleyin ve hangi sınırlamaların ve varsayımların geçerli olduğunu belirtin. Şu kaynaktan
double-beep

0

SQL Server dinamik SQL kullanmanız gerekir

DECLARE @table     NVARCHAR(128),
        @sql       NVARCHAR(MAX);

SET @table = N'tableName';

SET @sql = N'SELECT * FROM ' + @table;

Herhangi bir SQL yürütmek için EXEC kullanın

EXEC (@sql)

Herhangi bir SQL yürütmek için EXEC sp_executesql kullanın

EXEC sp_executesql @sql;

Herhangi bir SQL yürütmek için EXECUTE sp_executesql kullanın

EXECUTE sp_executesql @sql

-1
Declare @fs_e int, @C_Tables CURSOR, @Table varchar(50)

SET @C_Tables = CURSOR FOR
        select name from sysobjects where OBJECTPROPERTY(id, N'IsUserTable') = 1 AND name like 'TR_%'
OPEN @C_Tables
FETCH @C_Tables INTO @Table
    SELECT @fs_e = sdec.fetch_Status FROM sys.dm_exec_cursors(0) as sdec where sdec.name = '@C_Tables'

WHILE ( @fs_e <> -1)
    BEGIN
        exec('Select * from '+ @Table)
        FETCH @C_Tables INTO @Table
        SELECT @fs_e = sdec.fetch_Status FROM sys.dm_exec_cursors(0) as sdec where sdec.name = '@C_Tables'
    END
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.