Deklarasikan Variabel untuk String Kueri

92

Saya bertanya-tanya apakah ada cara untuk melakukan ini di MS SQL Server 2005:

  DECLARE @theDate varchar(60)
  SET @theDate = '''2010-01-01'' AND ''2010-08-31 23:59:59'''

  SELECT    AdministratorCode, 
            SUM(Total) as theTotal, 
            SUM(WOD.Quantity) as theQty, 
            AVG(Total) as avgTotal, 
            (SELECT SUM(tblWOD.Amount)
                FROM tblWOD
                JOIN tblWO on tblWOD.OrderID = tblWO.ID
                WHERE tblWO.Approved = '1' 
                AND tblWO.AdministratorCode = tblWO.AdministratorCode
                AND tblWO.OrderDate BETWEEN @theDate
            )
 ... etc

Apakah ini mungkin dilakukan?

StealthRT
sumber

Jawaban:

97

Itu mungkin, tetapi membutuhkan penggunaan SQL dinamis.
Saya merekomendasikan membaca Kutukan dan berkah SQL dinamis sebelum melanjutkan ...

DECLARE @theDate varchar(60)
SET @theDate = '''2010-01-01'' AND ''2010-08-31 23:59:59'''

DECLARE @SQL VARCHAR(MAX)  
SET @SQL = 'SELECT AdministratorCode, 
                   SUM(Total) as theTotal, 
                   SUM(WOD.Quantity) as theQty, 
                   AVG(Total) as avgTotal, 
                  (SELECT SUM(tblWOD.Amount)
                     FROM tblWOD
                     JOIN tblWO on tblWOD.OrderID = tblWO.ID
                    WHERE tblWO.Approved = ''1''
                      AND tblWO.AdministratorCode = tblWO.AdministratorCode
                      AND tblWO.OrderDate BETWEEN '+ @theDate +')'

EXEC(@SQL)

SQL Dinamis hanyalah pernyataan SQL, disusun sebagai string sebelum dieksekusi. Jadi penggabungan string biasa terjadi. SQL dinamis diperlukan setiap kali Anda ingin melakukan sesuatu dalam sintaks SQL yang tidak diizinkan, seperti:

  • satu parameter untuk mewakili daftar nilai yang dipisahkan koma untuk klausa IN
  • variabel untuk mewakili nilai dan sintaks SQL (IE: contoh yang Anda berikan)

EXEC sp_executesql memungkinkan Anda untuk menggunakan parameter bind / preparedstatement sehingga Anda tidak perlu repot keluar dari tanda kutip tunggal / etc untuk serangan injeksi SQL.

OMG Ponies
sumber
Saya rasa ini adalah jawaban yang paling benar. Saya telah menggunakan SQL Server 2005 juga baru-baru ini, dan menggunakan variabel untuk penggantian string kueri seperti yang diinginkan OP tidak mungkin (menghasilkan kesalahan sintaks). Variabel tidak dapat menyertakan sintaks dan tipe data, seperti yang dikatakan @Ponies. SQL Dinamis adalah cara untuk membuat kueri di SQL Server melalui string. Ingatlah untuk berhati-hati dengan kutipan dan jenis Anda! String yang Anda jalankan memerlukan beberapa jenis, seperti datetime atau int, untuk diubah atau ditransmisikan untuk penggabungan string.
RoboBear
52
DECLARE @theDate DATETIME
SET @theDate = '2010-01-01'

Kemudian ubah kueri Anda untuk menggunakan logika ini:

AND 
(
    tblWO.OrderDate > DATEADD(MILLISECOND, -1, @theDate) 
    AND tblWO.OrderDate < DATEADD(DAY, 1, @theDate)
)
pemburu
sumber
2
Tunggu sebentar. Itu tidak bisa menjadi jawaban jika pertanyaannya menunjukkan dengan jelas dua tanggal yang berbeda. Bagaimana Anda mengkodekannya pada akhirnya @StealthRT? Di mana tanggal '2010-08-31' dalam jawaban? Juga, pertanyaan menanyakan dengan jelas apakah Anda dapat menggunakan variabel MENYATAKAN untuk menggantikan kode ke dalam pernyataan SELECT lainnya. Jawaban yang tepat ada di bawah.
Fandango68
2

Menggunakan EXEC

Anda dapat menggunakan contoh berikut untuk membuat pernyataan SQL.

DECLARE @sqlCommand varchar(1000)
DECLARE @columnList varchar(75)
DECLARE @city varchar(75)
SET @columnList = 'CustomerID, ContactName, City'
SET @city = '''London'''
SET @sqlCommand = 'SELECT ' + @columnList + ' FROM customers WHERE City = ' + @city
EXEC (@sqlCommand)

Menggunakan sp_executesql

Dengan menggunakan pendekatan ini, Anda dapat memastikan bahwa nilai data yang diteruskan ke dalam kueri adalah tipe data yang benar dan menghindari penggunaan lebih banyak tanda kutip.

DECLARE @sqlCommand nvarchar(1000)
DECLARE @columnList varchar(75)
DECLARE @city varchar(75)
SET @columnList = 'CustomerID, ContactName, City'
SET @city = 'London'
SET @sqlCommand = 'SELECT ' + @columnList + ' FROM customers WHERE City = @city'
EXECUTE sp_executesql @sqlCommand, N'@city nvarchar(75)', @city = @city

Referensi

Somnath Muluk
sumber
1

Saya akan menunjukkan bahwa dalam artikel yang ditautkan dalam jawaban teratas The Curse and Blessings of Dynamic SQL , penulis menyatakan bahwa jawabannya adalah tidak menggunakan SQL dinamis. Gulir hampir sampai akhir untuk melihat ini.

Dari artikel: "Metode yang benar adalah membongkar daftar ke dalam tabel dengan fungsi yang ditentukan pengguna atau prosedur tersimpan."

Tentu saja, setelah daftar ada di tabel, Anda dapat menggunakan gabungan. Saya tidak bisa berkomentar langsung pada jawaban teratas, jadi saya hanya menambahkan komentar ini.

DavidG
sumber
Ini tidak memberikan jawaban atas pertanyaan tersebut. Setelah memiliki reputasi yang memadai, Anda dapat mengomentari kiriman apa pun ; sebagai gantinya, berikan jawaban yang tidak memerlukan klarifikasi dari penanya . - Dari Ulasan
Sam M
Terima kasih Sam. Saya akan memperbarui komentar saya dengan detail setelah saya menerapkan apa yang disarankan Erland Sommarskog. Saya juga akan mereferensikan namanya karena dia pantas mendapatkan pujian atas jawabannya.
DavidG