Was sind die Unterschiede zwischen den Anweisungen SET
und SELECT
beim Zuweisen von Variablen in T-SQL?
Zitat , das aus diesem Artikel zusammenfasst:
- SET ist der ANSI-Standard für die Variablenzuweisung, SELECT nicht.
- SET kann jeweils nur eine Variable zuweisen, SELECT kann mehrere Zuweisungen gleichzeitig vornehmen.
- Beim Zuweisen aus einer Abfrage kann SET nur einen Skalarwert zuweisen. Wenn die Abfrage mehrere Werte/Zeilen zurückgibt, löst SET einen Fehler aus. SELECT weist der Variablen einen der Werte zu und blendet die Tatsache aus, dass mehrere Werte zurückgegeben wurden (sodass Sie wahrscheinlich nie wissen, warum an anderer Stelle etwas schief gelaufen ist - viel Spaß bei der Fehlerbehebung).
- Wenn bei der Zuweisung aus einer Abfrage kein Wert zurückgegeben wird, weist SET NULL zu, wobei SELECT die Zuweisung überhaupt nicht vornimmt (sodass die Variable nicht von ihrem vorherigen Wert geändert wird).
- In Bezug auf Geschwindigkeitsunterschiede gibt es keine direkten Unterschiede zwischen SET und SELECT. Die Fähigkeit von SELECT, mehrere Zuordnungen in einer Aufnahme vorzunehmen, bietet jedoch einen leichten Geschwindigkeitsvorteil gegenüber SET.
Ich glaube, dass SET
ANSI-Standard ist, während SELECT
dies nicht ist. Beachten Sie auch das unterschiedliche Verhalten von SET
vs. SELECT
im folgenden Beispiel, wenn ein Wert nicht gefunden wird.
declare @var varchar(20)
set @var = 'Joe'
set @var = (select name from master.sys.tables where name = 'qwerty')
select @var /* @var is now NULL */
set @var = 'Joe'
select @var = name from master.sys.tables where name = 'qwerty'
select @var /* @var is still equal to 'Joe' */
Beim Schreiben von Abfragen sollte dieser Unterschied beachtet werden:
DECLARE @A INT = 2
SELECT @A = TBL.A
FROM ( SELECT 1 A ) TBL
WHERE 1 = 2
SELECT @A
/* @A is 2*/
---------------------------------------------------------------
DECLARE @A INT = 2
SET @A = (
SELECT TBL.A
FROM ( SELECT 1 A) TBL
WHERE 1 = 2
)
SELECT @A
/* @A is null*/
Abgesehen von ANSI, Geschwindigkeit usw. gibt es einen sehr wichtigen Unterschied, der mir immer wichtig ist. mehr als ANSI und Geschwindigkeit. Die Anzahl der Fehler, die ich aufgrund dieses wichtigen Übersehens behoben habe, ist groß. Ich suche das die ganze Zeit bei Code-Überprüfungen.
-- Arrange
create table Employee (EmployeeId int);
insert into dbo.Employee values (1);
insert into dbo.Employee values (2);
insert into dbo.Employee values (3);
-- Act
declare @employeeId int;
select @employeeId = e.EmployeeId from dbo.Employee e;
-- Assert
-- This will print 3, the last EmployeeId from the query (an arbitrary value)
-- Almost always, this is not what the developer was intending.
print @employeeId;
Fast immer ist das nicht das, was der Entwickler vorhat. Oben ist die Abfrage einfach, aber ich habe Abfragen gesehen, die sehr komplex sind, und herauszufinden, ob ein einzelner Wert zurückgegeben wird oder nicht, ist nicht trivial. Die Abfrage ist häufig komplexer und hat zufällig einen einzelnen Wert zurückgegeben. Während des Entwicklertests ist alles in Ordnung. Dies ist jedoch wie eine tickende Bombe und führt zu Problemen, wenn die Abfrage mehrere Ergebnisse zurückgibt. Warum? Weil es der Variablen einfach den letzten Wert zuweist.
Versuchen wir jetzt dasselbe mit SET
:
-- Act
set @employeeId = (select e.EmployeeId from dbo.Employee e);
Sie erhalten eine Fehlermeldung:
Unterabfrage hat mehr als 1 Wert zurückgegeben. Dies ist nicht zulässig, wenn die Unterabfrage auf =,! =, <, <=,>,> = Folgt oder wenn die Unterabfrage als Ausdruck verwendet wird.
Das ist erstaunlich und sehr wichtig, denn warum sollten Sie dem @employeeId
einen unbedeutenden "letzten Punkt im Ergebnis" zuweisen? Mit select
erhalten Sie niemals einen Fehler und verbringen Minuten, Stunden mit dem Debuggen.
Möglicherweise suchen Sie nach einer einzelnen ID und SET
zwingt Sie, Ihre Abfrage zu korrigieren. So können Sie etwas tun wie:
-- Act
-- Notice the where clause
set @employeeId = (select e.EmployeeId from dbo.Employee e where e.EmployeeId = 1);
print @employeeId;
Aufräumen
drop table Employee;
Verwenden Sie abschließend:
SET
: Wenn Sie einer Variablen einen einzelnen Wert zuweisen möchten und Ihre Variable für einen einzelnen Wert bestimmt ist.SELECT
: Wenn Sie einer Variablen mehrere Werte zuweisen möchten. Die Variable kann eine Tabelle, eine temporäre Tabelle oder eine Tabellenvariable usw. sein.