Dichiara variabile per una stringa di query


92

Mi chiedevo se ci fosse un modo per farlo in 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

È possibile farlo?


Risposte:


96

È possibile, ma richiede l'utilizzo di SQL dinamico.
Consiglio di leggere La maledizione e le benedizioni dell'SQL dinamico prima di continuare ...

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)

L'SQL dinamico è solo un'istruzione SQL, composta come una stringa prima di essere eseguita. Quindi si verifica la solita concatenazione di stringhe. SQL dinamico è richiesto ogni volta che vuoi fare qualcosa nella sintassi SQL che non è consentita, come:

  • un singolo parametro per rappresentare un elenco di valori separati da virgole per una clausola IN
  • una variabile per rappresentare sia il valore che la sintassi SQL (IE: l'esempio che hai fornito)

EXEC sp_executesql ti consente di utilizzare parametri bind / readystatement in modo da non doverti preoccupare di sfuggire a virgolette singole / ecc per attacchi SQL injection.


Penso che questa sia la risposta più corretta. Ho usato anche SQL Server 2005 di recente e non è possibile utilizzare una variabile per la sostituzione della stringa di query come vuole l'OP (genera errori di sintassi). Le variabili non possono includere sia la sintassi che i tipi di dati, come dice @Ponies. SQL dinamico è la strada da percorrere per la creazione di query in SQL Server tramite stringhe. Ricorda solo di stare attento alle tue citazioni e ai tuoi tipi! La stringa che esegui richiede che alcuni tipi, come datetime o int, vengano convertiti o espressi per la concatenazione di stringhe.
RoboBear

52
DECLARE @theDate DATETIME
SET @theDate = '2010-01-01'

Quindi modifica la query per utilizzare questa logica:

AND 
(
    tblWO.OrderDate > DATEADD(MILLISECOND, -1, @theDate) 
    AND tblWO.OrderDate < DATEADD(DAY, 1, @theDate)
)

2
Un attimo. Questa non può essere la risposta se la domanda mostra chiaramente due date diverse. Come l'hai codificato alla fine @StealthRT? Dov'è la data "2010-08-31" nella risposta? Inoltre, la domanda chiede chiaramente se è possibile utilizzare le variabili DECLARE per sostituire il codice in un'altra istruzione SELECT. La risposta corretta è di seguito.
Fandango68

2

Utilizzando EXEC

È possibile utilizzare il seguente esempio per creare un'istruzione 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)

Utilizzando sp_executesql

Con l'utilizzo di questo approccio è possibile garantire che i valori dei dati passati nella query siano i tipi di dati corretti ed evitare l'uso di più virgolette.

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

Riferimento


1

Sottolineerò che nell'articolo collegato alla risposta più votata The Curse and Blessings of Dynamic SQL l'autore afferma che la risposta non è usare SQL dinamico. Scorri quasi fino alla fine per vedere questo.

Dall'articolo: "Il metodo corretto è decomprimere l'elenco in una tabella con una funzione definita dall'utente o una stored procedure."

Naturalmente, una volta che l'elenco è in una tabella, puoi utilizzare un join. Non ho potuto commentare direttamente la risposta più votata, quindi ho appena aggiunto questo commento.


Questo non fornisce una risposta alla domanda. Una volta che avrai una reputazione sufficiente, potrai commentare qualsiasi post ; fornire invece risposte che non richiedono chiarimenti da parte del richiedente . - Dalla recensione
Sam M

Grazie Sam. Aggiornerò il mio commento con i dettagli una volta implementato ciò che suggerisce Erland Sommarskog. Gli farò anche riferimento per nome poiché merita credito per la risposta.
DavidG
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.