it-swarm.com.de

SET versus SELECT beim Zuweisen von Variablen?

Was sind die Unterschiede zwischen den Anweisungen SET und SELECT beim Zuweisen von Variablen in T-SQL?

268
juur

Zitat , das aus diesem Artikel zusammenfasst:

  1. SET ist der ANSI-Standard für die Variablenzuweisung, SELECT nicht.
  2. SET kann jeweils nur eine Variable zuweisen, SELECT kann mehrere Zuweisungen gleichzeitig vornehmen.
  3. 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).
  4. 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).
  5. 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.
393
OMG Ponies

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' */
144
Joe Stefanelli

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*/
24
GorkemHalulu

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.
3
CodingYoshi