T-SQL'de veritabanı adı için bir değişken nasıl kullanılır?


123

Veritabanı adını komut dosyamın birkaç yerinde kullanıyorum ve hızlı bir şekilde değiştirebilmek istiyorum, bu yüzden şuna benzer bir şey arıyorum:

DECLARE @DBNAME VARCHAR(50)
SET @DBNAME = 'TEST'

CREATE DATABASE @DBNAME
GO
ALTER DATABASE @DBNAME SET COMPATIBILITY_LEVEL = 90
GO
ALTER DATABASE @DBNAME SET RECOVERY SIMPLE 
GO

Ama işe yaramıyor. Peki bu kodu yazmanın doğru yolu nedir?

Yanıtlar:


135

Tüm komut dosyasını {SERVERNAME} yer tutucularla birlikte bir şablon dizesine yerleştirin. Ardından dizeyi şunu kullanarak düzenleyin:

SET @SQL_SCRIPT = REPLACE(@TEMPLATE, '{SERVERNAME}', @DBNAME)

ve sonra çalıştır

EXECUTE (@SQL_SCRIPT)

Üç yıl içinde kodumun çalışmadığını kimsenin fark etmediğine inanmak zor !

EXECBirden fazla parti yapamazsınız . GObir toplu iş ayırıcısıdır, bir T-SQL ifadesi değildir. Üç ayrı dizge oluşturmak ve ardından ikameden sonra EXECher biri için gereklidir .

Sanırım tek bir şablon dizgesini bölerek birden çok satıra bölerek "akıllıca" bir şey yapılabilir GO; Bunu ADO.NET kodunda yaptım.

Ve "SERVERNAME" kelimesini nereden aldım?

İşte az önce test ettiğim (ve işe yarayan) bazı kodlar:

DECLARE @DBNAME VARCHAR(255)
SET @DBNAME = 'TestDB'

DECLARE @CREATE_TEMPLATE VARCHAR(MAX)
DECLARE @COMPAT_TEMPLATE VARCHAR(MAX)
DECLARE @RECOVERY_TEMPLATE VARCHAR(MAX)

SET @CREATE_TEMPLATE = 'CREATE DATABASE {DBNAME}'
SET @COMPAT_TEMPLATE='ALTER DATABASE {DBNAME} SET COMPATIBILITY_LEVEL = 90'
SET @RECOVERY_TEMPLATE='ALTER DATABASE {DBNAME} SET RECOVERY SIMPLE'

DECLARE @SQL_SCRIPT VARCHAR(MAX)

SET @SQL_SCRIPT = REPLACE(@CREATE_TEMPLATE, '{DBNAME}', @DBNAME)
EXECUTE (@SQL_SCRIPT)

SET @SQL_SCRIPT = REPLACE(@COMPAT_TEMPLATE, '{DBNAME}', @DBNAME)
EXECUTE (@SQL_SCRIPT)

SET @SQL_SCRIPT = REPLACE(@RECOVERY_TEMPLATE, '{DBNAME}', @DBNAME)
EXECUTE (@SQL_SCRIPT)

2
+1 Çok güzel bir yaklaşım ... Beni bir ton işten kurtardın, thx ... Gerçi EXECUTE (@SQL_SCRIPT) olmalı, ya da en azından benim için işe yarayan buydu.
respawned

2
Yine de kaçarken dikkatli olmalısın.
usr

4
SYSNAMEtüm olası veritabanı adlarıyla başa çıkmak için (ve muhtemelen adın kaynağına bağlı olarak SQL enjeksiyonunu önlemek için) VARCHAR(255)kullanılması gerekenden daha uygun bir veri türü olacaktırQUOTENAME
Martin Smith

1
CREATE SCHEMAKullanarak başka bir veritabanında istersem çalışmıyor USE {DBNAME}. Şema yanlış veritabanında oluşturuyor; /
Bomberlt

103

Bunun için sqlcmdmodu da kullanabilirsiniz (bunu Management Studio'daki "Sorgu" menüsünde etkinleştirin).

:setvar dbname "TEST" 

CREATE DATABASE $(dbname)
GO
ALTER DATABASE $(dbname) SET COMPATIBILITY_LEVEL = 90
GO
ALTER DATABASE $(dbname) SET RECOVERY SIMPLE 
GO

DÜZENLE:

SQLCMD aracı aracılığıyla parametreleri ayarlamak için bu MSDN makalesine bakın.


1
bu yöntem önceden tanımlanmış değişkenleri nasıl kullanabilir? "TEST" yerine bir @dbName ekleyebilir misiniz? Denedim ve çalışmadım
syclee

1
@syclee Bir TSQL değişkeni? Script sunucuya gönderilmeden önce sqlcmd değişiklikleri yapılmaz.
Martin Smith

@MartinSmith Hey, db adını OUTPUT komutu olarak istiyorum. Peki SQLCMD kullanarak buna nasıl sahip olabilirim?
Kunal Kakkad

12

Maalesef bu formattaki bir değişkenle veritabanı adlarını açıklayamazsınız.

Başarmaya çalıştığınız şey için, ifadelerinizi bir EXEC () ifadesi içine almanız gerekecek. Yani şöyle bir şeye sahip olursunuz:

DECLARE @Sql varchar(max) ='CREATE DATABASE ' + @DBNAME

Sonra ara

EXECUTE(@Sql) or sp_executesql(@Sql)

sql dizesini çalıştırmak için.


EXECsaklı bir yordamı arar. Bu durumda EXECUTEgereklidir.
Bob Blogge

2
Aslında özür dilemem gerekiyor. Ortaya çıkıyor EXECve EXECUTEaynı. Başarısız olduktan EXECve başardıktan sonra açıklamayı yaptım EXECUTE. Açıkçası benim gerçek sorunum ikisiyle de ilgisizdi.
Bob Blogge

2
Bunu üretimde yapmayın ... Hiç.
Magic Octopus Urn

@MagicOctopusUrn eski gönderi ve çok yorum farklı ama neden olmasın merak ediyorum? gereksinime özel olmamalı mı?
Sert

@MagicOctopusUrn Bu, enjeksiyon potansiyeli nedeniyle mi?
Isaac Reefman

5

Tablo oluşturma deyiminde bir değişken kullanamazsınız. Önerebileceğim en iyi şey, tüm sorguyu bir dizge olarak yazmak ve onu çalıştırmaktır.

Bunun gibi bir şey dene:

declare @query varchar(max);
set @query = 'create database TEST...';

exec (@query);
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.