2009-04-30 3 views
63

मैं एक चयनित फ़ील्ड मान को एक चर से एक चर में कैसे संग्रहीत कर सकता हूं और इसे अद्यतन कथन में उपयोग कर सकता हूं?एक चर के लिए एक परिणाम परिणाम असाइन कैसे करें?

मैं एक SQL सर्वर 2005 T-SQL संग्रहित प्रक्रिया है जो निम्नलिखित करता है लिख रहा हूँ:

  1. चालान आईडी चालान तालिका से की और दुकानों की सूची कर्सर को हो जाता है
  2. यहाँ मेरी प्रक्रिया है

  3. कर्सर से चालान आईडी लायें -> tmp_key चर
  4. foreach tmp_key ग्राहक तालिका से चालान ग्राहक प्राथमिक संपर्क आईडी
  5. अद्यतन करता है ग्राहक के संपर्क पाता है प्राथमिक संपर्क आईडी के साथ कुंजी
  6. पास कर्सर

यहाँ है मेरी कोड:

DECLARE @tmp_key int 
DECLARE @get_invckey cursor 

set @get_invckey = CURSOR FOR 
    select invckey from tarinvoice where confirmtocntctkey is null and tranno like '%115876' 

OPEN @get_invckey 

FETCH NEXT FROM @get_invckey into @tmp_key 

WHILE (@@FETCH_STATUS = 0) 
BEGIN 
    SELECT c.PrimaryCntctKey as PrimaryContactKey 
    from tarcustomer c, tarinvoice i 
    where i.custkey = c.custkey and i.invckey = @tmp_key 

    UPDATE tarinvoice set confirmtocntctkey = PrimaryContactKey where invckey = @tmp_key 
    FETCH NEXT FROM @get_invckey INTO @tmp_key 
END 

CLOSE @get_invckey 
DEALLOCATE @get_invckey 

मैं कैसे PrimaryContactKey स्टोर और निम्न अद्यतन बयान के सेट खंड में इसे फिर से प्रयोग करते हैं? क्या मैं एक कर्सर वैरिएबल बना सकता हूं या एक इंट टाइप के साथ बस एक और स्थानीय चर बना सकता हूं?

+2

नीचे @GilaMonster जवाब के रूप में, इस पूरे ऑपरेशन एक भी अद्यतन बयान (एक "सेट आधारित ऑपरेशन", नहीं एक [टी एसक्यूएल सेट बयान] साथ भ्रमित होने की (https हो सकता है : //msdn.microsoft.com/en-us/library/ms189484.aspx)) जो एक बेहतर तरीका है (तेज निष्पादन, कम ओवरहेड, और काफी कम कोड)। मैं बस इसे इंगित कर रहा हूं क्योंकि प्रश्न और सभी मौजूदा शीर्ष उत्तर एसईटी कथन लिखने के बारे में हैं, लेकिन यह वास्तव में शुरू करने का सबसे अच्छा तरीका नहीं है। – gregmac

उत्तर

40
DECLARE @tmp_key int 
DECLARE @get_invckey cursor 

SET @get_invckey = CURSOR FOR 
    SELECT invckey FROM tarinvoice WHERE confirmtocntctkey IS NULL AND tranno LIKE '%115876' 

OPEN @get_invckey 

FETCH NEXT FROM @get_invckey INTO @tmp_key 

DECLARE @PrimaryContactKey int --or whatever datatype it is 

WHILE (@@FETCH_STATUS = 0) 
BEGIN 
    SELECT @PrimaryContactKey=c.PrimaryCntctKey 
    FROM tarcustomer c, tarinvoice i 
    WHERE i.custkey = c.custkey AND i.invckey = @tmp_key 

    UPDATE tarinvoice SET confirmtocntctkey = @PrimaryContactKey WHERE invckey = @tmp_key 
    FETCH NEXT FROM @get_invckey INTO @tmp_key 
END 

CLOSE @get_invckey 
DEALLOCATE @get_invckey 

संपादित करें:
यह सवाल एक बहुत अधिक कर्षण की तुलना में मैं प्रत्याशित है | हो गया है। ध्यान दें कि मैं अपने उत्तर में कर्सर के उपयोग की वकालत नहीं कर रहा हूं, बल्कि यह दिखा रहा हूं कि प्रश्न के आधार पर मूल्य कैसे असाइन किया जाए।

18

यह

SELECT @PrimaryContactKey = c.PrimaryCntctKey 
FROM tarcustomer c, tarinvoice i 
WHERE i.custkey = c.custkey 
    AND i.invckey = @tmp_key 

UPDATE tarinvoice SET confirmtocntctkey = @PrimaryContactKey 
WHERE invckey = @tmp_key 
FETCH NEXT FROM @get_invckey INTO @tmp_key 

तुम सिर्फ एक मानक TSQL चर के रूप में अपने पाश के बाहर इस चर घोषणा करेंगे की कोशिश करो।

मुझे यह भी ध्यान रखना चाहिए कि यह किसी भी प्रकार के चयन के लिए ऐसा करेगा, न केवल कर्सर से निपटने के दौरान।

13

आपको कर्सर की आवश्यकता क्यों है? कोड के आपके पूरे सेगमेंट को इसके द्वारा प्रतिस्थापित किया जा सकता है, जो बड़ी संख्या में पंक्तियों पर बहुत तेजी से चलाएगा।

UPDATE tarinvoice set confirmtocntctkey = PrimaryCntctKey 
FROM tarinvoice INNER JOIN tarcustomer ON tarinvoice.custkey = tarcustomer.custkey 
WHERE confirmtocntctkey is null and tranno like '%115876' 
+0

क्या कर्सर वास्तव में डूब गए हैं? – phill

+4

वे धीमे हैं। SQL सर्वर सेट-आधारित क्वेरी के लिए अनुकूलित किया गया है। दस लाख बार एक पंक्ति पर काम करने की तुलना में एक प्रश्न में दस लाख पंक्तियों पर काम करना इसके लिए तेज़ है। उस कर्सर के ऊपर वाले ओवरहेड को जोड़ें, और आप सेट-आधारित ऑपरेशंस अपने कर्सर समाधान और मेरी क्वेरी का परीक्षण करें, देखें कि दोनों के निष्पादन के समय क्या हैं, इसके बजाय कर्सर का उपयोग करके प्रमुख प्रदर्शन समस्याओं की मांग कर रहे हैं। – GilaMonster

+0

धन्यवाद आदमी !!!! यह मेरे लिए यह था, मेरे विशिष्ट परिदृश्य के लिए कर्सर को बदलने का तरीका काम करने से भी आसान है। आप एक चैंपियन हैं! –

81

मैं सिर्फ एक ही समस्या और ...

declare @userId uniqueidentifier 
set @userId = (select top 1 UserId from aspnet_Users) 

या भी कम था:

declare @userId uniqueidentifier 
SELECT TOP 1 @userId = UserId FROM aspnet_Users 
+1

हाहा, मुझे यह पसंद है। स्केलर मान असाइन करने के लिए बहुत सरल होना चाहिए। नफरत कर्सर bla3 .. सौभाग्य से googling इस छोटे से जवाब मिला। – CallMeLaNN

+3

मुझे नहीं पता क्योंकि 'set @userId = (aspnet_Users से शीर्ष 1 उपयोगकर्ता आईडी चुनें) '** बिना ब्रैकेट ** **" चयन के करीब गलत वाक्यविन्यास "का कारण बन जाएगा! – CallMeLaNN

+0

यह मंच शीर्ष के लिए उचित दृष्टिकोण दिखाता है: http://www.sqlservercentral.com/Forums/Topic496124-169-1।एएसपीएक्स –

9

आदेश सुरक्षित रूप से एक चर आवंटित करने के लिए आप सेट-चयन का उपयोग करना पड़ में कथन:

SET @PrimaryContactKey = (SELECT c.PrimaryCntctKey 
    FROM tarcustomer c, tarinvoice i 
    WHERE i.custkey = c.custkey 
    AND i.invckey = @tmp_key) 

सुनिश्चित करें कि आप हे एक प्रारंभिक और एक अंतिम संश्लेषण दोनों!

एसईटी-चयन संस्करण एक चर सेट करने का सबसे सुरक्षित तरीका है दो गुना है।

1।चयन कई पोस्ट

क्या होता है यदि निम्नलिखित पोस्ट कई पदों में परिणाम चुनते हैं?

SELECT @PrimaryContactKey = c.PrimaryCntctKey 
FROM tarcustomer c, tarinvoice i 
WHERE i.custkey = c.custkey 
    AND i.invckey = @tmp_key 

@PrimaryContactKey परिणाम में पिछले पोस्ट से मूल्य आवंटित किया जाएगा।

वास्तव में @PrimaryContactKey परिणामस्वरूप प्रति पोस्ट एक मान असाइन किया जाएगा, इसलिए इसके परिणामस्वरूप SELECT-command प्रसंस्करण की अंतिम पोस्ट का मूल्य होगा।

कौन सी पोस्ट "आखिरी" किसी भी क्लस्टर इंडेक्स द्वारा निर्धारित की जाती है या यदि कोई क्लस्टर इंडेक्स का उपयोग नहीं किया जाता है या प्राथमिक कुंजी क्लस्टर किया जाता है, तो "आखिरी" पोस्ट सबसे हाल ही में पोस्ट की जाएगी। यह व्यवहार, सबसे खराब स्थिति परिदृश्य में, तालिका के अनुक्रमण को हर बार बदल दिया जा सकता है।

एक सेट-चयन कथन के साथ आपका चर null पर सेट हो जाएगा।

2. का चयन करें कोई पोस्ट रिटर्न

क्या होता है, जब, कोड के दूसरे संस्करण का उपयोग करता है, तो अपने चयन एक परिणाम बिल्कुल वापस नहीं करता है?

वैरिएबल के मान के विपरीत आपको शून्य नहीं होगा - यह को पिछले मान को बनाए रखेगा!

ऐसा इसलिए, क्योंकि जैसा कि ऊपर कहा गया है, एसक्यूएल चर पद प्रति एक बार करने के लिए एक मूल्य निर्दिष्ट जाएगा - जिसका अर्थ यह चर के साथ कुछ नहीं करेंगे, तो परिणाम की कोई पोस्ट नहीं होता है। इसलिए, वैरिएबल के पास अभी भी वह मान होगा जो आपके द्वारा कथन चलाने से पहले था।

सेट-चयन कथन के साथ मान null होगा।

यह भी देखें: SET versus SELECT when assigning variables?

+0

एर्क सही है और इसे उत्तर के रूप में चिह्नित किया जाना चाहिए था। दूसरा बिंदु मुझे हाल ही में पकड़ा गया है ... – wexman

+0

@wexman: क्यों, धन्यवाद! मेरे पास # 2 के साथ भी मेरे रन-इन्स हैं ... – Erk

+0

मैंने ऊपर दिए गए केस 1 के बाद कोड के साथ बस एक बग हल किया है। मूल कोडर की परवाह नहीं है कि कई पंक्तियों का चयन किया गया था, लेकिन दुर्भाग्यवश एक एमएस एसक्यूएल सर्वर कभी-कभी पंक्तियों को किसी अन्य क्रम में वापस लौटा सकता है, क्योंकि उन्हें ऑप्टिमाइज़ेशन के अलावा किसी अन्य स्पष्ट कारण के लिए डाला गया था ... परिणाम यादृच्छिक और भ्रमित था ... – Erk