Odpowiedzi:
Cytat , który podsumowuje z tego artykułu :
- SET jest standardem ANSI dla przypisywania zmiennych, SELECT nie.
- SET może przypisywać tylko jedną zmienną na raz, SELECT może wykonywać wiele przypisań jednocześnie.
- W przypadku przypisywania z zapytania SET może przypisać tylko wartość skalarną. Jeśli zapytanie zwróci wiele wartości / wierszy, wówczas SET spowoduje błąd. SELECT przypisze jedną z wartości do zmiennej i ukryje fakt, że zwrócono wiele wartości (więc prawdopodobnie nigdy nie dowiesz się, dlaczego coś poszło nie tak - baw się dobrze z rozwiązywaniem problemów)
- Przy przypisywaniu z zapytania, jeśli nie zostanie zwrócona żadna wartość, SET przypisze NULL, gdzie SELECT w ogóle nie wykona przypisania (więc zmienna nie zostanie zmieniona z poprzedniej wartości)
- Jeśli chodzi o różnice prędkości - nie ma bezpośrednich różnic między SET a SELECT. Jednak zdolność SELECT do wykonywania wielu zadań w jednym strzale daje mu niewielką przewagę prędkości nad SET.
SELECT @Int = @Int + 1, @Int = @Int + 1jeśli jest @Inturuchamiany jako 0, to kończy się na 2. Może to być bardzo przydatne podczas kolejnych operacji na łańcuchach.
Uważam, że SETjest to standard ANSI, a SELECTnie jest. Zwróć także uwagę na inne zachowanie SETvs. SELECTw poniższym przykładzie, gdy nie znaleziono wartości.
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'), dostaniesz @var jako null. Podany przykład nie jest tym samym zapytaniem.
(select name from master.sys.tables where name = 'qwerty')dla jednego, a name from master.sys.tables where name = 'qwerty'dla drugiego ... nie widzisz tego?
(select name from master.sys.tables where name = 'qwerty')jest skalarnym podzapytaniem i name from master.sys.tables where name = 'qwerty'jest prostym zapytaniem. Te dwa różne wyrażenia nie powinny dawać takich samych rezultatów, choć wydaje się, że sugerujesz, że powinny. Jeśli próbujesz powiedzieć, że słowa kluczowe SETi SELECTmają różne implementacje, nie powinieneś używać dwóch różnych wyrażeń w swoich przykładach. msdn.microsoft.com/en-us/library/ms187330.aspx
Pisząc zapytania, należy pamiętać o tej różnicy:
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*/
Oprócz tego, że jest to ANSI i prędkość itp., Jest bardzo ważna różnica, która zawsze ma dla mnie znaczenie; więcej niż ANSI i prędkość. Liczba błędów, które usunąłem z powodu tego ważnego przeoczenia, jest duża. Cały czas szukam tego podczas przeglądów kodu.
-- 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;
Prawie zawsze nie tego chce deweloper. W powyższym zapytaniu jest proste, ale widziałem zapytania, które są dość złożone i ustalenie, czy zwróci jedną wartość, czy nie, nie jest banalne. Zapytanie jest często bardziej złożone i przez przypadek zwraca jedną wartość. Podczas testowania programistów wszystko jest w porządku. Ale to jest jak tykająca bomba i spowoduje problemy, gdy zapytanie zwróci wiele wyników. Czemu? Ponieważ po prostu przypisze ostatnią wartość do zmiennej.
Teraz spróbujmy tego samego z SET:
-- Act
set @employeeId = (select e.EmployeeId from dbo.Employee e);
Otrzymasz błąd:
Subquery zwróciło więcej niż 1 wartość. Jest to niedozwolone, gdy podkwerenda występuje po =,! =, <, <=,>,> = Lub gdy podkwerenda jest używana jako wyrażenie.
To zadziwiające i bardzo ważne, ponieważ dlaczego chcesz przypisać trywialny „ostatni wynik w wyniku” do @employeeId. Dzięki selectniemu nigdy nie wystąpi żaden błąd i poświęcisz minuty, godziny debugowania.
Być może szukasz jednego identyfikatora i SETzmusisz Cię do naprawienia zapytania. Dlatego możesz zrobić coś takiego:
-- Act
-- Notice the where clause
set @employeeId = (select e.EmployeeId from dbo.Employee e where e.EmployeeId = 1);
print @employeeId;
Sprzątać
drop table Employee;
Podsumowując, użyj:
SET: Gdy chcesz przypisać pojedynczą wartość do zmiennej, a twoja zmienna dotyczy jednej wartości.SELECT: Gdy chcesz przypisać wiele wartości do zmiennej. Zmienna może być tabelą, tabelą temperatur lub zmienną tabelową itp.