Risposte:
Citazione , che riassume da questo articolo :
- SET è lo standard ANSI per l'assegnazione delle variabili, mentre SELECT non lo è.
- SET può assegnare una sola variabile alla volta, SELECT può eseguire più assegnazioni contemporaneamente.
- Se si assegna da una query, SET può assegnare solo un valore scalare. Se la query restituisce più valori / righe, SET genererà un errore. SELECT assegnerà uno dei valori alla variabile e nasconderà il fatto che sono stati restituiti più valori (quindi probabilmente non sapresti mai perché qualcosa non andava altrove - divertiti a risolverlo)
- Quando si assegna da una query se non viene restituito alcun valore, SET assegnerà NULL, dove SELECT non eseguirà affatto l'assegnazione (quindi la variabile non verrà modificata dal suo valore precedente)
- Per quanto riguarda le differenze di velocità, non ci sono differenze dirette tra SET e SELECT. Tuttavia, la capacità di SELECT di eseguire più incarichi in un colpo solo gli conferisce un leggero vantaggio di velocità rispetto a SET.
SELECT @Int = @Int + 1, @Int = @Int + 1
se @Int
avviato come 0, termina come 2. Ciò può essere molto utile quando si eseguono successive manipolazioni di stringhe.
Credo SET
sia lo standard ANSI mentre non lo SELECT
è. Si noti inoltre il diverso comportamento di SET
vs. SELECT
nell'esempio seguente quando non viene trovato 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' */
select @var = (select name from master.sys.tables where name = 'qwerty')
si otterrebbe @var come null. L'esempio che stai dando non è la stessa query.
(select name from master.sys.tables where name = 'qwerty')
per uno e name from master.sys.tables where name = 'qwerty'
per l'altro ... non lo vedi?
(select name from master.sys.tables where name = 'qwerty')
è una sottoquery scalare ed name from master.sys.tables where name = 'qwerty'
è una query semplice. Le due diverse espressioni non dovrebbero produrre gli stessi risultati, anche se sembra che tu stia insinuando che dovrebbero. Se stai cercando di dire che le parole chiave SET
e SELECT
hanno implementazioni diverse, non dovresti usare due espressioni diverse nei tuoi esempi. msdn.microsoft.com/en-us/library/ms187330.aspx
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*/
A parte quello che è ANSI e velocità ecc., C'è una differenza molto importante che conta sempre per me; più di ANSI e velocità. Il numero di bug che ho corretto a causa di questo aspetto importante è grande. Lo cerco continuamente durante le revisioni del codice.
-- 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 è questo lo scopo dello sviluppatore. In quanto sopra, la query è semplice ma ho visto query abbastanza 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 questo è come una bomba che spunta 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 subquery ha restituito più di 1 valore. Ciò non è consentito quando la sottoquery segue =,! =, <, <=,>,> = O quando la sottoquery viene utilizzata come espressione.
Questo è sorprendente e molto importante perché perché vorresti assegnare qualche banale "ultimo elemento nel risultato" al @employeeId
. Con select
te non otterrai mai alcun errore e passerai minuti, ore a eseguire il debug.
Forse stai cercando un singolo ID e SET
ti costringerà a correggere la tua query. Quindi puoi fare qualcosa del tipo:
-- 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, utilizzare:
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.