अलग-अलग पंक्तियों में एक कोमा सेपरेटेड स्ट्रिंग को चालू करना


234

मेरे पास इस तरह एक SQL टेबल है:

| SomeID         | OtherID     | Data
+----------------+-------------+-------------------
| abcdef-.....   | cdef123-... | 18,20,22
| abcdef-.....   | 4554a24-... | 17,19
| 987654-.....   | 12324a2-... | 13,19,20

क्या कोई क्वेरी है जहां मैं एक क्वेरी कर सकता हूं जैसे SELECT OtherID, SplitData WHERE SomeID = 'abcdef-.......'कि अलग-अलग पंक्तियों को लौटाता है, जैसे:

| OtherID     | SplitData
+-------------+-------------------
| cdef123-... | 18
| cdef123-... | 20
| cdef123-... | 22
| 4554a24-... | 17
| 4554a24-... | 19

मूल रूप से अल्पविराम में मेरे डेटा को अलग-अलग पंक्तियों में विभाजित करें?

मुझे पता है कि comma-separatedएक संबंधपरक डेटाबेस में एक स्ट्रिंग संग्रहीत करना गूंगा लगता है, लेकिन उपभोक्ता एप्लिकेशन में सामान्य उपयोग का मामला वास्तव में मददगार होता है।

मैं एप्लिकेशन में विभाजन नहीं करना चाहता क्योंकि मुझे पेजिंग की आवश्यकता है, इसलिए मैं पूरे ऐप को फिर से अपडेट करने से पहले विकल्पों का पता लगाना चाहता था।

यह SQL Server 2008(गैर-आर 2) है।


इन्हें भी देखें: periscopedata.com/blog/…
रिक जेम्स

जवाबों:


265

आप SQL सर्वर से अद्भुत पुनरावर्ती कार्यों का उपयोग कर सकते हैं:


नमूना तालिका:

CREATE TABLE Testdata
(
    SomeID INT,
    OtherID INT,
    String VARCHAR(MAX)
)

INSERT Testdata SELECT 1,  9, '18,20,22'
INSERT Testdata SELECT 2,  8, '17,19'
INSERT Testdata SELECT 3,  7, '13,19,20'
INSERT Testdata SELECT 4,  6, ''
INSERT Testdata SELECT 9, 11, '1,2,3,4'

पूछताछ

;WITH tmp(SomeID, OtherID, DataItem, String) AS
(
    SELECT
        SomeID,
        OtherID,
        LEFT(String, CHARINDEX(',', String + ',') - 1),
        STUFF(String, 1, CHARINDEX(',', String + ','), '')
    FROM Testdata
    UNION all

    SELECT
        SomeID,
        OtherID,
        LEFT(String, CHARINDEX(',', String + ',') - 1),
        STUFF(String, 1, CHARINDEX(',', String + ','), '')
    FROM tmp
    WHERE
        String > ''
)

SELECT
    SomeID,
    OtherID,
    DataItem
FROM tmp
ORDER BY SomeID
-- OPTION (maxrecursion 0)
-- normally recursion is limited to 100. If you know you have very long
-- strings, uncomment the option

उत्पादन

 SomeID | OtherID | DataItem 
--------+---------+----------
 1      | 9       | 18       
 1      | 9       | 20       
 1      | 9       | 22       
 2      | 8       | 17       
 2      | 8       | 19       
 3      | 7       | 13       
 3      | 7       | 19       
 3      | 7       | 20       
 4      | 6       |          
 9      | 11      | 1        
 9      | 11      | 2        
 9      | 11      | 3        
 9      | 11      | 4        

1
कोड काम नहीं करता है, तो परिवर्तन कॉलम के डेटा प्रकार Dataसे varchar(max)करने के लिए varchar(4000), उदाहरण के लिए create table Testdata(SomeID int, OtherID int, Data varchar(4000))?
ca9163d9

4
@ इस कारण हो सकता है क्योंकि UNION से पहले और बाद के सभी भाग LEFT फ़ंक्शन से विभिन्न प्रकारों को लौटाते हैं। व्यक्तिगत रूप से मैं नहीं देखता कि आप 4000 में पहुंचने के बाद मैक्स पर क्यों नहीं
कूदेंगे

मूल्यों के एक बड़े समूह के लिए, यह सीटीई के लिए पुनरावृत्ति की सीमा से आगे निकल सकता है।
dsz

3
@dsz यह है कि जब आप उपयोग करते हैंOPTION (maxrecursion 0)
रिचर्ड द किवी

14
LEFT फ़ंक्शन को काम करने के लिए CAST की आवश्यकता हो सकती है .... उदाहरण के लिए LEFT (CAST (डेटा AS VARCHAR (MAX)) ....
smoore4

141

अंत में, SQL Server 2016 के साथ प्रतीक्षा खत्म हो गई है । उन्होंने स्प्लिट स्ट्रिंग फंक्शन पेश किया है STRING_SPLIT:

select OtherID, cs.Value --SplitData
from yourtable
cross apply STRING_SPLIT (Data, ',') cs

एक्सएमएल, टैली टेबल, जबकि लूप, आदि जैसे स्ट्रिंग को विभाजित करने के अन्य सभी तरीकों को इस STRING_SPLITफ़ंक्शन द्वारा उड़ा दिया गया है ।

यहां प्रदर्शन तुलना के साथ एक उत्कृष्ट लेख है: प्रदर्शन आश्चर्य और अनुमान: STRING_SPLIT

पुराने संस्करणों के लिए, यहां टैली टेबल का उपयोग करना एक विभाजन स्ट्रिंग फ़ंक्शन (सर्वोत्तम संभव दृष्टिकोण) है

CREATE FUNCTION [dbo].[DelimitedSplit8K]
        (@pString VARCHAR(8000), @pDelimiter CHAR(1))
RETURNS TABLE WITH SCHEMABINDING AS
 RETURN
--===== "Inline" CTE Driven "Tally Table" produces values from 0 up to 10,000...
     -- enough to cover NVARCHAR(4000)
  WITH E1(N) AS (
                 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
                 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
                 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
                ),                          --10E+1 or 10 rows
       E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
       E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
 cteTally(N) AS (--==== This provides the "base" CTE and limits the number of rows right up front
                     -- for both a performance gain and prevention of accidental "overruns"
                 SELECT TOP (ISNULL(DATALENGTH(@pString),0)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
                ),
cteStart(N1) AS (--==== This returns N+1 (starting position of each "element" just once for each delimiter)
                 SELECT 1 UNION ALL
                 SELECT t.N+1 FROM cteTally t WHERE SUBSTRING(@pString,t.N,1) = @pDelimiter
                ),
cteLen(N1,L1) AS(--==== Return start and length (for use in substring)
                 SELECT s.N1,
                        ISNULL(NULLIF(CHARINDEX(@pDelimiter,@pString,s.N1),0)-s.N1,8000)
                   FROM cteStart s
                )
--===== Do the actual split. The ISNULL/NULLIF combo handles the length for the final element when no delimiter is found.
 SELECT ItemNumber = ROW_NUMBER() OVER(ORDER BY l.N1),
        Item       = SUBSTRING(@pString, l.N1, l.L1)
   FROM cteLen l
;

टैली ओह से संदर्भित ! एक बेहतर SQL 8K "CSV फाड़नेवाला" समारोह


9
बहुत महत्वपूर्ण उत्तर
सैयद मो। कमरुज्जमाँ

यदि केवल सर्वर SQL Server 2016 पर था, तो मैं STRING_SPLIT का उपयोग करूंगा! आपके द्वारा लिंक किए गए पृष्ठ के अनुसार BTW, फ़ील्ड नाम यह आउटपुट है value, नहीं SplitData
स्टीवर्ट

89

इसे देखो

 SELECT A.OtherID,  
     Split.a.value('.', 'VARCHAR(100)') AS Data  
 FROM  
 (
     SELECT OtherID,  
         CAST ('<M>' + REPLACE(Data, ',', '</M><M>') + '</M>' AS XML) AS Data  
     FROM  Table1
 ) AS A CROSS APPLY Data.nodes ('/M') AS Split(a); 

8
इस दृष्टिकोण का उपयोग करते समय आपको यह सुनिश्चित करना होगा कि आपके किसी भी मान में कुछ भी नहीं है जो अवैध XML होगा
user1151923

यह भी खूब रही। क्या मैं आपसे पूछ सकता हूं कि मैं कैसे फिर से लिखूंगा कि अगर मैं चाहता था कि नया कॉलम केवल मेरे विभाजन स्ट्रिंग से पहला चरित्र दिखाए?
नियंत्रण

यह पूरी तरह से काम किया, धन्यवाद! मुझे VARCHAR की सीमा को अपडेट करना था, लेकिन इसके बाद यह सही काम करता था।
chazbot7

मुझे आपको यह बताना होगा कि यह विधि "लवलील" है (प्यार को महसूस करें?) को "एक्सएमएल स्प्लिटर मेथड" कहा जाता है और यह लगभग लूप या पुनरावर्ती सीटीई जितना ही धीमा है। मैं दृढ़ता से सलाह देता हूं कि आप हर समय इससे बचें। इसके बजाय DelimitedSplit8K का उपयोग करें। यह 2016 में स्प्लिट_स्ट्रिंग () फ़ंक्शन या एक अच्छी तरह से लिखित सीएलआर को छोड़कर सब कुछ के दरवाजे बंद कर देता है।
जेफ मोदन

20
select t.OtherID,x.Kod
    from testData t
    cross apply (select Code from dbo.Split(t.Data,',') ) x

3
ठीक वैसा ही है जैसा मैं था, और कई अन्य उदाहरणों की तुलना में पढ़ना आसान है (बशर्ते कि सीमांकित स्ट्रिंग विभाजन के लिए डीबी में पहले से ही एक फ़ंक्शन है)। जैसा कि कोई पहले से परिचित नहीं है CROSS APPLY, यह थोड़े उपयोगी है!
टोब्रियांड

मैं इस हिस्से को नहीं समझ सका (dbo.Split (t.Data, ',') से कोड का चयन करें)? dbo.Split एक तालिका है जहाँ यह मौजूद है और यह भी कोड भाजित तालिका में कॉलम है? मुझे इस पृष्ठ में कहीं भी उन तालिका या मूल्यों की सूची नहीं मिली?
जयेंद्रन

1
मेरा काम कोड हैं:select t.OtherID, x.* from testData t cross apply (select item as Data from dbo.Split(t.Data,',') ) x
अकबर कौत्सर

12

फरवरी २०१६ के अनुसार - TALLY तालिका का उदाहरण देखें - फरवरी २०१४ से, नीचे मेरे TVF के बेहतर प्रदर्शन की संभावना है। पोस्ट के लिए मूल पद नीचे रखते हुए:


उपरोक्त उदाहरणों में मेरी पसंद के लिए बहुत अधिक दोहराया गया कोड। और मैं सीटीई और एक्सएमएल के प्रदर्शन को नापसंद करता हूं। इसके अलावा, एक स्पष्ट Idताकि उपभोक्ताओं को आदेश विशिष्ट हैं एक ORDER BYखंड निर्दिष्ट कर सकते हैं ।

CREATE FUNCTION dbo.Split
(
    @Line nvarchar(MAX),
    @SplitOn nvarchar(5) = ','
)
RETURNS @RtnValue table
(
    Id INT NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED,
    Data nvarchar(100) NOT NULL
)
AS
BEGIN
    IF @Line IS NULL RETURN

    DECLARE @split_on_len INT = LEN(@SplitOn)
    DECLARE @start_at INT = 1
    DECLARE @end_at INT
    DECLARE @data_len INT

    WHILE 1=1
    BEGIN
        SET @end_at = CHARINDEX(@SplitOn,@Line,@start_at)
        SET @data_len = CASE @end_at WHEN 0 THEN LEN(@Line) ELSE @end_at-@start_at END
        INSERT INTO @RtnValue (data) VALUES( SUBSTRING(@Line,@start_at,@data_len) );
        IF @end_at = 0 BREAK;
        SET @start_at = @end_at + @split_on_len
    END

    RETURN
END

6

यह देखकर अच्छा लगा कि यह 2016 के संस्करण में हल किया गया है, लेकिन उन सभी के लिए जो उस पर नहीं हैं, यहां ऊपर दिए गए तरीकों के दो सामान्यीकृत और सरलीकृत संस्करण हैं।

XML- विधि कम है, लेकिन निश्चित रूप से xml-trick (कोई 'बुरा' वर्ण) के लिए अनुमति देने के लिए स्ट्रिंग की आवश्यकता होती है।

एक्सएमएल-विधि:

create function dbo.splitString(@input Varchar(max), @Splitter VarChar(99)) returns table as
Return
    SELECT Split.a.value('.', 'VARCHAR(max)') AS Data FROM
    ( SELECT CAST ('<M>' + REPLACE(@input, @Splitter, '</M><M>') + '</M>' AS XML) AS Data 
    ) AS A CROSS APPLY Data.nodes ('/M') AS Split(a); 

पुनरावर्ती विधि:

create function dbo.splitString(@input Varchar(max), @Splitter Varchar(99)) returns table as
Return
  with tmp (DataItem, ix) as
   ( select @input  , CHARINDEX('',@Input)  --Recu. start, ignored val to get the types right
     union all
     select Substring(@input, ix+1,ix2-ix-1), ix2
     from (Select *, CHARINDEX(@Splitter,@Input+@Splitter,ix+1) ix2 from tmp) x where ix2<>0
   ) select DataItem from tmp where ix<>0

क्रिया में क्रिया

Create table TEST_X (A int, CSV Varchar(100));
Insert into test_x select 1, 'A,B';
Insert into test_x select 2, 'C,D';

Select A,data from TEST_X x cross apply dbo.splitString(x.CSV,',') Y;

Drop table TEST_X

एक्सएमएल-एमओएचओडी 2: यूनिकोड फ्रेंडली 2 (मैक्स होजेस का जोड़ शिष्टाचार) create function dbo.splitString(@input nVarchar(max), @Splitter nVarchar(99)) returns table as Return SELECT Split.a.value('.', 'NVARCHAR(max)') AS Data FROM ( SELECT CAST ('<M>' + REPLACE(@input, @Splitter, '</M><M>') + '</M>' AS XML) AS Data ) AS A CROSS APPLY Data.nodes ('/M') AS Split(a);


1
यह स्पष्ट लग सकता है, लेकिन आप इन दो कार्यों का उपयोग कैसे करते हैं? विशेष रूप से, आप यह दिखा सकते हैं कि ओपी के उपयोग के मामले में इसका उपयोग कैसे करें?
jpaugh

1
यहां एक त्वरित उदाहरण है: तालिका बनाएं TEST_X (एक इंट, सीएसवी वर्चर (100)); Test_x में डालें 1, 'ए, बी' का चयन करें; Test_x में 2 चुनें, 'C, D'; A चुनें, TEST_X x क्रॉस से डेटा dbo.splitString (x.CSV, ',') Y लागू करें; ड्रॉप टेबल TEST_X
Eske Rahn

मुझे ठीक इसी की आवश्यकता थी! धन्यवाद।
नितिन बडोले

5

कृपया नीचे TSQL देखें। STRING_SPLIT फ़ंक्शन केवल संगतता स्तर 130 और इसके बाद के संस्करण के तहत उपलब्ध है।

TSQL:

DECLARE @stringValue NVARCHAR(400) = 'red,blue,green,yellow,black'  
DECLARE @separator CHAR = ','

SELECT [value]  As Colour
FROM STRING_SPLIT(@stringValue, @separator); 

परिणाम:

रंग

लाल नीला हरा पीला काला


5

बहुत देर से लेकिन यह आज़माएं:

SELECT ColumnID, Column1, value  --Do not change 'value' name. Leave it as it is.
FROM tbl_Sample  
CROSS APPLY STRING_SPLIT(Tags, ','); --'Tags' is the name of column containing comma separated values

तो हम यह कर रहे थे: tbl_Sample:

ColumnID|   Column1 |   Tags
--------|-----------|-------------
1       |   ABC     |   10,11,12    
2       |   PQR     |   20,21,22

इस क्वेरी को चलाने के बाद:

ColumnID|   Column1 |   value
--------|-----------|-----------
1       |   ABC     |   10
1       |   ABC     |   11
1       |   ABC     |   12
2       |   PQR     |   20
2       |   PQR     |   21
2       |   PQR     |   22

धन्यवाद!


STRING_SPLITनिफ्टी है, लेकिन इसके लिए SQL सर्वर 2016 की आवश्यकता है। docs.microsoft.com/en-us/sql/t-sql/functions/…
क्रेग सिल्वर

सुरुचिपूर्ण समाधान।
संग्राम नंदखिले

3
DECLARE @id_list VARCHAR(MAX) = '1234,23,56,576,1231,567,122,87876,57553,1216'
DECLARE @table TABLE ( id VARCHAR(50) )
DECLARE @x INT = 0
DECLARE @firstcomma INT = 0
DECLARE @nextcomma INT = 0

SET @x = LEN(@id_list) - LEN(REPLACE(@id_list, ',', '')) + 1 -- number of ids in id_list

WHILE @x > 0
    BEGIN
        SET @nextcomma = CASE WHEN CHARINDEX(',', @id_list, @firstcomma + 1) = 0
                              THEN LEN(@id_list) + 1
                              ELSE CHARINDEX(',', @id_list, @firstcomma + 1)
                         END
        INSERT  INTO @table
        VALUES  ( SUBSTRING(@id_list, @firstcomma + 1, (@nextcomma - @firstcomma) - 1) )
        SET @firstcomma = CHARINDEX(',', @id_list, @firstcomma + 1)
        SET @x = @x - 1
    END

SELECT  *
FROM    @table

यह कुछ तरीकों में से एक है जो Azure SQL Data Warehouse में सीमित SQL समर्थन के साथ काम करता है।
आरोन

1
;WITH tmp(SomeID, OtherID, DataItem, Data) as (
    SELECT SomeID, OtherID, LEFT(Data, CHARINDEX(',',Data+',')-1),
        STUFF(Data, 1, CHARINDEX(',',Data+','), '')
FROM Testdata
WHERE Data > ''
)
SELECT SomeID, OtherID, Data
FROM tmp
ORDER BY SomeID

उपरोक्त क्वेरी के लिए केवल छोटे से संशोधन के साथ ...


6
क्या आप संक्षेप में बता सकते हैं कि स्वीकृत उत्तर में संस्करण पर यह कैसे सुधार है?
लीह

कोई संघ नहीं ... कम कोड। चूंकि यह संघ के बजाय सभी का उपयोग कर रहा है, इसलिए प्रदर्शन में अंतर नहीं होना चाहिए?
तमसुराजॉय

1
यह सभी पंक्तियों को वापस नहीं करना चाहिए था। मुझे यकीन नहीं है कि डेटा के बारे में संघ को सभी की आवश्यकता है, लेकिन आपके समाधान ने मूल तालिका के समान पंक्तियों को वापस कर दिया।
Oedhel Setren

1
(यहाँ समस्या यह है कि पुनरावर्ती भाग एक छोड़ दिया गया है ...)
Eske Rahn

मुझे उम्मीद नहीं थी कि उत्पादन केवल अलग पंक्ति में पहला रिकॉर्ड दे रहा है
अंकित मिश्रा

1

इस दृष्टिकोण का उपयोग करते समय आपको यह सुनिश्चित करना होगा कि आपके किसी भी मूल्य में ऐसा कुछ नहीं है जो अवैध XML होगा - user1151923

मैं हमेशा एक्सएमएल विधि का उपयोग करता हूं। सुनिश्चित करें कि आप VALID XML का उपयोग करते हैं। वैध XML और पाठ के बीच कनवर्ट करने के लिए मेरे पास दो कार्य हैं। (मैं गाड़ी से वापसी करने के लिए तैयार हूं क्योंकि मुझे आमतौर पर उनकी जरूरत नहीं है।

CREATE FUNCTION dbo.udf_ConvertTextToXML (@Text varchar(MAX)) 
    RETURNS varchar(MAX)
AS
    BEGIN
        SET @Text = REPLACE(@Text,CHAR(10),'')
        SET @Text = REPLACE(@Text,CHAR(13),'')
        SET @Text = REPLACE(@Text,'<','&lt;')
        SET @Text = REPLACE(@Text,'&','&amp;')
        SET @Text = REPLACE(@Text,'>','&gt;')
        SET @Text = REPLACE(@Text,'''','&apos;')
        SET @Text = REPLACE(@Text,'"','&quot;')
    RETURN @Text
END


CREATE FUNCTION dbo.udf_ConvertTextFromXML (@Text VARCHAR(MAX)) 
    RETURNS VARCHAR(max)
AS
    BEGIN
        SET @Text = REPLACE(@Text,'&lt;','<')
        SET @Text = REPLACE(@Text,'&amp;','&')
        SET @Text = REPLACE(@Text,'&gt;','>')
        SET @Text = REPLACE(@Text,'&apos;','''')
        SET @Text = REPLACE(@Text,'&quot;','"')
    RETURN @Text
END

1
आपके पास वहां मौजूद कोड के साथ एक छोटी सी समस्या है। यह '<' को '& lt;' में बदलेगा '& lt;' के बजाय जैसा होना चाहिए। इसलिए आपको पहले 'और' को एनकोड करना होगा।
स्टीवर्ट

इस तरह के फ़ंक्शन की कोई आवश्यकता नहीं है ... बस अंतर्निहित क्षमताओं का उपयोग करें। इसे आज़माएं:SELECT (SELECT '<&> blah' + CHAR(13)+CHAR(10) + 'next line' FOR XML PATH(''))
शन्नो

1

समारोह

CREATE FUNCTION dbo.SplitToRows (@column varchar(100), @separator varchar(10))
RETURNS @rtnTable TABLE
  (
  ID int identity(1,1),
  ColumnA varchar(max)
  )
 AS
BEGIN
    DECLARE @position int = 0
    DECLARE @endAt int = 0
    DECLARE @tempString varchar(100)

    set @column = ltrim(rtrim(@column))

    WHILE @position<=len(@column)
    BEGIN       
        set @endAt = CHARINDEX(@separator,@column,@position)
            if(@endAt=0)
            begin
            Insert into @rtnTable(ColumnA) Select substring(@column,@position,len(@column)-@position)
            break;
            end
        set @tempString = substring(ltrim(rtrim(@column)),@position,@endAt-@position)

        Insert into @rtnTable(ColumnA) select @tempString
        set @position=@endAt+1;
    END
    return
END

उदाहरण

select * from dbo.SplitToRows('T14; p226.0001; eee; 3554;', ';')

या बस एक से अधिक परिणाम सेट के साथ चयन करें

DECLARE @column varchar(max)= '1234; 4748;abcde; 324432'
DECLARE @separator varchar(10) = ';'
DECLARE @position int = 0
DECLARE @endAt int = 0
DECLARE @tempString varchar(100)

set @column = ltrim(rtrim(@column))

WHILE @position<=len(@column)
BEGIN       
    set @endAt = CHARINDEX(@separator,@column,@position)
        if(@endAt=0)
        begin
        Select substring(@column,@position,len(@column)-@position)
        break;
        end
    set @tempString = substring(ltrim(rtrim(@column)),@position,@endAt-@position)

    select @tempString
    set @position=@endAt+1;
END

मल्टीस्टैटमेंट टेबल वैल्यू फंक्शन के अंदर थोड़ी देर लूप का उपयोग करना स्ट्रिंग्स को विभाजित करने के सबसे खराब तरीके के बारे में है। इस सवाल पर बहुत सारे सेट आधारित विकल्प पहले से हैं।
शॉन लैंग

0

नीचे sql सर्वर 2008 पर काम करता है

select *, ROW_NUMBER() OVER(order by items) as row# 
from 
( select 134 myColumn1, 34 myColumn2, 'd,c,k,e,f,g,h,a' comaSeperatedColumn) myTable
    cross apply 
SPLIT (rtrim(comaSeperatedColumn), ',') splitedTable -- gives 'items'  column 

स्प्लिट टेबल के मूल टेबल कॉलम प्लस "आइटम" के साथ सभी कार्टेशियन उत्पाद प्राप्त करेंगे।


0

डेटा निकालने के लिए आप निम्न फ़ंक्शन का उपयोग कर सकते हैं

CREATE FUNCTION [dbo].[SplitString]
(    
    @RowData NVARCHAR(MAX),
    @Delimeter NVARCHAR(MAX)
)
RETURNS @RtnValue TABLE 
(
    ID INT IDENTITY(1,1),
    Data NVARCHAR(MAX)
) 
AS
BEGIN 
    DECLARE @Iterator INT
    SET @Iterator = 1

    DECLARE @FoundIndex INT
    SET @FoundIndex = CHARINDEX(@Delimeter,@RowData)

    WHILE (@FoundIndex>0)
    BEGIN
        INSERT INTO @RtnValue (data)
        SELECT 
            Data = LTRIM(RTRIM(SUBSTRING(@RowData, 1, @FoundIndex - 1)))

        SET @RowData = SUBSTRING(@RowData,
                @FoundIndex + DATALENGTH(@Delimeter) / 2,
                LEN(@RowData))

        SET @Iterator = @Iterator + 1
        SET @FoundIndex = CHARINDEX(@Delimeter, @RowData)
    END

    INSERT INTO @RtnValue (Data)
    SELECT Data = LTRIM(RTRIM(@RowData))

    RETURN
END

मल्टीस्टैटमेंट टेबल वैल्यू फंक्शन के अंदर थोड़ी देर लूप का उपयोग करना स्ट्रिंग्स को विभाजित करने के सबसे खराब तरीके के बारे में है। इस सवाल पर बहुत सारे सेट आधारित विकल्प पहले से हैं।
शॉन लैंग
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.