Care sunt diferențele între " SET " și "SELECTAȚI" declarații atunci când atribuie variabile în T-SQL?
Quote, care rezumă din acest articol:
- SETUL este standardul ANSI pentru atribuirea variabilă, SELECTAȚI nu.
- SETUL poate atribui doar o singură variabilă la un moment dat, SELECTAȚI pot face mai multe sarcini simultan.
- Dacă atribuirea dintr-o interogare, SET poate atribui numai o valoare scalară. Dacă interogarea returnează valori multiple/rânduri STABILIT apoi va genera o eroare. SELECTAȚI vor atribui una dintre valorile variabilei și ascunde faptul că mai multe valori au fost returnate (deci'd probabil nu știu de ce există ceva în neregulă în altă parte - distreaza-te de depanare asta)
- Atunci când atribuirea dintr-o interogare dacă nu există nici o valoare a revenit apoi SETAȚI va atribui NUL, în cazul în care SELECTAȚI nu va face repartizarea la toate (deci variabila nu va fi schimbat de la valoarea anterioară)
- În ceea ce privește viteza diferențe nu sunt direct diferențele dintre SET și SELECTAȚI. Cu toate acestea, SELECTA's capacitatea de a face mai multe sarcini într-o singură lovitură se dă un ușor avantaj de viteză pe SET.
Cred ca " SET "este ANSI standard întrucât "SELECTAȚI" nu este. Rețineți, de asemenea, un comportament diferit de " SET " vs "ALEGE" în exemplul de mai jos, atunci când o valoare nu este găsită.
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' */
Atunci când scrieți interogări, această diferență ar trebui să fie păstrate în minte :
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*/
În afară de o singură ființă ANSI și viteza etc., există o diferență foarte importantă că întotdeauna contează pentru mine; mai mult de ANSI și viteza. Numărul de bug-uri am fix din cauza acestui important vedere este mare. Ma uit in cod clienți tot timpul.
-- 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;
Aproape întotdeauna, că nu este ceea ce dezvoltatorul intenționează. În cele de mai sus, interogarea este drept înainte, dar am văzut interogări care sunt destul de complexe și dea seama dacă acesta va returna o singură valoare sau nu, nu este trivial. Interogarea este de multe ori mai complexă decât aceasta și din întâmplare a fost întorcându-se singură valoare. În timpul producător de testare totul este bine. Dar acest lucru este ca o bombă cu ceas și va provoca probleme atunci când interogarea returnează mai multe rezultate. De ce? Pentru că pur și simplu va atribui ultima valoare a variabilei.
Acum las's încercați același lucru cu "SET":
-- Act
set @employeeId = (select e.EmployeeId from dbo.Employee e);
Veți primi o eroare:
Subinterogare a revenit mai mult de 1 valoare. Acest lucru nu este permis atunci când subinterogare cum urmează =, !=, <, <= , >, >= sau atunci când subinterogare este folosit ca o expresie.
Este uimitor și foarte important, deoarece de ce ai vrea să atribuiți un banal "ultimul element din urma" la @employeeId
. Cu "selectați" tu nu va primi nici o eroare și va petrece minute, ore depanare.
Probabil, sunteți în căutarea pentru un singur Id si " SET " va forța pentru a repara erorile de interogare. Astfel s-ar putea face ceva de genul:
-- Act
-- Notice the where clause
set @employeeId = (select e.EmployeeId from dbo.Employee e where e.EmployeeId = 1);
print @employeeId;
Curatare
drop table Employee;
În concluzie, folosiți: