2011-07-29 43 views
6

Let us Böyle bir sorgu var ki: El ile her yerde dize değiştirerek bu sorgu farklı tablolarla birden çok kez çalıştırıyorumTablo adını bir dize olarak belirtmenin bir yolu var mı?

SELECT * FROM 
(
    SELECT * FROM 
    (
    SELECT * FROM DB.dbo.Table 
) 
    INNER JOIN DB.dbo.Table ON ... 

.

DECLARE @tablename AS VARCHAR(255) 
SET @tablename = 'DB.dbo.Table' 

Ama bu ben kullanmadan önce bir tablo değişkeni olarak @tablename ilan etme ihtiyacı olduğunu söyleyerek bana bir hata atar gibi çalışmaya görünmüyor: Aşağıdaki bildirerek çalıştı. Tablo adımı nasıl düzenlerim ve eğer mümkünse Intellisense hala çalışır mı?

cevap

7

Böyle bir EXEC açıklamada sarın:

declare @my_tablename nvarchar(100) = 'mytable'; 
exec(' 
SELECT * FROM 
(
    SELECT * FROM 
    (
    SELECT * FROM ' + @my_tablename + ' 
) 
    INNER JOIN ' + @my_tablename + ' ON ...' 
); 

Ama hayır, Intellisense bu senaryoda çalışmaz.

size çıkış önceden nasıl görüneceğini biliyorsanız

, o zaman sonuç tutmak için geçici bir tablo ilan edebilir ve sonra EXEC olmadan bu erişebilir. Geçici masadaki zekayı alacaksın. Örneğin

:

--this must match whatever your SELECT is going to return 
    CREATE TABLE #results(
    FIELD1 INT 
    ,FIELD2 NVARCHAR(100) 
    ,FIELD3 BIT 
    ); 

EXEC(' 
    INSERT INTO #results(field1,field2,field3) 
    SELECT FIELD1,FIELD2,FIELD3 FROM ' + @my_tablename 
); 

select * from #results --you will have intellisense on #results 
3

Dinamik SQL kullanın. Emin değilim bu kadar çok iç içe seçer gerek ama bir şey gibi olurdu neden:

DECLARE @sql NVARCHAR(MAX) = N'SELECT ... FROM ' + @tablename + '...'; 
EXEC sp_executeSQL @sql; 

Ancak, SQL enjeksiyon unutmayın. Ve hayır, IntelliSense, nesne adları için bir dizeyi ayrıştırma yeteneğine sahip değildir (veya hangi nesne adını orada düzenleyeceğini bile bilmek bile). Eğer bir dize olarak C# programında işlev adı belirleyemezsiniz gibi

+0

+ 1. Bağımlılık enjeksiyonunu söylediğin için teşekkürler. Link için –

4

sayılı. T-SQL derlemesinin kesin bir erişim planı oluşturması gerekiyor, bu da hangi indekslerin açılacağını ve sorguyu tatmin edecek şekilde kullanılacağını gösteriyor. Bir yöntem olarak bir 'dizesi' çağırmak için kod oluşturmak için C# imkansız olurdu, tıpkı bir 'string' için bir plan ile gelip imkansız olurdu.

declare @sql NVARCHAR(MAX) = N'SELECT ... FROM ' + 
    quotename(@dbname) + N'.' + quotename(@schema) + N'.' + quotename(@table) + 
    N' WHERE ...'; 
exec sp_executesql @sql; 

... sadece C# dinamik çalışma zamanı çağırmayı yapmak yansıma kullandığınız gibi:

çözüm dinamik SQL olduğunu. Daha fazla bilgi için

The Curse and Blessings of Dynamic SQL görüyoruz.

PS. bileşenlerine @ Tabloadı bölünmüş ve QUOTENAME kullanımı mutlak bir zorunluluktur, bu SQL Enjeksiyon agaisnt koruyan olduğunu. Bölme işlemini sizin için PARSENAME kullanın.

+0

+1, dinamik SQL ile uğraşırken her zaman gidilecek ilk yer – Lamak

İlgili konular