আমি কীভাবে একটি স্ট্রিং বিভক্ত করব যাতে আমি এক্স আইটেমটি অ্যাক্সেস করতে পারি?


493

এসকিউএল সার্ভার ব্যবহার করে, আমি কীভাবে একটি স্ট্রিং বিভক্ত করব যাতে আমি আইটেম এক্স অ্যাক্সেস করতে পারি?

"হ্যালো জন স্মিথ" একটি স্ট্রিং নিন। আমি কীভাবে স্থান দ্বারা স্ট্রিংটি বিভক্ত করতে পারি এবং সূচি 1 এ আইটেমটি অ্যাক্সেস করতে পারি যা "জন" ফিরে আসতে পারে?




4
এখানে সর্বাধিক উত্তরগুলি হ'ল - আমার পক্ষে কমপক্ষে - বেশ পুরানো ফ্যাশনযুক্ত এবং বরং পুরানো। পদ্ধতিগত লোকগ, লুপস, পুনরাবৃত্তি, সিএলআর, ফাংশন, কোডের অনেক লাইন ... আরও আপ-টু-ডেট পদ্ধতির সন্ধানের জন্য "সক্রিয়" উত্তরগুলি পড়তে আগ্রহী হতে পারে ।
শুনুগো

: আমি আরো বেশি আপ-টু-ডেট পদ্ধতির সঙ্গে একটি নতুন উত্তর যোগ করেছেন stackoverflow.com/a/49669994/632604
Gorgi Rankovski

একটি তালিকার নবম উপাদানটি পেতে চেষ্টা করুন -> Portosql.wordpress.com/2019/05/27/enesimo-elemento-lista
জোসে

উত্তর:


191

আপনি এসকিউএল ব্যবহারকারী সংজ্ঞায়িত ফাংশনটিতে একটি সীমাবদ্ধ স্ট্রিং সহায়ক ( কোড প্রকল্প থেকে ) সহায়ক পার্স করার সমাধান পেতে পারেন ।

আপনি এই সহজ যুক্তি ব্যবহার করতে পারেন:

Declare @products varchar(200) = '1|20|3|343|44|6|8765'
Declare @individual varchar(20) = null

WHILE LEN(@products) > 0
BEGIN
    IF PATINDEX('%|%', @products) > 0
    BEGIN
        SET @individual = SUBSTRING(@products,
                                    0,
                                    PATINDEX('%|%', @products))
        SELECT @individual

        SET @products = SUBSTRING(@products,
                                  LEN(@individual + '|') + 1,
                                  LEN(@products))
    END
    ELSE
    BEGIN
        SET @individual = @products
        SET @products = NULL
        SELECT @individual
    END
END

1
কেন SET @p_SourceText = RTRIM( LTRIM( @p_SourceText)) SET @w_Length = DATALENGTH( RTRIM( LTRIM( @p_SourceText)))এবং না SET @p_SourceText = RTRIM( LTRIM( @p_SourceText)) SET @w_Length = DATALENGTH( @p_SourceText)?
বেথ

12
@ গেটকিলার এই সমাধানটি ইউনিকোড সমর্থন করে না এবং এটি কঠোর কোডড সংখ্যাসূচক (18,3) ব্যবহার করে যা এটি একটি কার্যকর "পুনরায় ব্যবহারযোগ্য" ফাংশন করে না।
ফিলিপ ডি ভোস

4
এটি কাজ করে তবে প্রচুর স্মৃতি বরাদ্দ করে এবং সিপিইউ নষ্ট করে।
jjxtra

2
এসকিউএল সার্ভার 2016 হিসাবে, এখন একটি অন্তর্নির্মিত ফাংশন রয়েছে STRING_SPLITযা একটি স্ট্রিংকে বিভক্ত করবে এবং একটি কলামের টেবিলের ফলাফলটি ফিরিয়ে দেবে যা আপনি কোনও SELECTবিবৃতিতে বা অন্য কোথাও ব্যবহার করতে পারবেন ।
qJake

আমি যে ছেলেদের জন্য কাজ করি খুব খারাপ তা 2016 এ নয় But তবে তারা যদি কখনও জুতা থেকে নেতৃত্ব না পায় তবে আমি এটিকে মনে রাখব। অন্তর্বর্তীকালীন দুর্দান্ত সমাধান। আমি এটিকে একটি ফাংশন হিসাবে বাস্তবায়ন করেছি এবং যুক্তি হিসাবে ডিলিমিটার যুক্ত করেছি।
ব্র্যান্ডন গ্রিফিন

355

আমি বিশ্বাস করি না যে এসকিউএল সার্ভারের একটি অন্তর্নির্মিত স্প্লিট ফাংশন রয়েছে, সুতরাং ইউডিএফ ব্যতীত, আমি জানি কেবলমাত্র অন্য উত্তরটি হল পার্সনেম ফাংশন হাইজ্যাক করা:

SELECT PARSENAME(REPLACE('Hello John Smith', ' ', '.'), 2) 

PARSENAME একটি স্ট্রিং নেয় এবং এটিকে পিরিয়ড ক্যারেক্টারে আলাদা করে দেয়। এটি তার দ্বিতীয় তর্ক হিসাবে একটি সংখ্যা নেয় এবং সেই সংখ্যাটি স্ট্রিংয়ের কোন অংশটি ফিরে আসবে (পিছন থেকে সামনের দিকে কাজ করছে) তা নির্দিষ্ট করে।

SELECT PARSENAME(REPLACE('Hello John Smith', ' ', '.'), 3)  --return Hello

স্পষ্ট সমস্যাটি যখন স্ট্রিংটিতে ইতিমধ্যে একটি পিরিয়ড থাকে। আমি এখনও মনে করি ইউডিএফ ব্যবহার করা সবচেয়ে ভাল উপায় ... অন্য কোনও পরামর্শ?


102
ধন্যবাদ শৌল ... আমার উল্লেখ করা উচিত যে এই সমাধানটি সত্যিকারের উন্নয়নের জন্য একটি খারাপ সমাধান। PARSENAME কেবলমাত্র চারটি অংশের প্রত্যাশা করে, তাই চারটিরও বেশি অংশের সাথে একটি স্ট্রিং ব্যবহার করা এটি NUL ফিরে আসে। ইউডিএফ সমাধানগুলি অবশ্যই আরও ভাল।
নাথান বেডফোর্ড

33
এটি দুর্দান্ত হ্যাক, এবং আমাকে কাঁদিয়ে তোলে যে সত্যিকারের ভাষাগুলিতে এত সহজ সরল কোনও কিছুর জন্য এই জাতীয় কিছু প্রয়োজনীয়।
ফ্যাক্টর মিস্টিক

36
সূচকগুলিকে "সঠিক" উপায়ে কাজ করতে, অর্থাৎ 1 থেকে শুরু করে, আমি আপনার হাইজ্যাকটি প্রত্যাহারের সাথে হাইজ্যাক করেছি: রিভার্স (পার্সনেম (রিপ্লেস ('হ্যালো জন স্মিথ'), '', '।') , 1)) - হ্যালো প্রদান করে
NothingsImp ممڪن

3
@ ফ্যাক্টরমিস্টিক প্রথম সাধারণ ফর্মের জন্য আপনাকে একক ক্ষেত্রে একাধিক মান স্থাপন করা দরকার না। এটি একটি আরডিবিএমএসের আক্ষরিক অর্থে প্রথম নিয়ম। কোনও SPLIT()ফাংশন সরবরাহ করা হয় না কারণ এটি দুর্বল ডাটাবেস ডিজাইনকে উত্সাহ দেয় এবং ডাটাবেসটি কখনও এই বিন্যাসে সঞ্চিত ডেটা ব্যবহার করতে অনুকূলিত হবে না। আরডিবিএমএস বিকাশকারীকে বোকা জিনিসগুলি পরিচালনা করতে সহায়তা করার বাধ্যবাধকতা নয় যা এটি পরিচালনা না করার জন্য ডিজাইন করা হয়েছে । সঠিক উত্তরটি সর্বদা "আপনার ডাটাবেসকে সাধারণীকরণ করুন যেমন আমরা 40 বছর আগে আপনাকে বলেছিলাম।" এসকিউএল বা আরডিবিএমএস উভয়ই দুর্বল ডিজাইনের জন্য দায়ী নয়।
বেকন বিট 4 ই

8
@ বেকনবিটস যখন আমি তত্ত্বের সাথে একমত হই, তখন অনুশীলনের সরঞ্জামগুলিতে দরকারী যেগুলি যখন আপনার আগে এসেছিল তার দ্বারা উত্পাদিত একটি দুর্বল নকশা স্বাভাবিক করার সময়।
টিম আবেল

110

প্রথমে একটি ফাংশন তৈরি করুন (সিটিই ব্যবহার করে সাধারণ টেবিল এক্সপ্রেশনটি টেম্প টেবিলের প্রয়োজনীয়তা সরিয়ে দেয়)

 create function dbo.SplitString 
    (
        @str nvarchar(4000), 
        @separator char(1)
    )
    returns table
    AS
    return (
        with tokens(p, a, b) AS (
            select 
                1, 
                1, 
                charindex(@separator, @str)
            union all
            select
                p + 1, 
                b + 1, 
                charindex(@separator, @str, b + 1)
            from tokens
            where b > 0
        )
        select
            p-1 zeroBasedOccurance,
            substring(
                @str, 
                a, 
                case when b > 0 then b-a ELSE 4000 end) 
            AS s
        from tokens
      )
    GO

তারপরে, এটিকে যেকোন টেবিল হিসাবে ব্যবহার করুন (বা এটি আপনার বিদ্যমান সঞ্চিত প্রকল্পের মধ্যে ফিট করার জন্য পরিবর্তন করুন)।

select s 
from dbo.SplitString('Hello John Smith', ' ')
where zeroBasedOccurance=1

হালনাগাদ

পূর্ববর্তী সংস্করণ 4000 অক্ষরের চেয়ে দীর্ঘ ইনপুট স্ট্রিংয়ের জন্য ব্যর্থ হবে। এই সংস্করণটি সীমাবদ্ধতার যত্ন নেয়:

create function dbo.SplitString 
(
    @str nvarchar(max), 
    @separator char(1)
)
returns table
AS
return (
with tokens(p, a, b) AS (
    select 
        cast(1 as bigint), 
        cast(1 as bigint), 
        charindex(@separator, @str)
    union all
    select
        p + 1, 
        b + 1, 
        charindex(@separator, @str, b + 1)
    from tokens
    where b > 0
)
select
    p-1 ItemIndex,
    substring(
        @str, 
        a, 
        case when b > 0 then b-a ELSE LEN(@str) end) 
    AS s
from tokens
);

GO

ব্যবহার একই থাকে।


14
এটি মার্জিত তবে কেবল পুনরাবৃত্তির গভীরতার সীমাবদ্ধতার কারণে 100 টি উপাদানের জন্য কাজ করে।
7'12 প্যাকিং

4
@ প্যাকিং, না, ডিফল্ট হ'ল 100(অসীম লুপ প্রতিরোধে)। ব্যবহারের MAXRECURSION ইঙ্গিতটি পুনরাবৃত্তির স্তরের নম্বর (সংজ্ঞায়িত করতে 0করতে 32767, 0হয় "কোন সীমা" - সার্ভার পেষ পারে)। বিটিডাব্লু, এর চেয়ে অনেক বেশি ভাল উত্তর PARSENAME, কারণ এটি সর্বজনীন :-)। +1
মাইচা পাওগা

maxrecursionএই সমাধানটিতে যুক্ত করা এই প্রশ্ন এবং এর উত্তরগুলি মনে রাখবেন কীভাবে maxrecursionসারণির মূল্যবান-কার্যকারিতাটির মধ্যে কোনও সিটিইর জন্য বিকল্প সেটআপ করবেন
মিশা পোভাগা

বিশেষত, ক্রিসফোলের উত্তরটি উল্লেখ করুন - তার পদ্ধতিটি কিছুটা ধীর করে দেয়, তবে অন্যান্য বিকল্পগুলির চেয়ে সহজ।
অহিগিন্স

গৌণ বিন্দু কিন্তু ব্যবহার একইরকম থাকে না কারণ আপনি কলামের নাম পরিবর্তন করেছেন, তাই sআর সংজ্ঞায়িত করা হয়নি
টিম আবেল

62

এখানকার বেশিরভাগ সমাধান লুপস বা পুনরাবৃত্ত সিটিইর সময় ব্যবহার করে। একটি সেট-ভিত্তিক পদ্ধতির উচ্চতর হবে, আমি প্রতিশ্রুতি, আপনি যদি একটি স্থান ছাড়া অন্য একটি ডিলিমিটার ব্যবহার করতে পারেন:

CREATE FUNCTION [dbo].[SplitString]
    (
        @List NVARCHAR(MAX),
        @Delim VARCHAR(255)
    )
    RETURNS TABLE
    AS
        RETURN ( SELECT [Value], idx = RANK() OVER (ORDER BY n) FROM 
          ( 
            SELECT n = Number, 
              [Value] = LTRIM(RTRIM(SUBSTRING(@List, [Number],
              CHARINDEX(@Delim, @List + @Delim, [Number]) - [Number])))
            FROM (SELECT Number = ROW_NUMBER() OVER (ORDER BY name)
              FROM sys.all_objects) AS x
              WHERE Number <= LEN(@List)
              AND SUBSTRING(@Delim + @List, [Number], LEN(@Delim)) = @Delim
          ) AS y
        );

নমুনা ব্যবহার:

SELECT Value FROM dbo.SplitString('foo,bar,blat,foo,splunge',',')
  WHERE idx = 3;

ফলাফল:

----
blat

আপনি idxএই ফাংশনটির পক্ষে যুক্তি হিসাবে যা চান তা যুক্ত করতে পারেন, তবে আমি এটি পাঠকের অনুশীলন হিসাবে ছেড়ে দেব।

আপনার সাথে এই ব্যবহার করতে পারবেন না শুধু নেটিভ STRING_SPLITফাংশন এসকিউএল সার্ভার 2016 সালে যোগ যে কোন গ্যারান্টি আউটপুট মূল তালিকার অনুক্রমে রেন্ডার হবে না থাকায়। অন্য কথায়, আপনি যদি পাস করেন 3,6,1তবে ফলাফলটি সম্ভবত সেই ক্রমে থাকবে তবে তা হতে পারে 1,3,6। আমি এখানে অন্তর্নির্মিত কার্যকারিতা উন্নতিতে সম্প্রদায়ের সহায়তা চেয়েছি:

পর্যাপ্ত গুণগত প্রতিক্রিয়ার সাথে তারা প্রকৃতপক্ষে এর কিছু উন্নতি করতে পারে:

স্প্লিট ফাংশনগুলির বিষয়ে আরও কেন, (এবং প্রমাণ হিসাবে) লুপগুলি এবং পুনরাবৃত্ত সিটিই স্কেল করে না, এবং আরও ভাল বিকল্পগুলি, যদি অ্যাপ্লিকেশন স্তর থেকে পৃথক পৃথক স্ট্রিংগুলি আসে:

উপরে SQL সার্ভার 2016 বা, যদিও, আপনি তাকান উচিত STRING_SPLIT()এবং STRING_AGG():


1
সেরা উত্তর, আইএমএইচও। অন্য কয়েকটি উত্তরে এসকিউএল পুনরাবৃত্তি সীমা 100 এর বিষয়টি রয়েছে তবে এই ক্ষেত্রে নয় case খুব দ্রুত এবং খুব সাধারণ বাস্তবায়ন। +2 বোতামটি কোথায়?
টি-মোটি

5
আমি ব্যবহারের সাথে এই ফাংশনটি ভারব্যাটিম চেষ্টা করেছি: select * from DBO.SplitString('Hello John smith', ' ');এবং উত্পাদিত আউটপুটটি ছিল: মূল্য হ্যালো ইলো ললো লো ও জন ওঁ এইচএন এন স্মিথ মিঠ h ম এইচ
wwmbes

2
অ্যারোনবার্ট্র্যান্ড গেটকিলার পোস্ট করা মূল সমস্যাটিতে একটি স্পেস ডিলিমিটার জড়িত।
wwmbes

1
@ ব্যবহারকারী 1255933 ঠিকানা।
অ্যারোন বার্ট্র্যান্ড

1
@ মিশেল হ্যাঁ, এটি সত্য। আপনার কাছে বিকল্প স্কেমা অনুমতি না থাকলে বাছাই করার জন্য আপনার কাছে কোনও টেবিলও নেই এবং আপনি যদি নির্বাচনের অনুমতি না পেয়ে থাকেন তবে তা থেকে নির্বাচন করতে পারবেন না আপনি সর্বদা কাউকে আপনার জন্য ফাংশন তৈরি করতে বলতে চাইতে পারেন । বা এটি যে কোনও জায়গায় তৈরি করুন আপনি এটি তৈরি করতে পারেন (এমনকি অস্থায়ীভাবে, টেম্পিডবিতে বলুন)। এবং 2016+ এ আপনি STRING_SPLIT () ব্যবহার করা উচিত এবং আপনাকে যেভাবেই নিজের তৈরি করতে হবে এমন কোনও ফাংশন নয়।
অ্যারন বারট্রান্ড

38

স্ট্রিং পার্সিংয়ের জন্য আপনি একটি নম্বর সারণীটি উত্তোলন করতে পারেন।

একটি দৈহিক সংখ্যা সারণী তৈরি করুন:

    create table dbo.Numbers (N int primary key);
    insert into dbo.Numbers
        select top 1000 row_number() over(order by number) from master..spt_values
    go

1000000 সারি দিয়ে পরীক্ষার সারণী তৈরি করুন

    create table #yak (i int identity(1,1) primary key, array varchar(50))

    insert into #yak(array)
        select 'a,b,c' from dbo.Numbers n cross join dbo.Numbers nn
    go

ফাংশন তৈরি করুন

    create function [dbo].[ufn_ParseArray]
        (   @Input      nvarchar(4000), 
            @Delimiter  char(1) = ',',
            @BaseIdent  int
        )
    returns table as
    return  
        (   select  row_number() over (order by n asc) + (@BaseIdent - 1) [i],
                    substring(@Input, n, charindex(@Delimiter, @Input + @Delimiter, n) - n) s
            from    dbo.Numbers
            where   n <= convert(int, len(@Input)) and
                    substring(@Delimiter + @Input, n, 1) = @Delimiter
        )
    go

ব্যবহার (আমার ল্যাপটপে 3 মাইল সারি আউটপুটস)

    select * 
    from #yak 
    cross apply dbo.ufn_ParseArray(array, ',', 1)

পরিষ্কার কর

    drop table dbo.Numbers;
    drop function  [dbo].[ufn_ParseArray]

এখানে পারফরম্যান্স আশ্চর্যজনক নয়, তবে এক মিলিয়ন সারি টেবিলের উপরে কোনও ফাংশন কল করা সেরা ধারণা নয়। যদি অনেকগুলি সারিতে স্ট্রিং বিভক্ত হয় তবে আমি ফাংশনটি এড়াতে চাই।


2
সেরা সমাধান আইএমও, অন্যদের মধ্যে একরকম সীমাবদ্ধতা রয়েছে .. এটি দ্রুত এবং অনেক উপাদান সহ দীর্ঘ স্ট্রিংকে পার্স করতে পারে।

আপনি কেন নামার আদেশ দিচ্ছেন? যদি সেখানে তিনটি আইটেম থাকে এবং আমরা 1 এ সংখ্যাটি শুরু করেছিলাম, তবে প্রথম আইটেমটি 3 নম্বর হবে এবং শেষটি হবে 1 নম্বরটি desc?
হ্যাচেট -

1
সম্মত, asc দিকের আরও স্বজ্ঞাত হবে। আমি পার্সনাম () কনভেনশনটি অনুসরণ করছিলাম যা ডেস্ক ব্যবহার করে
নাথান

3
এই কাজগুলি কীভাবে দুর্দান্ত হবে সে সম্পর্কে কিছু ব্যাখ্যা
টিম আবেল

পার্স করার জন্য 3 টি ক্ষেত্রের 100 মিলিয়ন সারিগুলির একটি পরীক্ষায়, ufn_ParseArray 25 মিনিটের পরে শেষ হয় নি, যখন REVERSE(PARSENAME(REPLACE(REVERSE('Hello John Smith'), ' ', '.'), 1)) @ নোটিংিংস ইম্পসিবল থেকে 1.5 মিনিটে সম্পন্ন হয়েছে। @hello_earth আপনার সমাধান কীভাবে 4 টিরও বেশি ক্ষেত্রের সাথে দীর্ঘতর স্ট্রিংয়ের সাথে তুলনা করতে পারে?
wwmbes

31

এই প্রশ্ন একটি স্ট্রিং বিভক্ত পদ্ধতির সম্পর্কে না , কিন্তু সম্পর্কে কিভাবে n তম উপাদান পেতে

এখানে সমস্ত উত্তর পুনরাবৃত্তি ব্যবহার করে কিছু ধরণের স্ট্রিং বিভক্ত করছে, CTE গুলি, একাধিক CHARINDEX, REVERSEএবং PATINDEX, উদ্ভাবন ফাংশন, CLR পদ্ধতি, সংখ্যা টেবিল, আহ্বান CROSS APPLYs ... সর্বাধিক উত্তর কোডের অনেক লাইন আবরণ।

তবে - যদি আপনি সত্যিই নবম এলিমেন্টটি পাওয়ার পদ্ধতির চেয়ে আরও কিছু চান না - এটি বাস্তব ওয়ান-লাইনার হিসাবে , কোনও ইউডিএফ, এমনকি উপ-নির্বাচন হিসাবেও করা যায় না ... এবং অতিরিক্ত সুবিধা হিসাবে: নিরাপদ টাইপ করুন

একটি স্থান দ্বারা সীমানা অংশ 2 পান:

DECLARE @input NVARCHAR(100)=N'part1 part2 part3';
SELECT CAST(N'<x>' + REPLACE(@input,N' ',N'</x><x>') + N'</x>' AS XML).value('/x[2]','nvarchar(max)')

অবশ্যই আপনি ডিলিমিটার এবং অবস্থানের জন্য ভেরিয়েবলগুলি ব্যবহার করতে পারেন (ব্যবহার করুন)sql:column কোনও প্রশ্নের মান থেকে সরাসরি অবস্থানটি পুনরুদ্ধার করতে ):

DECLARE @dlmt NVARCHAR(10)=N' ';
DECLARE @pos INT = 2;
SELECT CAST(N'<x>' + REPLACE(@input,@dlmt,N'</x><x>') + N'</x>' AS XML).value('/x[sql:variable("@pos")][1]','nvarchar(max)')

যদি আপনার স্ট্রিংয়ে নিষিদ্ধ অক্ষরগুলি (বিশেষত একটির মধ্যে একটি &><) অন্তর্ভুক্ত থাকে তবে আপনি এখনও এইভাবে এটি করতে পারেন। FOR XML PATHপ্রথমে আপনার স্ট্রিংয়ের মধ্যে সমস্ত নিষিদ্ধ অক্ষরকে পুরোপুরি ফিট করার ক্রমটি প্রতিস্থাপন করতে ব্যবহার করুন।

এটি অতিরিক্ত বিশেষ ক্ষেত্রে যদি - অতিরিক্তভাবে - আপনার ডিলিমিটারটি সেমিকোলন হয় । এই ক্ষেত্রে আমি প্রথমে ডিলিমিটারটি '# DLMT #' এ প্রতিস্থাপন করব এবং শেষ পর্যন্ত এটি এক্সএমএল ট্যাগগুলিতে প্রতিস্থাপন করব:

SET @input=N'Some <, > and &;Other äöü@€;One more';
SET @dlmt=N';';
SELECT CAST(N'<x>' + REPLACE((SELECT REPLACE(@input,@dlmt,'#DLMT#') AS [*] FOR XML PATH('')),N'#DLMT#',N'</x><x>') + N'</x>' AS XML).value('/x[sql:variable("@pos")][1]','nvarchar(max)');

এসকিউএল-সার্ভার 2016+ এর জন্য আপডেট

দুঃখের সাথে বিকাশকারীরা অংশটির সূচকটি দিয়ে ফিরে যেতে ভুলে গেছেন STRING_SPLIT। তবে, এসকিউএল-সার্ভার 2016+ ব্যবহার করে রয়েছেJSON_VALUE এবং রয়েছে OPENJSON

সঙ্গে JSON_VALUE আমরা সূচকের অ্যারে হিসাবে অবস্থানে যেতে পারি।

জন্য ডকুমেন্টেশনOPENJSON স্পষ্টভাবে বলে:

যখন ওপেনজসন একটি জেএসওএন অ্যারে পার্স করে, ফাংশনটি জেএসএন পাঠ্যের উপাদানগুলির সূচিগুলি কী হিসাবে দেয়।

মত একটি পংক্তি 1,2,3বন্ধনী চেয়ে বেশি চাহিদা কিছুই: [1,2,3]
মত শব্দ একটি স্ট্রিং this is an exampleচাহিদা হতে ["this","is","an","example"]
এগুলি খুব সহজ স্ট্রিং অপারেশন। এটি চেষ্টা করে দেখুন:

DECLARE @str VARCHAR(100)='Hello John Smith';
DECLARE @position INT = 2;

--We can build the json-path '$[1]' using CONCAT
SELECT JSON_VALUE('["' + REPLACE(@str,' ','","') + '"]',CONCAT('$[',@position-1,']'));

- নিরাপদ স্ট্রিং-স্প্লিটার ( শূন্য-ভিত্তিক ) এর জন্য এটি দেখুন:

SELECT  JsonArray.[key] AS [Position]
       ,JsonArray.[value] AS [Part]
FROM OPENJSON('["' + REPLACE(@str,' ','","') + '"]') JsonArray

ইন এই পোস্টে আমি বিভিন্ন পন্থা পরীক্ষিত দেখলেন, যেOPENJSON সত্যিই দ্রুত। বিখ্যাত "ডিলিমিটেডস্প্লিট 8 কে ()" পদ্ধতির চেয়ে অনেক দ্রুত ...

আপডেট 2 - মান টাইপ-নিরাপদ পান

দ্বিগুণ ব্যবহার করে আমরা একটি অ্যারের মধ্যে একটি অ্যারের ব্যবহার করতে পারি [[]]। এটি টাইপড WITHক্লাউজগুলির জন্য অনুমতি দেয় :

DECLARE  @SomeDelimitedString VARCHAR(100)='part1|1|20190920';

DECLARE @JsonArray NVARCHAR(MAX)=CONCAT('[["',REPLACE(@SomeDelimitedString,'|','","'),'"]]');

SELECT @SomeDelimitedString          AS TheOriginal
      ,@JsonArray                    AS TransformedToJSON
      ,ValuesFromTheArray.*
FROM OPENJSON(@JsonArray)
WITH(TheFirstFragment  VARCHAR(100) '$[0]'
    ,TheSecondFragment INT          '$[1]'
    ,TheThirdFragment  DATE         '$[2]') ValuesFromTheArray

পুনরায়: যদি আপনার স্ট্রিংটিতে নিষিদ্ধ অক্ষর অন্তর্ভুক্ত থাকে ... আপনি কেবল সাবস্ট্রিংগুলিকে কেবল মোড়ানো করতে পারেন <x><![CDATA[x<&>x]]></x>
সালমান এ

@ সালমানা, হ্যাঁ, - বিভাগগুলিও এটিকে CDATAমোকাবেলা করতে পারে ... তবে অভিনয়ের পরে তারা চলে গেছে ( স্পষ্টভাবে পালাতে বদলে গেছে text())। আমি হুডের নীচে যাদু পছন্দ করি না , তাই আমি (SELECT 'Text with <&>' AS [*] FOR XML PATH(''))- পদ্ধতির পছন্দ করব । এটি আমার কাছে পরিষ্কার দেখায় এবং যাইহোক ঘটে ... ( সিডিএটিএ এবং এক্সএমএল সম্পর্কে আরও কিছু )।
শুনুগো

22

এখানে একটি ইউডিএফ রয়েছে যা এটি করবে। এটি সীমানাঙ্কিত মানগুলির একটি সারণী ফিরিয়ে দেবে, এটিতে সমস্ত পরিস্থিতিতে চেষ্টা করে দেখেনি তবে আপনার উদাহরণটি ঠিক কাজ করে।


CREATE FUNCTION SplitString 
(
    -- Add the parameters for the function here
    @myString varchar(500),
    @deliminator varchar(10)
)
RETURNS 
@ReturnTable TABLE 
(
    -- Add the column definitions for the TABLE variable here
    [id] [int] IDENTITY(1,1) NOT NULL,
    [part] [varchar](50) NULL
)
AS
BEGIN
        Declare @iSpaces int
        Declare @part varchar(50)

        --initialize spaces
        Select @iSpaces = charindex(@deliminator,@myString,0)
        While @iSpaces > 0

        Begin
            Select @part = substring(@myString,0,charindex(@deliminator,@myString,0))

            Insert Into @ReturnTable(part)
            Select @part

    Select @myString = substring(@mystring,charindex(@deliminator,@myString,0)+ len(@deliminator),len(@myString) - charindex(' ',@myString,0))


            Select @iSpaces = charindex(@deliminator,@myString,0)
        end

        If len(@myString) > 0
            Insert Into @ReturnTable
            Select @myString

    RETURN 
END
GO

আপনি এটিকে এভাবে ডাকবেন:


Select * From SplitString('Hello John Smith',' ')

সম্পাদনা করুন: লেন> 1 এর সাথে ডিলিমটারগুলি হ্যান্ডেল করার আপডেট সমাধান:


select * From SplitString('Hello**John**Smith','**')

Dbo.ethos_SplitString_fn (* লোক, উইকস, এখানে ছিলেন ',', ') আইডি অংশটি থেকে * নির্বাচনের জন্য কাজ করেনি ----------- ------------ -------------------------------------- 1 লোক 2 বেত
গাই

2
লেন () সহ নজর রাখুন কারণ এটির যুক্তির পিছনে স্থান থাকলে সঠিক নম্বরটি ফিরে আসবে না eg যেমন লেন ('-') = ২
ররি

এতে কাজ করে না: ডিবিও থেকে * নির্বাচন করুন pস্প্লিটস্ট্রিং ('foo, foo test ,,,, foo', ',')
সিবিপি

1
সিবিপি-র জন্য স্থির করুন .. @myString = স্ট্রিং নির্বাচন করুন (@ মাইস্ট্রিং, @ আইস্পেসস + লেন (@ ডেলিমনেটর), লেন (@ মাইস্ট্রিং) - চারিনডেক্স (@ ডিলিমিনেটর, @ মাইস্ট্রিং, 0))
অ্যালেক্সওয়েস্ট

16

এখানে আমি সমাধানের একটি সহজ উপায় পোস্ট করি

CREATE FUNCTION [dbo].[split](
          @delimited NVARCHAR(MAX),
          @delimiter NVARCHAR(100)
        ) RETURNS @t TABLE (id INT IDENTITY(1,1), val NVARCHAR(MAX))
        AS
        BEGIN
          DECLARE @xml XML
          SET @xml = N'<t>' + REPLACE(@delimited,@delimiter,'</t><t>') + '</t>'

          INSERT INTO @t(val)
          SELECT  r.value('.','varchar(MAX)') as item
          FROM  @xml.nodes('/t') as records(r)
          RETURN
        END


ফাংশনটি এভাবে চালিত করুন

  select * from dbo.split('Hello John Smith',' ')

আমি এই সমাধানটি পছন্দ করেছি। ফলাফলের মধ্যে নির্দিষ্ট কলামের উপর ভিত্তি করে একটি স্কেলারের মান ফেরানোর জন্য এটি প্রসারিত করে।
অ্যালান

আমি এটি ব্যবহার করে স্ট্রিংটিতে একটি '&' দিয়ে
জ্বলিত হয়েছি

10

আমার মতে আপনি ছেলেরা এটিকে খুব জটিল করে তুলছেন। কেবল একটি সিএলআর ইউডিএফ তৈরি করুন এবং এটি দিয়ে সম্পন্ন করুন।

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Collections.Generic;

public partial class UserDefinedFunctions {
  [SqlFunction]
  public static SqlString SearchString(string Search) {
    List<string> SearchWords = new List<string>();
    foreach (string s in Search.Split(new char[] { ' ' })) {
      if (!s.ToLower().Equals("or") && !s.ToLower().Equals("and")) {
        SearchWords.Add(s);
      }
    }

    return new SqlString(string.Join(" OR ", SearchWords.ToArray()));
  }
};

20
আমি অনুমান করি এটি খুব জটিল, কারণ আমার ভিজ্যুয়াল স্টুডিও থাকা দরকার, তারপরে সার্ভারে সিএলআর সক্ষম করুন, তারপরে প্রকল্পটি তৈরি এবং সংকলন করুন এবং অবশেষে এটি ব্যবহারের জন্য অ্যাসেমব্লিগুলি ডাটাবেজে যুক্ত করুন। তবে এখনও একটি আকর্ষণীয় উত্তর।
গিলারমো গুটিরিজ

3
@ guillegr123, এটি জটিল হওয়ার দরকার নেই। আপনি কেবল ডাউনলোড এবং ইনস্টল করতে পারেন (নিখরচায়!), এসকিউএল #, এটি এসকিউএলআরআর ফাংশন এবং প্রোসগুলির একটি গ্রন্থাগার। আপনি এটি এসকিউএলশার ডটকম থেকে পেতে পারেন । হ্যাঁ, আমি লেখক তবে স্ট্রিং_স্প্লিটটি ফ্রি সংস্করণে অন্তর্ভুক্ত।
সলোমন রুটজকি

10

ব্যবহার stringএবং values()বিবৃতি সম্পর্কে কি ?

DECLARE @str varchar(max)
SET @str = 'Hello John Smith'

DECLARE @separator varchar(max)
SET @separator = ' '

DECLARE @Splited TABLE(id int IDENTITY(1,1), item varchar(max))

SET @str = REPLACE(@str, @separator, '''),(''')
SET @str = 'SELECT * FROM (VALUES(''' + @str + ''')) AS V(A)' 

INSERT INTO @Splited
EXEC(@str)

SELECT * FROM @Splited

ফলাফল-সেট অর্জন।

id  item
1   Hello
2   John
3   Smith

1
আমি আপনার উত্তরটি ব্যবহার করেছি তবে কার্যকর হয়নি তবে আমি সংশোধন করেছি এবং এটি সকলের সাথে মিলিত হয়েছে, আমি
দেবদূত

9

আমি ফ্রেডেরিকের উত্তরটি ব্যবহার করি তবে এটি এসকিউএল সার্ভার 2005-এ কাজ করে না

আমি এটা পরিবর্তিত এবং আমি ব্যবহার করছি selectসঙ্গে union allএবং এটি কাজ করে

DECLARE @str varchar(max)
SET @str = 'Hello John Smith how are you'

DECLARE @separator varchar(max)
SET @separator = ' '

DECLARE @Splited table(id int IDENTITY(1,1), item varchar(max))

SET @str = REPLACE(@str, @separator, ''' UNION ALL SELECT ''')
SET @str = ' SELECT  ''' + @str + '''  ' 

INSERT INTO @Splited
EXEC(@str)

SELECT * FROM @Splited

এবং ফলাফল সেট:

id  item
1   Hello
2   John
3   Smith
4   how
5   are
6   you

এটি সত্যিই দুর্দান্ত যে আমি কখনই স্কল স্টাফগুলিতে দেখেছি, এটি আমার কাজের জন্য কাজ করেছে এবং আমি তার প্রশংসা করি, ধন্যবাদ!
আব্দুররহমান আই।

আমি এটি দেখে সত্যিই উত্তেজিত হয়েছি কারণ এটি দেখতে এত পরিষ্কার এবং সহজেই বোঝা যায়, তবে দুর্ভাগ্যক্রমে আপনি এটি কোনও ইউডিএফের ভিতরে রাখতে পারেন না EXECEXECস্পষ্টতই একটি সঞ্চিত প্রক্রিয়া কল করে এবং আপনি ইউডিএফগুলিতে সঞ্চিত পদ্ধতি ব্যবহার করতে পারবেন না।
ক্রিস্টেন হাম্মাক

এটি পুরোপুরি কাজ করে !! আমি এখান থেকে একটি ফাংশন (স্প্লিটসট্রিংস_মডেন) ব্যবহারের দিকে তাকিয়ে ছিলাম: sqlperformance.com/2012/07/t-sql-queries/split-strings# মন্তব্য যে এটি করে এবং ডেটা বিভক্ত করতে এবং ফিরে আসতে দেড় মিনিট সময় লেগেছিল সারিগুলি যখন কেবল 4 অ্যাকাউন্ট নম্বর ব্যবহার করে। আমি অ্যাকাউন্টে নম্বরগুলির ডেটা সহ টেবিলে বাম জোড় দিয়ে আপনার সংস্করণটি পরীক্ষা করেছি এবং এটি 2 বা 3 সেকেন্ডের মতো লেগেছে! বিশাল পার্থক্য এবং নির্দ্বিধায় কাজ করে! আমি যদি সম্ভব হয় এই 20 টি ভোট দিতে!
ম্যাট 18

8

এই প্যাটার্নটি সূক্ষ্মভাবে কাজ করে এবং আপনি সাধারণীকরণ করতে পারেন

Convert(xml,'<n>'+Replace(FIELD,'.','</n><n>')+'</n>').value('(/n[INDEX])','TYPE')
                          ^^^^^                                   ^^^^^     ^^^^

FIELD , INDEX এবং টাইপ নোট করুন ।

আইডেন্টিফায়ারদের মতো কিছু টেবিল দিন

sys.message.1234.warning.A45
sys.message.1235.error.O98
....

তারপরে, আপনি লিখতে পারেন

SELECT Source         = q.value('(/n[1])', 'varchar(10)'),
       RecordType     = q.value('(/n[2])', 'varchar(20)'),
       RecordNumber   = q.value('(/n[3])', 'int'),
       Status         = q.value('(/n[4])', 'varchar(5)')
FROM   (
         SELECT   q = Convert(xml,'<n>'+Replace(fieldName,'.','</n><n>')+'</n>')
         FROM     some_TABLE
       ) Q

বিভাজন এবং সমস্ত অংশ ingালাই।


এটি এখানে একমাত্র সমাধান যা আপনাকে নির্দিষ্ট ধরণের জন্য toালাই করতে দেয় এবং মাঝারিভাবে দক্ষ (সিএলআর এখনও সবচেয়ে দক্ষ, তবে এই পদ্ধতিটি প্রায় 9 মিনিটে একটি 8 জিবি, 10 টোকেন, 10 এম সারি টেবিল পরিচালনা করে (অ্যাউস এম 3 সার্ভার, 4 কে আইপস) প্রভিশনড ড্রাইভ)
অ্যান্ড্রু হিল

7

আপনার ডাটাবেস 130 বা উচ্চতর এর সামঞ্জস্য স্তর থাকে তারপর আপনি ব্যবহার করতে পারেন STRING_SPLIT সহ ফাংশন OFFSET আনা সূচী দ্বারা নির্দিষ্ট আইটেম পেতে ক্লজ।

সূচক এন (শূন্য ভিত্তিক) এ আইটেমটি পেতে , আপনি নিম্নলিখিত কোডটি ব্যবহার করতে পারেন

SELECT value
FROM STRING_SPLIT('Hello John Smith',' ')
ORDER BY (SELECT NULL)
OFFSET N ROWS
FETCH NEXT 1 ROWS ONLY

আপনার ডাটাবেসের সামঞ্জস্যের স্তরটি পরীক্ষা করতে , এই কোডটি কার্যকর করুন:

SELECT compatibility_level  
FROM sys.databases WHERE name = 'YourDBName';

কৌতুকটি অফসট 1 রো এর মধ্যে রয়েছে যা প্রথম আইটেমটি এড়িয়ে যাবে এবং দ্বিতীয় আইটেমটি ফিরিয়ে দেবে। যদি আপনার সূচকগুলি 0-ভিত্তিক হয় এবং আপনি যে আইটেম সূচকটি পেতে চান তা @ এক্স যদি পরিবর্তনশীল হয় তবে আপনি অবশ্যই @ এক্স ROWS
গর্গী রানকোভস্কি

ঠিক আছে, এটি আগে ব্যবহার করিনি ... জানতে xmlপেরে ভাল লাগল ... আমি এখনও -স্প্লিট ভিত্তিক পদ্ধতির পছন্দ করব , কারণ এটি মান টাইপ-নিরাপদ আনতে দেয় এবং সাব-কোয়েরির প্রয়োজন হয় না, তবে এটি একটি ভাল একটা. আমার পক্ষ থেকে +1
শ্রুনুগো

3
এখানে সমস্যা হ'ল STRING_SPLIT ফেরত ফলাফলের আদেশের গ্যারান্টি দেয় না। সুতরাং আপনার আইটেম 1 আমার আইটেম 1 বা নাও হতে পারে।
ব্যবহারকারীর 1443098

@ গর্জিআরঙ্কভস্কি, ভি STRING_SPLIT2016 + এর জন্য দাবি ব্যবহার করে । এই ক্ষেত্রে এটি অনেক ব্যবহার করাই ভালো OPENJSONবা JSON_VALUE। আপনি আমার উত্তরটি চেক
শ্নুগো

6

আমি নেটে সমাধান খুঁজছিলাম এবং নীচে আমার জন্য কাজ করে। সূত্র

এবং আপনি এইভাবে ফাংশন কল:

SELECT * FROM dbo.split('ram shyam hari gopal',' ')

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE FUNCTION [dbo].[Split](@String VARCHAR(8000), @Delimiter CHAR(1))       
RETURNS @temptable TABLE (items VARCHAR(8000))       
AS       
BEGIN       
    DECLARE @idx INT       
    DECLARE @slice VARCHAR(8000)        
    SELECT @idx = 1       
    IF len(@String)<1 OR @String IS NULL  RETURN       
    WHILE @idx!= 0       
    BEGIN       
        SET @idx = charindex(@Delimiter,@String)       
        IF @idx!=0       
            SET @slice = LEFT(@String,@idx - 1)       
        ELSE       
            SET @slice = @String       
        IF(len(@slice)>0)  
            INSERT INTO @temptable(Items) VALUES(@slice)       
        SET @String = RIGHT(@String,len(@String) - @idx)       
        IF len(@String) = 0 break       
    END   
    RETURN       
END

আপনি এই ফাংশনটি ব্যবহার করে সহজেই এনথ আইটেমটি অ্যাক্সেস করতে পারবেন না।
Björn Lindqvist

6

তবুও অন্য ডিলিমিটার ফাংশন দ্বারা স্ট্রিংয়ের n'th অংশ পান:

create function GetStringPartByDelimeter (
    @value as nvarchar(max),
    @delimeter as nvarchar(max),
    @position as int
) returns NVARCHAR(MAX) 
AS BEGIN
    declare @startPos as int
    declare @endPos as int
    set @endPos = -1
    while (@position > 0 and @endPos != 0) begin
        set @startPos = @endPos + 1
        set @endPos = charindex(@delimeter, @value, @startPos)

        if(@position = 1) begin
            if(@endPos = 0)
                set @endPos = len(@value) + 1

            return substring(@value, @startPos, @endPos - @startPos)
        end

        set @position = @position - 1
    end

    return null
end

এবং ব্যবহার:

select dbo.GetStringPartByDelimeter ('a;b;c;d;e', ';', 3)

যা প্রত্যাবর্তন করে:

c

আপনার পরে একটিটি বিশ্লেষণযোগ্য টেবিল পাওয়ার বিপরীতে একটি একক সাবস্ট্রিং ফিরিয়ে দেওয়ার বিকল্প হিসাবে আমি এই সমাধানটি পছন্দ করি। টেবিলের ফলাফল ব্যবহারের এর ব্যবহার রয়েছে তবে আমার যা প্রয়োজন এটির জন্য পুরোপুরি কাজ করে।
জেমস এইচ

5

এটা চেষ্টা কর:

CREATE function [SplitWordList]
(
 @list varchar(8000)
)
returns @t table 
(
 Word varchar(50) not null,
 Position int identity(1,1) not null
)
as begin
  declare 
    @pos int,
    @lpos int,
    @item varchar(100),
    @ignore varchar(100),
    @dl int,
    @a1 int,
    @a2 int,
    @z1 int,
    @z2 int,
    @n1 int,
    @n2 int,
    @c varchar(1),
    @a smallint
  select 
    @a1 = ascii('a'),
    @a2 = ascii('A'),
    @z1 = ascii('z'),
    @z2 = ascii('Z'),
    @n1 = ascii('0'),
    @n2 = ascii('9')
  set @ignore = '''"'
  set @pos = 1
  set @dl = datalength(@list)
  set @lpos = 1
  set @item = ''
  while (@pos <= @dl) begin
    set @c = substring(@list, @pos, 1)
    if (@ignore not like '%' + @c + '%') begin
      set @a = ascii(@c)
      if ((@a >= @a1) and (@a <= @z1))  
        or ((@a >= @a2) and (@a <= @z2))
        or ((@a >= @n1) and (@a <= @n2))
      begin
        set @item = @item + @c
      end else if (@item > '') begin
        insert into @t values (@item)
        set @item = ''
      end
    end 
    set @pos = @pos + 1
  end
  if (@item > '') begin
    insert into @t values (@item)
  end
  return
end

এটি পরীক্ষা করুন:

select * from SplitWordList('Hello John Smith')

আমি এটি পেরেছি এবং এটি আমার যা ইচ্ছা তা পুরোপুরি! এমনকি আমি বেছে নেওয়া বিশেষ চরিত্রগুলি উপেক্ষা করার জন্য এটিও কাস্টমাইজ করতে পারি!
বিকাশ

5

নিম্নলিখিত উদাহরণটিতে একটি পুনরাবৃত্ত সিটিই ব্যবহার করা হয়েছে

আপডেট 18.09.2013

CREATE FUNCTION dbo.SplitStrings_CTE(@List nvarchar(max), @Delimiter nvarchar(1))
RETURNS @returns TABLE (val nvarchar(max), [level] int, PRIMARY KEY CLUSTERED([level]))
AS
BEGIN
;WITH cte AS
 (
  SELECT SUBSTRING(@List, 0, CHARINDEX(@Delimiter,  @List + @Delimiter)) AS val,
         CAST(STUFF(@List + @Delimiter, 1, CHARINDEX(@Delimiter, @List + @Delimiter), '') AS nvarchar(max)) AS stval, 
         1 AS [level]
  UNION ALL
  SELECT SUBSTRING(stval, 0, CHARINDEX(@Delimiter, stval)),
         CAST(STUFF(stval, 1, CHARINDEX(@Delimiter, stval), '') AS nvarchar(max)),
         [level] + 1
  FROM cte
  WHERE stval != ''
  )
  INSERT @returns
  SELECT REPLACE(val, ' ','' ) AS val, [level]
  FROM cte
  WHERE val > ''
  RETURN
END

এসকিউএলফিডেলে ডেমো


2


    Alter Function dbo.fn_Split
    (
    @Expression nvarchar(max),
    @Delimiter  nvarchar(20) = ',',
    @Qualifier  char(1) = Null
    )
    RETURNS @Results TABLE (id int IDENTITY(1,1), value nvarchar(max))
    AS
    BEGIN
       /* USAGE
            Select * From dbo.fn_Split('apple pear grape banana orange honeydew cantalope 3 2 1 4', ' ', Null)
            Select * From dbo.fn_Split('1,abc,"Doe, John",4', ',', '"')
            Select * From dbo.fn_Split('Hello 0,"&""&&&&', ',', '"')
       */

       -- Declare Variables
       DECLARE
          @X     xml,
          @Temp  nvarchar(max),
          @Temp2 nvarchar(max),
          @Start int,
          @End   int

       -- HTML Encode @Expression
       Select @Expression = (Select @Expression For XML Path(''))

       -- Find all occurences of @Delimiter within @Qualifier and replace with |||***|||
       While PATINDEX('%' + @Qualifier + '%', @Expression) > 0 AND Len(IsNull(@Qualifier, '')) > 0
       BEGIN
          Select
             -- Starting character position of @Qualifier
             @Start = PATINDEX('%' + @Qualifier + '%', @Expression),
             -- @Expression starting at the @Start position
             @Temp = SubString(@Expression, @Start + 1, LEN(@Expression)-@Start+1),
             -- Next position of @Qualifier within @Expression
             @End = PATINDEX('%' + @Qualifier + '%', @Temp) - 1,
             -- The part of Expression found between the @Qualifiers
             @Temp2 = Case When @End < 0 Then @Temp Else Left(@Temp, @End) End,
             -- New @Expression
             @Expression = REPLACE(@Expression,
                                   @Qualifier + @Temp2 + Case When @End < 0 Then '' Else @Qualifier End,
                                   Replace(@Temp2, @Delimiter, '|||***|||')
                           )
       END

       -- Replace all occurences of @Delimiter within @Expression with '</fn_Split><fn_Split>'
       -- And convert it to XML so we can select from it
       SET
          @X = Cast('<fn_Split>' +
                    Replace(@Expression, @Delimiter, '</fn_Split><fn_Split>') +
                    '</fn_Split>' as xml)

       -- Insert into our returnable table replacing '|||***|||' back to @Delimiter
       INSERT @Results
       SELECT
          "Value" = LTRIM(RTrim(Replace(C.value('.', 'nvarchar(max)'), '|||***|||', @Delimiter)))
       FROM
          @X.nodes('fn_Split') as X(C)

       -- Return our temp table
       RETURN
    END

2

আপনি কোনও ফাংশনের প্রয়োজন ছাড়াই এসকিউএলে একটি স্ট্রিং বিভক্ত করতে পারেন:

DECLARE @bla varchar(MAX)
SET @bla = 'BED40DFC-F468-46DD-8017-00EF2FA3E4A4,64B59FC5-3F4D-4B0E-9A48-01F3D4F220B0,A611A108-97CA-42F3-A2E1-057165339719,E72D95EA-578F-45FC-88E5-075F66FD726C'

-- http://stackoverflow.com/questions/14712864/how-to-query-values-from-xml-nodes
SELECT 
    x.XmlCol.value('.', 'varchar(36)') AS val 
FROM 
(
    SELECT 
    CAST('<e>' + REPLACE(@bla, ',', '</e><e>') + '</e>' AS xml) AS RawXml
) AS b 
CROSS APPLY b.RawXml.nodes('e') x(XmlCol);

আপনার যদি নির্বিচারে স্ট্রিংগুলি সমর্থন করতে হয় (এক্সএমএল বিশেষ অক্ষর সহ)

DECLARE @bla NVARCHAR(MAX)
SET @bla = '<html>unsafe & safe Utf8CharsDon''tGetEncoded ÄöÜ - "Conex"<html>,Barnes & Noble,abc,def,ghi'

-- http://stackoverflow.com/questions/14712864/how-to-query-values-from-xml-nodes
SELECT 
    x.XmlCol.value('.', 'nvarchar(MAX)') AS val 
FROM 
(
    SELECT 
    CAST('<e>' + REPLACE((SELECT @bla FOR XML PATH('')), ',', '</e><e>') + '</e>' AS xml) AS RawXml
) AS b 
CROSS APPLY b.RawXml.nodes('e') x(XmlCol); 

1

আমি জানি এটি একটি পুরানো প্রশ্ন, তবে আমি মনে করি যে কেউ আমার সমাধান থেকে উপকৃত হতে পারে।

select 
SUBSTRING(column_name,1,CHARINDEX(' ',column_name,1)-1)
,SUBSTRING(SUBSTRING(column_name,CHARINDEX(' ',column_name,1)+1,LEN(column_name))
    ,1
    ,CHARINDEX(' ',SUBSTRING(column_name,CHARINDEX(' ',column_name,1)+1,LEN(column_name)),1)-1)
,SUBSTRING(SUBSTRING(column_name,CHARINDEX(' ',column_name,1)+1,LEN(column_name))
    ,CHARINDEX(' ',SUBSTRING(column_name,CHARINDEX(' ',column_name,1)+1,LEN(column_name)),1)+1
    ,LEN(column_name))
from table_name

এসকিউএল ফিডল

সুবিধাদি:

  • এটি '' দ্বারা 3 টি সাব-স্ট্রিং ডিলিমিনেটর পৃথক করে।
  • লুপ চলাকালীন একজনকে অবশ্যই ব্যবহার করা উচিত নয়, কারণ এটি কর্মক্ষমতা হ্রাস করে।
  • পিভোটের দরকার নেই কারণ সমস্ত ফলস্বরূপ সাব-স্ট্রিংগুলি একটি সারিতে প্রদর্শিত হবে

সীমাবদ্ধতা:

  • মোট নংটি অবশ্যই জেনে রাখা উচিত। স্পেসের (উপ-স্ট্রিং)।

দ্রষ্টব্য : সমাধানটি এন-তে সাব-স্ট্রিং দিতে পারে the

সীমাবদ্ধতা কাটিয়ে উঠতে আমরা নিম্নলিখিত রেফ ব্যবহার করতে পারি ।

তবে আবার উপরের সমাধানটি কোনও সারণীতে ব্যবহার করা যাবে না (অ্যাক্টোলি আমি এটি ব্যবহার করতে পারিনি)।

আবার আমি আশা করি এই সমাধানটি কারওর পক্ষে সহায়তা করতে পারে।

আপডেট করুন: রেকর্ডস যদি> 50000 তা না হয় যুক্তিযুক্ত ব্যবহার করতে LOOPSযেমন ধ্বংস করে দেবে পারফরমেন্স


1

TVFপুনরাবৃত্তির সাহায্যে বিশুদ্ধ সেট-ভিত্তিক সমাধান CTE। আপনি JOINএবং APPLYযে কোনও ডেটাসেটে এই ফাংশনটি করতে পারেন ।

create function [dbo].[SplitStringToResultSet] (@value varchar(max), @separator char(1))
returns table
as return
with r as (
    select value, cast(null as varchar(max)) [x], -1 [no] from (select rtrim(cast(@value as varchar(max))) [value]) as j
    union all
    select right(value, len(value)-case charindex(@separator, value) when 0 then len(value) else charindex(@separator, value) end) [value]
    , left(r.[value], case charindex(@separator, r.value) when 0 then len(r.value) else abs(charindex(@separator, r.[value])-1) end ) [x]
    , [no] + 1 [no]
    from r where value > '')

select ltrim(x) [value], [no] [index] from r where x is not null;
go

ব্যবহার:

select *
from [dbo].[SplitStringToResultSet]('Hello John Smith', ' ')
where [index] = 1;

ফলাফল:

value   index
-------------
John    1

1

প্রায় সমস্ত অন্যান্য উত্তরগুলি স্ট্রিংকে বিভক্ত হয়ে প্রতিস্থাপন করে যা সিপিইউ চক্রকে নষ্ট করে এবং অপ্রয়োজনীয় মেমরি বরাদ্দ করে।

আমি এখানে স্ট্রিং বিভক্ত করার আরও অনেক ভাল উপায় কভার করেছি: http://www.digitalruby.com/split-string-sql-server/

কোডটি এখানে:

SET NOCOUNT ON

-- You will want to change nvarchar(MAX) to nvarchar(50), varchar(50) or whatever matches exactly with the string column you will be searching against
DECLARE @SplitStringTable TABLE (Value nvarchar(MAX) NOT NULL)
DECLARE @StringToSplit nvarchar(MAX) = 'your|string|to|split|here'
DECLARE @SplitEndPos int
DECLARE @SplitValue nvarchar(MAX)
DECLARE @SplitDelim nvarchar(1) = '|'
DECLARE @SplitStartPos int = 1

SET @SplitEndPos = CHARINDEX(@SplitDelim, @StringToSplit, @SplitStartPos)

WHILE @SplitEndPos > 0
BEGIN
    SET @SplitValue = SUBSTRING(@StringToSplit, @SplitStartPos, (@SplitEndPos - @SplitStartPos))
    INSERT @SplitStringTable (Value) VALUES (@SplitValue)
    SET @SplitStartPos = @SplitEndPos + 1
    SET @SplitEndPos = CHARINDEX(@SplitDelim, @StringToSplit, @SplitStartPos)
END

SET @SplitValue = SUBSTRING(@StringToSplit, @SplitStartPos, 2147483647)
INSERT @SplitStringTable (Value) VALUES(@SplitValue)

SET NOCOUNT OFF

-- You can select or join with the values in @SplitStringTable at this point.

0

সার্ভারের ব্যথার সাথে পুনরাবৃত্ত সিটিই দ্রবণটি পরীক্ষা করে দেখুন

এমএস এসকিউএল সার্ভার ২০০৮ স্কিমা সেটআপ :

create table Course( Courses varchar(100) );
insert into Course values ('Hello John Smith');

প্রশ্ন 1 :

with cte as
   ( select 
        left( Courses, charindex( ' ' , Courses) ) as a_l,
        cast( substring( Courses, 
                         charindex( ' ' , Courses) + 1 , 
                         len(Courses ) ) + ' ' 
              as varchar(100) )  as a_r,
        Courses as a,
        0 as n
     from Course t
    union all
      select 
        left(a_r, charindex( ' ' , a_r) ) as a_l,
        substring( a_r, charindex( ' ' , a_r) + 1 , len(a_R ) ) as a_r,
        cte.a,
        cte.n + 1 as n
    from Course t inner join cte 
         on t.Courses = cte.a and len( a_r ) > 0

   )
select a_l, n from cte
--where N = 1

ফলাফল :

|    A_L | N |
|--------|---|
| Hello  | 0 |
|  John  | 1 |
| Smith  | 2 |

0

জোসেজুয়ানের এক্সএমএল ভিত্তিক উত্তরের অনুরূপ, আমি দেখতে পেয়েছি যে কেবলমাত্র একবার এক্সএমএল পাথ প্রসেসিং করা হয়েছে, তবে পিভোটিং মাঝারি চেয়ে আরও দক্ষ ছিল:

select ID,
    [3] as PathProvidingID,
    [4] as PathProvider,
    [5] as ComponentProvidingID,
    [6] as ComponentProviding,
    [7] as InputRecievingID,
    [8] as InputRecieving,
    [9] as RowsPassed,
    [10] as InputRecieving2
    from
    (
    select id,message,d.* from sysssislog cross apply       ( 
          SELECT Item = y.i.value('(./text())[1]', 'varchar(200)'),
              row_number() over(order by y.i) as rn
          FROM 
          ( 
             SELECT x = CONVERT(XML, '<i>' + REPLACE(Message, ':', '</i><i>') + '</i>').query('.')
          ) AS a CROSS APPLY x.nodes('i') AS y(i)
       ) d
       WHERE event
       = 
       'OnPipelineRowsSent'
    ) as tokens 
    pivot 
    ( max(item) for [rn] in ([3],[4],[5],[6],[7],[8],[9],[10]) 
    ) as data

সাড়ে আটটায় চলে গেল

select id,
tokens.value('(/n[3])', 'varchar(100)')as PathProvidingID,
tokens.value('(/n[4])', 'varchar(100)') as PathProvider,
tokens.value('(/n[5])', 'varchar(100)') as ComponentProvidingID,
tokens.value('(/n[6])', 'varchar(100)') as ComponentProviding,
tokens.value('(/n[7])', 'varchar(100)') as InputRecievingID,
tokens.value('(/n[8])', 'varchar(100)') as InputRecieving,
tokens.value('(/n[9])', 'varchar(100)') as RowsPassed
 from
(
    select id, Convert(xml,'<n>'+Replace(message,'.','</n><n>')+'</n>') tokens
         from sysssislog 
       WHERE event
       = 
       'OnPipelineRowsSent'
    ) as data

9:20 এ দৌড়েছিল


0
CREATE FUNCTION [dbo].[fnSplitString] 
( 
    @string NVARCHAR(MAX), 
    @delimiter CHAR(1) 
) 
RETURNS @output TABLE(splitdata NVARCHAR(MAX) 
) 
BEGIN 
    DECLARE @start INT, @end INT 
    SELECT @start = 1, @end = CHARINDEX(@delimiter, @string) 
    WHILE @start < LEN(@string) + 1 BEGIN 
        IF @end = 0  
            SET @end = LEN(@string) + 1

        INSERT INTO @output (splitdata)  
        VALUES(SUBSTRING(@string, @start, @end - @start)) 
        SET @start = @end + 1 
        SET @end = CHARINDEX(@delimiter, @string, @start)

    END 
    RETURN 
END

এবং এটি ব্যবহার করুন

select *from dbo.fnSplitString('Querying SQL Server','')

0

কেউ যদি বিভক্ত পাঠ্যের কেবল একটি অংশ পেতে চান তবে এটি ব্যবহার করতে পারেন

* স্প্লিটস্ট্রিংসপ থেকে নির্বাচন করুন ('ওয়ার্ড 1 ওয়ার্ডার 2 ওয়ার্ড 3', '')

CREATE function [dbo].[SplitStringSep] 
(
    @str nvarchar(4000), 
    @separator char(1)
)
returns table
AS
return (
    with tokens(p, a, b) AS (
        select 
        1, 
        1, 
        charindex(@separator, @str)
        union all
        select
            p + 1, 
            b + 1, 
            charindex(@separator, @str, b + 1)
        from tokens
        where b > 0
        )
        select
            p-1 zeroBasedOccurance,
            substring(
                @str, 
                a, 
                case when b > 0 then b-a ELSE 4000 end) 
            AS s
        from tokens
  )

0

আমি এটিকে ভেঙে ফেলেছি,

declare @x nvarchar(Max) = 'ali.veli.deli.';
declare @item nvarchar(Max);
declare @splitter char='.';

while CHARINDEX(@splitter,@x) != 0
begin
    set @item = LEFT(@x,CHARINDEX(@splitter,@x))
    set @x    = RIGHT(@x,len(@x)-len(@item) )
     select @item as item, @x as x;
end

আপনার কেবলমাত্র মনোযোগ ডট '' @ x এর শেষটি সর্বদা থাকা উচিত।


0

@ নোটিংসআইম্পিলিভ সমাধানটির উপর ভিত্তি করে তৈরি করা বা সর্বাধিক ভোটপ্রাপ্ত উত্তরের উপর মন্তব্য (স্বীকৃত উত্তরের ঠিক নীচে), আমি নীচের দ্রুত এবং নোংরা সমাধানটি আমার নিজের চাহিদা পূরণ করতে দেখেছি - এটি সম্পূর্ণরূপে এসকিউএল ডোমেনের মধ্যে থাকার একটি সুবিধা রয়েছে।

একটি স্ট্রিং দেওয়া হয়েছে "প্রথম; দ্বিতীয়; তৃতীয়; চতুর্থ; পঞ্চম", বলুন, আমি তৃতীয় টোকেন পেতে চাই। এটি কেবল তখনই কাজ করে যদি আমরা জানি যে স্ট্রিংটি কত টোকনে চলেছে - এই ক্ষেত্রে এটি 5 টি so সুতরাং আমার ক্রিয়াকলাপটি হ'ল শেষ দুটি টোকেন কেটে ফেলে (অভ্যন্তরীণ কোয়েরি) এবং তারপরে প্রথম দুটি টোকেন কেটে ফেলুন ( বাইরের ক্যোয়ারী)

আমি জানি যে এটি কুরুচিপূর্ণ এবং আমার যে নির্দিষ্ট শর্ত ছিল সেগুলি coversেকে রাখে তবে কারওর পক্ষে এটি কার্যকর মনে হলে এটি পোস্ট করছি। চিয়ার্স

select 
    REVERSE(
        SUBSTRING(
            reverse_substring, 
            0, 
            CHARINDEX(';', reverse_substring)
        )
    ) 
from 
(
    select 
        msg,
        SUBSTRING(
            REVERSE(msg), 
            CHARINDEX(
                ';', 
                REVERSE(msg), 
                CHARINDEX(
                    ';',
                    REVERSE(msg)
                )+1
            )+1,
            1000
        ) reverse_substring
    from 
    (
        select 'first;second;third;fourth;fifth' msg
    ) a
) b

এটি কেবলমাত্র যদি আমরা জানতে পারি যে স্ট্রিংটি কত
টোকনে চলেছে

0
declare @strng varchar(max)='hello john smith'
select (
    substring(
        @strng,
        charindex(' ', @strng) + 1,
        (
          (charindex(' ', @strng, charindex(' ', @strng) + 1))
          - charindex(' ',@strng)
        )
    ))

0

এসকিউএল সার্ভার 2016 দিয়ে শুরু করে আমরা স্ট্রিং_স্প্লিট করছি

DECLARE @string varchar(100) = 'Richard, Mike, Mark'

SELECT value FROM string_split(@string, ',')

এটি ভাল এবং ভাল, তবে এটি নবম ফলাফল প্রাপ্তির প্রশ্নটির সমাধান করে না।
জনি কার

STRING_SPLITএকই আদেশ ফেরত দেওয়ার গ্যারান্টি দেয় না। তবে OPENJSON(আমার উত্তর দেখুন (আপডেট বিভাগটি দেখুন) )
Shnugo
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.