Değişkenleri atarken SET'e karşı SEÇ?


Yanıtlar:


412

Bu makaleden özetleyen alıntı :

  1. SET, değişken ataması için ANSI standardıdır, SELECT değildir.
  2. SET aynı anda yalnızca bir değişken atayabilir, SELECT aynı anda birden fazla atama yapabilir.
  3. Bir sorgudan atama yapılıyorsa, SET sadece skaler bir değer atayabilir. Sorgu birden çok değer / satır döndürürse SET bir hata oluşturur. SELECT, değişkenlerden birine değişkenlerden birini atar ve birden çok değerin döndürüldüğü gerçeğini gizler (bu nedenle, başka bir yerde neden bir şeyin yanlış gittiğini asla bilemezsiniz - bu sorun giderme işleminde eğlenin)
  4. Döndürülen değer yoksa bir sorgudan atama yaparken SET, NULL atayacaktır; burada SELECT atamayı hiç yapmayacaktır (bu nedenle değişken önceki değerinden değiştirilmeyecektir)
  5. Hız farkları kadar - SET ve SELECT arasında doğrudan fark yoktur. Ancak SELECT'in bir çekimde birden fazla atama yapabilmesi, SET'e göre hafif bir hız avantajı sağlar.

3
Ben aşağı itmedim, ancak aşağıdakiler tam olarak doğru değil: "Hız farklılıkları kadar - SET ve SELECT arasında doğrudan bir fark yoktur". Bir slaytta birden çok değer atarsanız, bu, birden çok kümeden daha hızlı olabilir. Google up "Bir SELECT ile birden fazla değişken atamak daha hızlı çalışıyor"
AK

14
@AlexKuznetsov: Daha sonra cümle tam olarak bunu söylüyor.
OMG Ponies

3
@OMG Ponies: 10 kat daha hızlı veya daha fazla olabilir, bu yüzden "hafif hız avantajı" olduğundan emin değilim.
AK

2
Özellikle While-Loop kullanırken tüm değişkenlerimi one-Select vs. Ayrıca, Değişken-Mantıkımı bir Seferde de bir seferde çalıştırabilirim: Örnek: 0 olarak SELECT @Int = @Int + 1, @Int = @Int + 1başlarsa @Int, 2 olarak biter. Bu, ardışık dize manipülasyonları yaparken çok yararlı olabilir.
MikeTeeVee

Performans farkı hakkında ilginç bir tartışma. Seçme yoluyla birden çok değer ayarlamak daha hızlıysa (kodlamak ve yürütmek için), o zaman nokta 4'ü (sorgu null döndürürse değişken değeriniz değişmezse) seçimden önce değişkeninizi açıkça null olarak ayarlamaktır. Bunu hesaba kattığınızda, ikisi performans ile nasıl karşılaştırılır? (Yan not: Bir sorgu null döndürdüğü durumda değişkeninizi null olarak ayarlamamanın
seçiminin mantığını anlamıyorum

155

SETANSI standardı olduğuna inanıyorum , oysa SELECTdeğil. Ayrıca , bir değer bulunamadığında aşağıdaki örnekte SETvs.'nin farklı davranışına dikkat edin SELECT.

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' */

4
+1 Sadece okumak için anlamak, kontrol etmek, oynamak, ezberlemek için bir kez çalıştırmak daha iyidir, ancak diğer cevaplar sadece metindir
Gennady Vanin Геннадий Ванин

4
Eğer gerçekten kullandıysanız select @var = (select name from master.sys.tables where name = 'qwerty')@var null olarak alınır. Verdiğiniz örnek aynı sorgu değil.
Zack

4
You have (select name from master.sys.tables where name = 'qwerty')biri için ve name from master.sys.tables where name = 'qwerty'diğeri için ... bunu görmüyorum?
Zack

4
@Zack: Her biri demo için denediğim şey için doğru sözdizimidir; temel sorgu hiçbir sonuç döndürmediğinde bir değişkene değer atamak için SET vs. SELECT kullanma arasındaki fark.
Joe Stefanelli

5
(select name from master.sys.tables where name = 'qwerty')skaler bir alt name from master.sys.tables where name = 'qwerty'sorgudur ve basit bir sorgudur. İki farklı ifadenin aynı sonuçları üretmesi beklenmiyor, ancak öyle olması gerektiğini ima ediyorsunuz. SETVe SELECTanahtar kelimelerin farklı uygulamaları olduğunu söylemeye çalışıyorsanız , örneklerinizde iki farklı ifade kullanmamalısınız . msdn.microsoft.com/tr-tr/library/ms187330.aspx
Zack

27

Sorgu yazarken, bu fark göz önünde bulundurulmalıdır:

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*/

çok güzel, kısa ve öz
SimplyInk

8

Birinin ANSI ve hız vs. olmasının yanı sıra, benim için her zaman önemli olan çok önemli bir fark var; ANSI ve hızdan daha fazlası. Bu önemli göz ardı nedeniyle sabitlediğim hata sayısı çok fazla. Ben her zaman kod gözden geçirme sırasında bak.

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

Neredeyse her zaman, geliştiricinin istediği bu değildir. Yukarıda, sorgu düz ileri ama oldukça karmaşık sorguları gördüm ve tek bir değer döndürüp dönmeyeceğini bulmak önemsiz değil. Sorgu genellikle bundan daha karmaşıktır ve şans eseri tek bir değer döndürmektedir. Geliştirici testi sırasında her şey yolunda. Ancak bu bir tik tak bomba gibidir ve sorgu birden fazla sonuç döndürdüğünde sorunlara neden olur. Neden? Çünkü değişkene sadece son değeri atayacaktır.

Şimdi aynı şeyi deneyelim SET:

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

Bir hata mesajı alırsınız:

Alt sorgu 1'den fazla değer döndürdü. Alt sorgu =,! =, <, <=,>,> = Öğesini izlediğinde veya alt sorgu ifade olarak kullanıldığında buna izin verilmez.

Bu şaşırtıcı ve çok önemli, çünkü neden önemsiz bir "sonuçta son öğe" atamak istersiniz @employeeId. İle selectherhangi bir hatayı asla ve dakika geçirecek, saat ayıklama.

Belki de tek bir kimlik arıyorsunuz ve SETsorgunuzu düzeltmeye zorlayacaksınız. Böylece şöyle bir şey yapabilirsiniz:

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

Temizlemek

drop table Employee;

Sonuç olarak, şunları kullanın:

  • SET: Bir değişkene tek bir değer atamak istediğinizde ve değişkeniniz tek bir değer içindir.
  • SELECT: Bir değişkene birden çok değer atamak istediğinizde. Değişken bir tablo, geçici tablo veya tablo değişkeni vb. Olabilir.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.