Nama tabel sebagai variabel

171

Saya mencoba menjalankan kueri ini:

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

Ini menghasilkan kesalahan berikut:

Msg 1087, Level 16, Negara 1, Jalur 5

Harus mendeklarasikan variabel tabel "@tablename".

Apa cara yang tepat untuk membuat nama tabel diisi secara dinamis?

SoftwareGeek
sumber

Jawaban:

131

Untuk kueri statis, seperti yang ada di pertanyaan Anda, nama tabel dan nama kolom harus statis.

Untuk kueri dinamis, Anda harus membuat SQL lengkap secara dinamis, dan menggunakan sp_executesql untuk menjalankannya.

Berikut adalah contoh skrip yang digunakan untuk membandingkan data antara tabel yang sama dari database yang berbeda:

permintaan statis:

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

karena saya ingin dengan mudah mengubah nama tabledan schemasaya telah membuat permintaan dinamis ini:

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

Karena pertanyaan dinamis memiliki banyak detail yang perlu dipertimbangkan dan sulit untuk dipertahankan, saya sarankan Anda membaca: Kutukan dan berkah dari SQL dinamis

mdma
sumber
103

Ubah pernyataan terakhir Anda menjadi ini:

EXEC('SELECT * FROM ' + @tablename)

Ini adalah cara saya melakukan prosedur tersimpan. Blok pertama akan mendeklarasikan variabel, dan mengatur nama tabel berdasarkan tahun dan bulan saat ini, dalam hal ini TEST_2012OCTOBER. Saya kemudian memeriksa apakah sudah ada di DB, dan hapus jika ada. Kemudian blok selanjutnya akan menggunakan SELECT INTO Statement untuk membuat tabel dan mengisinya dengan catatan dari tabel lain dengan parameter.

--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''')
Tim
sumber
Ini jawaban terbaik.
ColinMac
Ini adalah jawaban terbaik karena ini adalah yang paling langsung berlaku untuk kode OP yang ada.
BH
37

Agak terlambat untuk jawaban tetapi harus membantu orang lain:

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
Atul Chaudhary
sumber
15
QUOTENAME penting untuk keamanan. Terima kasih.
Cihan Yakar
3
Tetapi bagaimana cara mengembalikan nilai dari permintaan seperti itu? Misalnya COUNT(*)?
Suncatcher
35

Anda tidak dapat menggunakan nama tabel untuk variabel, Anda harus melakukan ini sebagai gantinya:

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

Anda harus membuat sql secara dinamis:

declare @tablename varchar(50) 

set @tablename = 'test' 

declare @sql varchar(500)

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

exec (@sql)
Paul Kearney - hal
sumber
8

Gunakan sp_executesqluntuk mengeksekusi SQL apa pun, misalnya

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
ghgh
sumber
contoh ini sangat bermanfaat.
Downhillski
0

Anda juga dapat menggunakan ini ...

DECLARE @SeqID varchar(150);
DECLARE @TableName varchar(150);  
SET @TableName = (Select TableName from Table);
SET @SeqID = 'SELECT NEXT VALUE FOR '+ @TableName + '_Data'
exec (@SeqID)
Disha Sojitra
sumber
0
Declare  @tablename varchar(50) 
set @tablename = 'Your table Name' 
EXEC('select * from ' + @tablename)
pengguna13581111
sumber
1
Selamat Datang di Stack Overflow! Meskipun kode ini dapat menyelesaikan pertanyaan, termasuk penjelasan tentang bagaimana dan mengapa ini menyelesaikan masalah akan sangat membantu untuk meningkatkan kualitas posting Anda, dan mungkin menghasilkan lebih banyak suara. Ingatlah bahwa Anda menjawab pertanyaan untuk pembaca di masa depan, bukan hanya orang yang bertanya sekarang. Harap edit jawaban Anda untuk menambahkan penjelasan dan berikan indikasi tentang batasan dan asumsi apa yang berlaku. Dari Ulasan
double-beep
0

Anda perlu menggunakan SQL Server dinamis SQL

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

SET @table = N'tableName';

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

Gunakan EXEC untuk menjalankan SQL apa pun

EXEC (@sql)

Gunakan EXEC sp_executesql untuk menjalankan SQL apa pun

EXEC sp_executesql @sql;

Gunakan EXECUTE sp_executesql untuk menjalankan SQL apa pun

EXECUTE sp_executesql @sql
Reza Jenabi
sumber
-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
Laurent
sumber