2013-03-23 3 views
10

मैं की तरह अल्पविराम के द्वारा अलग आईडी की एक सूची है:SQL सर्वर 2005 में अल्पविराम से अलग NVARCHAR तालिका रिकॉर्ड में कनवर्ट करने के लिए कैसे?

1,17,25,44,46,67,88 

मैं उनकी तरह

#tempTable 

number_ 
-------- 
1 
17 
25 
44 
46 
67 
88 

(अस्थायी तालिका में) एक मेज रिकॉर्ड के कनवर्ट करना चाहते हैं यह एक समारोह के साथ संभव है, एक टेबल-मूल्यवान एक?

मुझे यह क्यों चाहिए? मैं के रूप में की तरह एक और मेज (रों) के साथ INNER JOIN खंड (संग्रहीत प्रक्रिया में) के लिए उपयोग करना चाहते हैं:

SELECT a,b,c FROM T1 
INNER JOIN functionNameWhichReturnsTable 
ON functionNameWhichReturnsTable.number_ = T1.a 

मैं IN उपयोग नहीं कर सकते, क्योंकि मैं संग्रहीत प्रक्रिया किस प्रकार NVARCHAR की एक पैरामीटर स्वीकार करता है का उपयोग करेगा। वह पैरामीटर आईडी की सूची प्रदान करेगा।

आप

+0

संभावित डुप्लिकेट [व्यक्तिगत पंक्तियों में कॉमा सेपरेटेड स्ट्रिंग को चालू करना] (http://stackoverflow.com/que स्टेन्स/54 9 3510/टर्न-ए-कॉमा से अलग-स्ट्रिंग-इन-व्यक्तिगत-पंक्तियां) –

+0

[एसक्यूएल में स्प्लिट स्ट्रिंग] के संभावित डुप्लिकेट (http://stackoverflow.com/questions/2647/split-string-in-sql) –

उत्तर

18

separate comma separated values and store in table in sql server की संभावित डुप्लिकेट धन्यवाद। अन्य तरीके से आवश्यकता XML का उपयोग

CREATE FUNCTION [dbo].[ufn_CSVToTable] (@StringInput VARCHAR(8000), @Delimiter nvarchar(1)) 
RETURNS @OutputTable TABLE ([String] VARCHAR(10)) 
AS 
BEGIN 

    DECLARE @String VARCHAR(10) 

    WHILE LEN(@StringInput) > 0 
    BEGIN 
     SET @String  = LEFT(@StringInput, 
           ISNULL(NULLIF(CHARINDEX(@Delimiter, @StringInput) - 1, -1), 
           LEN(@StringInput))) 
     SET @StringInput = SUBSTRING(@StringInput, 
            ISNULL(NULLIF(CHARINDEX(@Delimiter, @StringInput), 0), 
            LEN(@StringInput)) + 1, LEN(@StringInput)) 

     INSERT INTO @OutputTable ([String]) 
     VALUES (@String) 
    END 

    RETURN 
END 
GO 

चेक:

Comma-Delimited Value to Table से एक सटीक एक करने का प्रयास करें

DECLARE @param NVARCHAR(MAX) 
SET @param = '1:0,2:1,3:1,4:0' 

SELECT 
    Split.a.value('.', 'VARCHAR(100)') AS CVS 
FROM 
(
    SELECT CAST ('<M>' + REPLACE(@param, ',', '</M><M>') + '</M>' AS XML) AS CVS 
) AS A CROSS APPLY CVS.nodes ('/M') AS Split(a) 
+0

एक्सएमएल विभाजन लूप एक से 3 गुना धीमी है! –

+0

एक्सएमएल स्प्लिट अधिक तेज़ होगा यदि आपके पास अल्पविराम से अलग स्ट्रिंग में हजारों मान हैं यानी @param – Gurunadh

2

विधि मैंने पाया एक समारोह या एक्सएमएल चाल जरूरत नहीं है।

असल में आप स्ट्रिंग को अस्थायी तालिका के लिए एक एकल सम्मिलन कथन में बदल देते हैं।
जो आगे प्रसंस्करण के लिए उपयोग किया जा सकता है।

IF OBJECT_ID('tempdb..#tempTable') IS NOT NULL DROP TABLE #tempTable; 
CREATE TABLE #tempTable (number int); 

DECLARE @TEXT varchar(max) = '1,17,25,44,46,67,88'; 

DECLARE @InsertStatement varchar(max) = 'insert into #tempTable values ('+REPLACE(@TEXT,',','),(')+');'; 
EXEC (@InsertStatement); 

SELECT * FROM #tempTable; 

यह विधि 1000 मानों के लिए उपयोग योग्य है।
क्योंकि 1000 पंक्ति मान अभिव्यक्ति की अधिकतम सीमा है।
या @InsertStatement के लिए वर्कर की सीमा तक पहुंच गई है।

इसके अलावा, स्टुअर्ट एन्सवर्थ ने बताया।
चूंकि यह विधि EXEC का उपयोग करती है, कोड इंजेक्शन से सावधान रहें और असत्यापित उपयोगकर्ता इनपुट के आधार पर तारों के लिए इसका उपयोग न करें।

+0

इस लाइन को आजमाएं: DECLARE @TEXT वर्कर (अधिकतम) = '1,17,25,44,46 , 67,88); #tempTable से हटाएं (1 = 1 '; इस विधि के साथ एसक्यूएल इंजेक्शन संभव है, हालांकि संभव नहीं है। –

+0

मुझे खेद है; मुझे लगता है कि आपको गलत समझा जाता है। मैंने एक टेक्स्ट में एक डिलीट स्टेटमेंट डाला स्ट्रिंग, जो आपके निष्पादन कथन द्वारा निष्पादित की जाएगी। यह एसक्यूएल इंजेक्शन का क्लासिक रूप है; पर्याप्त विशेषाधिकार के साथ, कोई भी सभी प्रकार की शरारत कर सकता है (जैसे डेटाबेस छोड़ना, उपयोगकर्ताओं को बनाना) ... –

+0

फिर से, यह संभावना नहीं है, लेकिन यह बचने के लिए एक डिज़ाइन पैटर्न है। –

0

जवाब को पूरा करने, आप भी एकाधिक स्तंभों में एकाधिक मान संग्रहीत करने के लिए सीएसवी स्ट्रिंग इस्तेमाल कर सकते हैं:

--input sql text 
declare @text_IN varchar(max) ='text1, text1.2, text1.3, 1, 2010-01-01\r\n text2, text2.2, text2.3, 2, 2016-01-01' 

स्प्लिट पंक्तियों में csv फ़ाइल: स्तंभों में

declare @temptable table (csvRow varchar(max))  
declare @DelimiterInit varchar(4) = '\r\n' 
declare @Delimiter varchar(1) = '|' 
declare @idx int  
declare @slice varchar(max)  

set @text_IN = REPLACE(@text_IN,@DelimiterInit,@Delimiter) 


select @idx = 1  
    if len(@text_IN)<1 or @text_IN is null return  

while @idx!= 0  
begin  
    set @idx = charindex(@Delimiter,@text_IN)  
    if @idx!=0  
     set @slice = left(@text_IN,@idx - 1)  
    else  
     set @slice = @text_IN 

    if(len(@slice)>0) 
     insert into @temptable(csvRow) values(@slice)  

    set @text_IN = right(@text_IN,len(@text_IN) - @idx)  
    if len(@text_IN) = 0 break  
end 

स्प्लिट पंक्तियों:

;WITH XMLTable (xmlTag) 
AS 
(
    SELECT CONVERT(XML,'<CSV><champ>' + REPLACE(csvRow,',', '</champ><champ>') + '</champ></CSV>') AS xmlTag 
    FROM @temptable 
) 

SELECT RTRIM(LTRIM(xmlTag.value('/CSV[1]/champ[1]','varchar(max)'))) AS Column1,  
     RTRIM(LTRIM(xmlTag.value('/CSV[1]/champ[2]','varchar(max)'))) AS Column2, 
     RTRIM(LTRIM(xmlTag.value('/CSV[1]/champ[3]','varchar(max)'))) AS Column3,  
     RTRIM(LTRIM(xmlTag.value('/CSV[1]/champ[4]','int'))) AS Column4, 
     RTRIM(LTRIM(xmlTag.value('/CSV[1]/champ[5]','datetime'))) AS Column5 
FROM XMLTable 
संबंधित मुद्दे