Gegeben die folgende Tabelle:
%Vor% Ich wollte eine dynamische SQL-Abfrage mit EXEC
bei einem Val
-Wert ausführen:
Dies wird ohne Fehler ausgeführt und liefert das korrekte Ergebnis.
Ich gehe davon aus, dass dies zu einem Fehler führen wird:
Konvertierung fehlgeschlagen beim Konvertieren des Varchar-Wertes 'SELECT * FROM #T WHERE Val = 'zum Datentyp int.
Da @Val
vom Datentyp INT
ist und nach den Regeln von Datentyp Vorrang muss die Abfrage in EXEC
in INT
konvertiert werden.
Meine Frage ist, warum hat der Aufruf von EXEC
keinen Konvertierungsfehler verursacht?
Anmerkungen:
- Ich weiß über sp_executesql
. Ich frage auch nicht nach einer Alternative. Ich frage nur nach einer Erklärung, warum kein Fehler erzeugt wurde.
- Die Antwort auf diese Frage scheint meine Situation nicht zu erklären, da sich die Frage auf% co_de bezieht % bis VARCHAR
Verkettung.
Laut MSDN / BOL lautet die vereinfachte Syntax für EXEC[UTE]
statement:
Wenige Anmerkungen:
1) Nach dieser Zeile ( { @string_variable | [ N ] 'command_string [ ? ]' } [ **+** ...n ]
können wir etwas wie EXEC (@var1 + @var2 + @var3)
schreiben, aber laut letztem Absatz erwartet SQL Server, dass diese Variablen einen der folgenden string -Datentypen haben: char
, varchar
, nchar
oder nvarchar
.
2) Diese Syntax verweist auch nur auf string variables
( @string_variable | [ N ] 'command_string [ ? ]' } [ + ...n
). Ich glaube, das ist der Grund, warum EXEC ('SELECT * FROM #T WHERE Val = ' + 3);
fehlschlägt: 3
ist keine Variable.
3) Ich nehme an, dass wenn eine dieser Variablen keinen der oben genannten Stringtypen hat, SQL Server eine implizite Konvertierung durchführt. Ich gehe davon aus, dass die Quellvariable von INT
(zum Beispiel) in NVARCHAR
konvertiert wird, weil sie die höchste Datentyp Vorrang zwischen diesen String-Typen.
4) Dies ist nicht der einzige Ort, an dem die Priorität des Datentyps nicht funktioniert. ISNULL(param1, param2)
ist nur ein weiteres Beispiel. In diesem Fall wird param2
in den Datentyp param1
konvertiert.
Eine implizite Konvertierung von int
in Zeichenkettentypen ist erlaubt, mindestens so weit zurück wie SQL Server 2008.
Siehe auch: Datentypkonvertierung (Datenbankmodul)
Sie können die implizite Konvertierung nicht deaktivieren: Gibt es eine Möglichkeit, die implizite Typkonvertierung in SQL Server zu deaktivieren?
Bearbeiten: Ich schrieb ursprünglich
'SELECT * FROM #T WHERE Val = ' + @Val
wird vor dem Aufruf vonEXEC
erstellt.
Ich bin mir da nicht so sicher. Ich vermute jetzt, dass das Argument zu EXEC
an einen Teil der DB-Engine übergeben wird, der es auf eine andere Art analysiert als wir es gewohnt sind.
Alles, was MSDN über die Verkettung in EXEC [UTE] erzählt, ist:
Die Verkettung wird im SQL Server-Parser logisch ausgeführt und tritt nie im Speicher auf.
Wir können also nicht viel darüber wissen, was SQL Server tief in sich trägt. Wir wissen nur, dass EXEC einen Ausdruck nicht als Argument akzeptiert, sondern eine Liste von Strings akzeptiert, die durch '+' begrenzt sind.
Wenn Sie sich die Syntax ansehen:
%Vor%Es unterstützt direkt eine Anzahl von Strings oder Variablen, die durch ein '+' Zeichen getrennt sind. Daher übergeben Sie einen Ausdruck nicht wirklich an EXEC, und Sie umgehen daher den SQL Server-Ausdrucksparser.
Tags und Links sql-server dynamic-sql