2016-11-29 7 views
0

Als höher in der Hierarchie Forum Benutzer vorgeschlagen Im Postig mein Problem als eine neue Frage zu diesem: declare variable for query string.Variable für Query String

Ich benutze dynamische Abfrage hier, weil ich in der Lage sein möchte, Variablen zu verwenden (ich brauche es für mein Experiment mit Parameter Sniffing). Meine Abfrage sieht wie folgt aus:

DECLARE @i NVARCHAR(10) 
SET @i = 'POL' 

DECLARE @sql VARCHAR(MAX) 
SET @sql = 'SELECT 

a.something1, 
b.something2, 
c.something3 

FROM 
aaa a WITH(NOLOCK) 
LEFT JOIN bbb b WITH(NOLOCK) ON.... 
LEFT JOIN ccc c WITH(NOLOCK) ON.... 

WHERE 
a.somethingelse = ''aa'' 
AND 
((a.entirelysomethingelse=''aaa'') OR (a.entirelysomethingelse=''aaaa'')) 
AND 
b.anotherdifferentsomething != 41 
AND 
c.yetanotherdifferentthing LIKE(''%@%'') 
AND 
c.datafromvariablewannabe = (@i) 
GROUP BY 
... 
ORDER BY 
...' 
EXECUTE (@SQL) 

Wenn ich möchte wie meine Abfrage Ich erhalte Fehler auszuführen:

'Msg 137, Level 15, State 2, Line 28 
Must declare the scalar variable "@i".' 

Wenn ich Deklaration der Variablen @i in die @sql dann bewegt es sorta funktioniert. Trotzdem glaube ich nicht, dass es das ist, was ich wollte. Mache ich etwas falsch oder hat es so aussehen ?:

DECLARE @sql VARCHAR(MAX) 
SET @sql = ' 

DECLARE @i NVARCHAR(10) 
SET @i = 'POL' 

SELECT 

a.something1, 
b.something2, 
c.something3 

FROM 
aaa a WITH(NOLOCK) 
LEFT JOIN bbb b WITH(NOLOCK) ON.... 
LEFT JOIN ccc c WITH(NOLOCK) ON.... 

WHERE 
a.somethingelse = ''aa'' 
AND 
((a.entirelysomethingelse=''aaa'') OR (a.entirelysomethingelse=''aaaa'')) 
AND 
b.anotherdifferentsomething != 41 
AND 
c.yetanotherdifferentthing LIKE(''%@%'') 
AND 
c.datafromvariablewannabe = (@i) 
GROUP BY 
... 
ORDER BY 
...' 
EXECUTE (@SQL) 

Gibt es in meinem Code keine Fehler so Im MSG137 Fehler bekommen oder es ist nur unmögliche Aufgabe, die ich hier machen will.

Ich möchte keine gespeicherte Prozedur von dieser Abfrage erstellen. Ich möchte in der Lage sein, Variablen zu verwenden, ohne auf gespeicherte Prozeduren angewiesen zu sein.

Ich entschuldige mich Admins/Forum Benutzer für Probleme mit meiner früheren Frage in Frage gestellt.

+0

was bedeutet das 'Als ich die Deklaration der Variablen @i in die @sql verschoben habe, funktioniert es. Dennoch glaube ich nicht, dass es das ist, was ich wollte – TheGameiswar

+2

Variablen sind auf einen Batch beschränkt und exec läuft in separaten Batch, so müssen Sie es in der gleichen @ sql – TheGameiswar

+0

Ich meinte, dass ich gutes Ergebnis, aber die Methode, diese Ergebnisse zu bekommen war nicht diejenige, nach der ich suchte. Ich wusste nicht, dass ich die Abfragezeichenfolge (wie @mortb suggested) "brechen" muss, damit meine Variable "geladen" werden könnte? da drin. – M3How

Antwort

2

Sie müssen die Zeichenfolge "brechen". Der Wert @i ist in dem Bereich, in dem die Zeichenfolge ausgeführt wird, nicht verfügbar, daher müssen Sie ihn in die Zeichenfolge aufnehmen. Wie so:

DECLARE @tmp NVARCHAR(10) 
SET @tmp = 'POL' 

DECLARE @sql VARCHAR(MAX) 
SET @sql = 'SELECT 

a.something1, 
b.something2, 
c.something3 

FROM 
aaa a WITH(NOLOCK) 
LEFT JOIN bbb b WITH(NOLOCK) ON.... 
LEFT JOIN ccc c WITH(NOLOCK) ON.... 

WHERE 
a.somethingelse = ''aa'' 
AND 
((a.entirelysomethingelse=''aaa'') OR (a.entirelysomethingelse=''aaaa'')) 
AND 
b.anotherdifferentsomething != 41 
AND 
c.yetanotherdifferentthing LIKE(''%@%'') 
AND 
c.datafromvariablewannabe = (@i) 
GROUP BY 
... 
ORDER BY 
... 
OPTION(OPTIMIZE FOR(@i = ''' + @tmp + '''))' 
EXEC SP_EXECUTESQL @SQL, N'@i NVARCHAR(255)', @i = @tmp 
+0

Dies ist die Antwort, nach der ich gesucht habe. Trotzdem musste ich die @ i-Variable in Anführungszeichen setzen. So muss es aussehen: 'DECLARE @i nvARCHAR (10) SET @i = '' 'POL' ''' – M3How

+0

Es gibt noch eine Sache. Wenn ich hier 'option (für @i optimieren)' hinzufügen möchte, wo oder wie soll ich das machen? In diesem speziellen Fall. – M3How

+1

Nach der ORDER BY Ref: https://msdn.microsoft.com/en-us/library/ms181714.aspx Es ist spezifisch für eine Abfrage-Anweisung (Sie sollten es zuletzt in Sie SELECT-Anweisung setzen) – mortb

1

Die Arbeitslösung mit optimize für @variable so aussehen würde:

DECLARE @i NVARCHAR(255) 
declare @tmp nvarchar(255) 
SET @tmp = 'POL' 

DECLARE @SQL nVARCHAR(MAX) 
SET @sql = 'SELECT 

a.something1, 
b.something2, 
c.something3 

FROM 
aaa a WITH(NOLOCK) 
LEFT JOIN bbb b WITH(NOLOCK) ON.... 
LEFT JOIN ccc c WITH(NOLOCK) ON.... 

WHERE 
a.somethingelse = ''aa'' 
AND 
((a.entirelysomethingelse=''aaa'') 
OR 
(a.entirelysomethingelse=''aaaa'')) 
AND 
b.anotherdifferentsomething != 41 
AND 
c.yetanotherdifferentthing LIKE(''%@%'') 
AND 
c.datafromvariablewannabe = (@i) 

GROUP BY 
... 
ORDER BY 
... 

OPTION(OPTIMIZE FOR(@i = ''' + @tmp + '''))' 

EXECUTE SP_EXECUTESQL @SQL, N'@i NVARCHAR(255)', @i = @tmp 

Es hat ohne erklären Variable @temp nicht funktioniert. Danach stieß ich auf ein Problem mit Exec. Ich konnte SP_EXECUTESQL nicht als @mortb vorgeschlagen verwenden. Ich musste EXECUTE vor SP_EXECUTESQL verwenden und ich fand einige Informationen zum nächsten Fehler in diesem Beitrag Why do I get "Procedure expects parameter '@statement' of type 'ntext/nchar/nvarchar'." when I try to use sp_executesql?. Ich musste den Typ für eine Abfragevariable ändern und wurde von Klammern befreit.

Noch würde ich gerne wissen, warum ich neue Variable erstellen musste und es wäre hilfreich ein bisschen mehr über diesen Teil des Codes zu wissen:

OPTION(OPTIMIZE FOR(@i = ''' + @tmp + '''))' 

EXECUTE SP_EXECUTESQL @SQL, N'@i NVARCHAR(255)', @i = @tmp 

Es funktioniert jetzt, aber ich möchte warum und wie?

+0

Ich habe Ihre Änderungen zu meiner Antwort oben hinzugefügt. – mortb

+1

'SP_EXECUTESQL' ist eine integrierte gespeicherte Prozedur, die eine SQL-Zeichenfolge verwendet und sie mit den angegebenen Parametern ausführt. Es ist am Anfang verwirrend, wenn Sie sql aus einer Zeichenkette machen. Der Teil 'N '@ i NVARCHAR (255)', @i = @ tmp' teilt der gespeicherten Prozedur mit, dass ein Parameter im SQL-Text mit dem Namen' @ i' und dem '@ i' (wenn der Text ausführt) sollte den gleichen Wert haben, den "@ tmp" außerhalb des Textes hat. Der Teil 'OPTION (OPTIMIZE FOR (@i = '' '+ @tmp +' '')) 'bedeutet, dass der Text * den Wert von *' tmp' enthält (es ist keine Variable mehr, wenn der Text ist in 'SP_EXECUTESQL' eingegeben. – mortb

+1

Gib ihm etwas Zeit und du wirst es verstehen :) – mortb