चरों को असाइन करते समय बनाम चयन करें?


जवाबों:


412

उद्धरण , जो इस लेख से सारांशित करता है :

  1. SET वेरिएबल असाइनमेंट के लिए ANSI मानक है, SELECT नहीं है।
  2. SET एक समय में केवल एक ही चर असाइन कर सकता है, SELECT एक ही बार में कई कार्य कर सकता है।
  3. यदि किसी क्वेरी से असाइन किया जाता है, तो SET केवल एक स्केलर मान प्रदान कर सकता है। यदि क्वेरी कई मान / पंक्तियाँ लौटाती है तो SET एक त्रुटि देगा। चयन चर में से किसी एक मान को असाइन करेगा और इस तथ्य को छिपाएगा कि कई मान लौटाए गए हैं (इसलिए आपको कभी पता नहीं चलेगा कि कहीं और गलत क्यों हो रहा है - मजेदार समस्या निवारण है)
  4. जब क्वेरी से असाइन किया जाता है यदि कोई मान नहीं लौटाया जाता है, तो SET NULL को असाइन करेगा, जहां SELECT असाइनमेंट बिल्कुल नहीं करेगा (इसलिए चर को उसके पिछले मूल्य से नहीं बदला जाएगा)
  5. जहाँ तक गति अंतर - SET और SELECT के बीच कोई प्रत्यक्ष अंतर नहीं हैं। हालाँकि एक शॉट में कई असाइनमेंट करने की सेलेक्ट की क्षमता इसे SET पर थोड़ी गति का लाभ देती है।

3
मैंने डाउनवोट नहीं किया, लेकिन निम्नलिखित बिल्कुल सही नहीं है: "जहां तक ​​गति अंतर - SET और SELECT के बीच कोई प्रत्यक्ष अंतर नहीं हैं"। यदि आप एक slect में कई मान निर्दिष्ट करते हैं, तो यह बहुत तेज़ी से हो सकता है जो maultiple सेट के माध्यम से होता है। Google "एक सेलेक्ट के साथ कई वेरिएबल्स को असाइन करता है तेजी से काम करता है"
AK

14
@AlexKuznetsov: वाक्य बाद में बिल्कुल यही कहता है।
OMG पॉनीज़

3
@OMG पॉनीज़: यह 10 गुना तेज या अधिक हो सकता है, इसलिए मुझे यकीन नहीं है कि यह "मामूली गति लाभ" है।
एके

2
विशेष रूप से जब एक लूप का उपयोग करते समय, मैंने एक-चयन बनाम कई-सेट का उपयोग करके अपने सभी चर को फिर से शुरू / पुन: प्रारंभ करके विशाल प्रदर्शन लाभ देखा है। मैं अपने Variable-Logic को एक सिलेक्ट में सभी में एक साथ भी चला सकता हूं: उदाहरण:, SELECT @Int = @Int + 1, @Int = @Int + 1यदि @Int0 के रूप में शुरू किया गया है, तो यह 2 के रूप में समाप्त होता है। क्रमिक स्ट्रिंग-जोड़तोड़ करते समय यह बहुत उपयोगी हो सकता है।
माइकटेवी

प्रदर्शन अंतर के बारे में दिलचस्प चर्चा। यदि चयन के माध्यम से कई मान सेट करना तेज़ है (कोड और निष्पादित करने के लिए) तो बिंदु 4 से बचने के लिए एक विफल तरीका है (यदि क्वेरी वापस आती है तो आपके परिवर्तनीय मान को बदलने में विफल है) स्पष्ट रूप से चयन करने से पहले अपने चर को शून्य में सेट करना है। एक बार जब आप यह बता देते हैं कि प्रदर्शन के लिए दोनों की तुलना कैसे की जाती है? (साइड नोट: मुझे यह समझ में नहीं आ रहा है कि क्वेरी में अशक्त होने की स्थिति में अपने वैरिएबल को सेट करने के लिए चयन न करें। आप कब ऐसा करना चाहेंगे?)
youcantryreachingme

155

मेरा मानना SETहै कि एएनएसआई मानक है जबकि SELECTऐसा नहीं है। मूल्य नहीं मिलने पर नीचे के उदाहरण में SETबनाम के विभिन्न व्यवहार पर भी ध्यान दें 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 समझने, जाँचने, खेलने, याद करने के लिए एक बार दौड़ना बेहतर है कि सिर्फ पढ़ने के लिए लेकिन अन्य उत्तर सिर्फ पाठ हैं
Gennady Vanin Геннадий Ванин

4
यदि आप वास्तव में उपयोग select @var = (select name from master.sys.tables where name = 'qwerty')करते हैं तो आपको null के रूप में @var मिलेगा। आप जो उदाहरण दे रहे हैं, वही क्वेरी नहीं है।
ज़ैक

4
आपके पास (select name from master.sys.tables where name = 'qwerty')एक के लिए है, और name from master.sys.tables where name = 'qwerty'दूसरे के लिए ... क्या आपको वह दिखाई नहीं देता?
जक

4
@Zack: मैं जो डेमो करने का प्रयास कर रहा हूं, उसके लिए प्रत्येक सही वाक्यविन्यास है; SET बनाम SELECT का उपयोग करने के बीच का अंतर एक वैरिएबल के लिए एक मान निर्दिष्ट करने के लिए जब अंतर्निहित क्वेरी कोई परिणाम नहीं देता है।
जो स्टेफनेली

5
(select name from master.sys.tables where name = 'qwerty')एक अदिश उपश्रेणी है, और name from master.sys.tables where name = 'qwerty'एक सरल क्वेरी है। दो अलग-अलग अभिव्यक्तियों को एक ही परिणाम नहीं माना जाता है, हालांकि ऐसा लगता है कि आप इसका अर्थ लगा रहे हैं कि उन्हें होना चाहिए। यदि आप यह कहना चाह रहे हैं कि कीवर्ड्स SETऔर SELECTकार्यान्वयन अलग-अलग हैं, तो आपको अपने उदाहरणों में दो अलग-अलग अभिव्यक्तियों का उपयोग नहीं करना चाहिए । msdn.microsoft.com/en-us/library/ms187330.aspx
जैक

27

प्रश्न लिखते समय, इस अंतर को ध्यान में रखा जाना चाहिए:

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

बहुत अच्छा,
रसीला

8

एक एएनएसआई और गति आदि होने के अलावा, एक बहुत महत्वपूर्ण अंतर है जो हमेशा मेरे लिए मायने रखता है; ANSI और गति से अधिक। इस महत्वपूर्ण अनदेखी के कारण मेरे द्वारा तय किए गए बग की संख्या बड़ी है। मैं हर समय कोड समीक्षा के दौरान इसकी तलाश करता हूं।

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

लगभग हमेशा, वह नहीं है जो डेवलपर का इरादा है। उपरोक्त में, क्वेरी सीधे आगे है लेकिन मैंने ऐसे प्रश्नों को देखा है जो काफी जटिल हैं और यह पता लगा रहे हैं कि क्या यह एकल मान लौटाएगा या नहीं, यह तुच्छ नहीं है। क्वेरी अक्सर इससे अधिक जटिल होती है और संयोग से यह एकल मान लौटा रही है। डेवलपर परीक्षण के दौरान सब ठीक है। लेकिन यह एक टिक करने वाले बम की तरह है और जब कई परिणाम आएंगे तो यह समस्या पैदा करेगा। क्यों? क्योंकि यह केवल चर को अंतिम मान देगा।

आइए अब उसी चीज को आजमाते हैं SET:

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

आपको एक त्रुटि प्राप्त होगी:

सबक्वेरी 1 से अधिक मूल्य पर लौटी। यह अनुमति नहीं है जब उप-वर्ग =,! =, <, <=,>,> = या जब उप-अभिव्यक्ति का उपयोग किया जाता है।

यह आश्चर्यजनक और बहुत महत्वपूर्ण है क्योंकि आप कुछ तुच्छ "अंतिम आइटम को परिणाम में" क्यों असाइन करना चाहते हैं @employeeId। आपके साथ selectकभी कोई त्रुटि नहीं होगी और आप मिनट, घंटे डिबगिंग खर्च करेंगे।

शायद, आप एक एकल आईडी की तलाश कर रहे हैं और SETआपको अपनी क्वेरी को ठीक करने के लिए मजबूर करेंगे। इस प्रकार आप कुछ ऐसा कर सकते हैं:

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

साफ - सफाई

drop table Employee;

निष्कर्ष में, उपयोग करें:

  • SET: जब आप किसी वैरिएबल को सिंगल वैल्यू असाइन करना चाहते हैं और आपका वैरिएबल सिंगल वैल्यू के लिए है।
  • SELECT: जब आप एक चर के लिए कई मान निर्दिष्ट करना चाहते हैं। चर एक तालिका, अस्थायी तालिका या तालिका चर आदि हो सकता है।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.