Antworten:
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.
- Bei der Zuweisung 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 verbirgt die Tatsache, dass mehrere Werte zurückgegeben wurden (sodass Sie wahrscheinlich nie wissen würden, warum anderswo 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 Aufgaben auf einmal zu erledigen, bietet jedoch einen leichten Geschwindigkeitsvorteil gegenüber SET.
SELECT @Int = @Int + 1, @Int = @Int + 1
Wenn sie @Int
als 0 gestartet wird, endet sie als 2. Dies kann sehr nützlich sein, wenn aufeinanderfolgende Zeichenfolgenmanipulationen durchgeführt werden.
Ich glaube, es SET
ist ANSI-Standard, während dies SELECT
nicht der Fall ist. Beachten Sie auch das unterschiedliche Verhalten von SET
vs. SELECT
im folgenden Beispiel, wenn kein Wert 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' */
select @var = (select name from master.sys.tables where name = 'qwerty')
, würden Sie @var als null erhalten. Das Beispiel, das Sie geben, ist nicht dieselbe Abfrage.
(select name from master.sys.tables where name = 'qwerty')
für den einen und name from master.sys.tables where name = 'qwerty'
für den anderen ... sehen Sie das nicht?
(select name from master.sys.tables where name = 'qwerty')
ist eine skalare Unterabfrage und name from master.sys.tables where name = 'qwerty'
eine einfache Abfrage. Die beiden unterschiedlichen Ausdrücke sollen nicht zu denselben Ergebnissen führen, obwohl Sie anscheinend implizieren, dass dies der Fall sein sollte. Wenn Sie das versuchen , zu sagen SET
und SELECT
Schlüsselwörter haben unterschiedliche Implementierungen, sollten Sie nicht verwenden zwei verschiedene Ausdrücke in Ihren Beispielen. msdn.microsoft.com/en-us/library/ms187330.aspx
Beim Schreiben von Abfragen sollte dieser Unterschied berücksichtigt 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 dies 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 die Absicht des Entwicklers. Oben ist die Abfrage einfach, aber ich habe Abfragen gesehen, die ziemlich komplex sind und herauszufinden, ob sie einen einzelnen Wert zurückgeben oder nicht, ist nicht trivial. Die Abfrage ist häufig komplexer und hat zufällig einen einzelnen Wert zurückgegeben. Während der 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:
Die Unterabfrage gab mehr als 1 Wert zurück. Dies ist nicht zulässig, wenn die Unterabfrage folgt = ,! =, <, <=,>,> = Oder wenn die Unterabfrage als Ausdruck verwendet wird.
Das ist erstaunlich und sehr wichtig , denn warum sollte man etwas trivial „letztes Element in Folge“ , um die zugewiesen werden soll @employeeId
. Mitselect
Sie nie einen Fehler bekommen und Sie werden Minuten, Stunden mit dem Debuggen verbringen.
Möglicherweise suchen Sie nach einer einzelnen ID und SET
werden gezwungen, 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.