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 + 1
jeśli jest @Int
uruchamiany jako 0, to kończy się na 2. Może to być bardzo przydatne podczas kolejnych operacji na łańcuchach.
Uważam, że SET
jest to standard ANSI, a SELECT
nie jest. Zwróć także uwagę na inne zachowanie SET
vs. SELECT
w 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 SET
i SELECT
mają 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 select
niemu nigdy nie wystąpi żaden błąd i poświęcisz minuty, godziny debugowania.
Być może szukasz jednego identyfikatora i SET
zmusisz 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.