2010-12-17 13 views
9

का उपयोग किए बिना, अल्पविराम से अलग स्ट्रिंग को int में परिवर्तित करें, मैं int की सूची (अल्पविराम से अलग)टी-एसक्यूएल उपयोगकर्ता निर्मित फ़ंक्शन

यानी। 1, 2, 3, 4

मेरे एसपी में। लेकिन मुझे एक त्रुटि मिल रही है क्योंकि सूची एक स्ट्रिंग है, और मैं एक int फ़ील्ड की तुलना कर रहा हूं। उपयोगकर्ता द्वारा बनाए गए फ़ंक्शन का उपयोग किये बिना सूची को int में परिवर्तित करने का कोई तरीका है?

नोट: EmployeeID INT

declare @intArray varchar(200) 

SELECT * 
FROM tbl_Employee 
WHERE employeeID IN (@intArray) 

है त्रुटि है "कनवर्ट नहीं कर सकता प्रकार varchar int करने के लिए"

+0

SQL सर्वर का कौन सा संस्करण? और क्या आप अपने एसपी को कॉल करने वाले कोड को बदलने में सक्षम हैं? –

+0

@ डेमियन एसक्यूएल सर्वर 2005. हाँ, मैं अपने एसपी को कॉल करने वाले कोड को बदलने में सक्षम हूं। – Kukoy

+1

चूहों। 2008 के लिए, मैं टेबल मूल्यवान पैरामीटर का उपयोग करने के लिए बदलने का सुझाव देना चाहूंगा। –

उत्तर

8

आप उस सूची को int में नहीं डालना चाहते हैं, लेकिन इनट्स की सूची में।

इसके लिए कोई कास्ट ऑपरेटर या फ़ंक्शन नहीं है, लेकिन आप इसके आसपास पाने के लिए गतिशील एसक्यूएल का उपयोग कर सकते हैं।

मूल रूप से आप लिखते हैं

EXECUTE('SELECT * FROM tbl_Employee WHERE employeeID IN ('[email protected]+')') 

हालांकि SQL इंजेक्शन हमले के प्रति सचेत रहें!

+3

ओपी चाहता है कि यह करने का एक अच्छा मूल तरीका है। ध्यान रखें कि कर्मचारियों और आईडी की बढ़ती सूची के रूप में, 'IN' वाक्यांश तेजी से अप्रभावी हो जाता है। 2005/2008 में, 'EXISTS' को प्राथमिकता दी जाती है। इसके अलावा, गतिशील एसक्यूएल को कैश नहीं किया जा सकता है, इसलिए निष्पादन कभी भी तेज नहीं होता है क्योंकि यह अन्य कथनों के साथ करता है। – Brad

+0

@ ब्रैड: गतिशील बयान कैश किए गए साथ ही किसी अन्य को भी मिलता है। जब तक आप क्वेरी टेक्स्ट नहीं बदलते, तब तक कैश की गई योजना ली जाती है। बेशक, यदि क्वेरी अक्सर निष्पादित की जाती है तो यहां विभिन्न आईडी-सूचियां एक समस्या होगी। EXISTS को खोजी गई आईडी को स्टोर करने के लिए कुछ (अस्थायी) तालिका की आवश्यकता होगी। यदि आपके पास सूची है (i।ई। एक वेब ऐप से जहां उपयोगकर्ता कुछ कर्मचारियों को चेकबॉक्स के साथ चुन सकता है), आईएन अभी भी आपको सबसे अच्छा विकल्प है। – TToni

+0

मैं मानता हूं कि 'EXISTS' बिल्कुल व्यावहारिक नहीं है, मैं बस यह इंगित करना चाहता था कि यह * पसंदीदा * है यदि तालिका या 'IN' सूची बड़ी है। यह जानना अच्छा है कि एसक्यूएल गतिशील एसक्यूएल (प्रत्येक परिवर्तन के लिए) के लिए कैश योजना करता है। लेकिन मुझे लगता है कि यह कैशिंग काफी हद तक छूट योग्य है क्योंकि क्वेरी अक्सर बदल जाएगी। यदि नहीं, तो आप गतिशील एसक्यूएल का उपयोग क्यों करना चुनेंगे? – Brad

4

आप कन्वर्ट करने के लिए न केवल एक stringint करने की कोशिश कर रहे हैं, लेकिन कईint रों में में। क्या आप उम्मीद करते हैं कि आपके SELECT सरणी में सूचीबद्ध सभी कर्मचारी के साथ और आईडी वापस कर देगा?

मुझे एहसास है कि आप बिना किसी फ़ंक्शन के करना चाहते थे। हालांकि, इस तरह मैं वर्तमान में यह करता हूं और यह बहुत अच्छा काम करता है। मेरे उत्तर से आप क्या करेंगे ले लो।

यह कोड while लूप का उपयोग करता है जो कि यदि आप SQL 2005/2008 में हैं तो रिकर्सिव सीटीई में सुधार किया जा सकता है। आप फ़ंक्शन के आउटपुट को उस तालिका के रूप में उपयोग कर सकते हैं जो आपको INNER JOIN है जिससे आपको बहुत तेज़ी से फ़िल्टर करने की अनुमति मिल जाएगी।

/* 
************************************************************************************************************************ 
    Name:   ConvertDelimitedListIntoTable 
    Description: Converts a list of delimited values into a table for use like a dynamic IN statment 

    Modification History 
    Date  Author   Description 
    ========== ============ ==================================== 
    2009-01-31 B. Williams  Initial Creation 

************************************************************************************************************************ 
*/ 
ALTER FUNCTION [dbo].[ConvertDelimitedListIntoTable] (
    @list NVARCHAR(MAX) ,@delimiter CHAR(1)) 
RETURNS @table TABLE ( 
    item VARCHAR(255) NOT NULL) 
AS 
    BEGIN 
     DECLARE @pos INT ,@nextpos INT ,@valuelen INT 

     SELECT @pos = 0 ,@nextpos = 1 

     WHILE @nextpos > 0 
      BEGIN 
       SELECT @nextpos = CHARINDEX(@delimiter,@list,@pos + 1) 
       SELECT @valuelen = CASE WHEN @nextpos > 0 THEN @nextpos 
             ELSE LEN(@list) + 1 
            END - @pos - 1 
       INSERT @table (item) 
       VALUES (CONVERT(INT,SUBSTRING(@list,@pos + 1,@valuelen))) 
       SELECT @pos = @nextpos 

      END 

     DELETE FROM @table 
     WHERE item = '' 

     RETURN 
    END 

उपयोग:

DECLARE @intArray varchar(200) 

SELECT * 
FROM tbl_Employee e 
     INNER JOIN dbo.ConvertDelimitedListIntoTable(@intArray,',') arr 
       ON e.EmployeeID = arr.Item 

वहाँ भी एक त्वरित तरीका एक tally तालिका के साथ यह करने के लिए हो सकता है।

+0

यह बढ़िया है, धन्यवाद! –

+0

संग्रहित प्रक्रिया में पहला समाधान कार्य करने के लिए प्रबंधित नहीं किया गया था। इस के लिए धन्यवाद! –

संबंधित मुद्दे