wake-up-neo.net

SET contro SELECT quando si assegnano le variabili?

Quali sono le differenze tra le istruzioni SET e SELECT quando si assegna variabili in T-SQL?

261
juur

Citazione , che riepiloga da questo articolo :

  1. SET è lo standard ANSI per l'assegnazione di variabili, SELECT no.
  2. SET può solo assegnare una variabile alla volta, SELECT può eseguire più incarichi contemporaneamente.
  3. Se si assegna da una query, SET può solo assegnare un valore scalare. Se la query restituisce più valori/righe, SET genererà un errore. SELECT assegna uno dei valori alla variabile e nasconde il fatto che sono stati restituiti più valori (quindi probabilmente non sapresti mai perché qualcosa andasse storto altrove - divertiti a risolverlo)
  4. Quando si assegna da una query se non è stato restituito alcun valore, SET assegnerà NULL, dove SELECT non eseguirà affatto l'assegnazione (quindi la variabile non verrà modificata rispetto al suo valore precedente)
  5. Per quanto riguarda le differenze di velocità, non ci sono differenze dirette tra SET e SELECT. Tuttavia, la capacità di SELEZIONA di eseguire più compiti in un colpo gli conferisce un leggero vantaggio di velocità rispetto a SET.
386
OMG Ponies

Credo che SET sia standard ANSI, mentre SELECT non lo è. Si noti inoltre il diverso comportamento di SET rispetto a SELECT nell'esempio qui sotto quando non si trova un valore.

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

Quando si scrivono query, è necessario tenere presente questa differenza:

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

A parte l'ANSI e la velocità ecc., C'è una differenza molto importante che mi interessa sempre; più di ANSI e velocità. Il numero di bug che ho corretto a causa di questo importante aspetto è grande. Lo cerco durante le revisioni del codice tutto il tempo.

-- 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; 

Quasi sempre, non è ciò che lo sviluppatore intende. In quanto sopra, la query è semplice ma ho visto query piuttosto complesse e capire se restituirà un singolo valore o meno, non è banale. La query è spesso più complessa di questa e per caso ha restituito un valore singolo. Durante i test degli sviluppatori va tutto bene. Ma è come una bomba a orologeria e causerà problemi quando la query restituisce più risultati. Perché? Perché assegnerà semplicemente l'ultimo valore alla variabile.

Ora proviamo la stessa cosa con SET:

 -- Act
 set @employeeId = (select e.EmployeeId from dbo.Employee e);

Riceverai un errore:

La sottoquery ha restituito più di 1 valore. Questo non è permesso quando la subquery segue =,! =, <, <=,>,> = O quando la sottoquery viene usata come espressione.

Questo è sorprendente e molto importante, perché dovresti voler assegnare qualche "ultimo elemento in risultato" banale al @employeeId. Con select non riceverai mai alcun errore e passerai minuti, ore di debugging.

Forse, stai cercando un singolo Id e SET ti costringerà a correggere la tua richiesta. Quindi puoi fare qualcosa come:

-- Act
-- Notice the where clause
set @employeeId = (select e.EmployeeId from dbo.Employee e where e.EmployeeId = 1);
print @employeeId;

Pulire

drop table Employee;

In conclusione, usa:

  • SET: quando si desidera assegnare un singolo valore a una variabile e la variabile è per un singolo valore.
  • SELECT: quando si desidera assegnare più valori a una variabile. La variabile può essere una tabella, una tabella temporanea o una variabile di tabella, ecc.
2
CodingYoshi