복붙노트

[SQL] 내가 항목 X에 액세스 할 수 있도록 어떻게 문자열을 분할합니까?

SQL

내가 항목 X에 액세스 할 수 있도록 어떻게 문자열을 분할합니까?

내가 항목 X에 액세스 할 수 있도록 내가 문자열을 분할 어떻게, SQL Server를 사용?

문자열 "안녕하세요 존 스미스"를보십시오. 어떻게 "존"을 반환해야합니다 공간 및 액세스 인덱스 1의 항목으로 문자열을 분할 할 수 있습니다?

해결법

  1. ==============================

    1.있습니다 (코드 프로젝트에서) 도움이 구분 된 문자열 구문 분석에 SQL 사용자 정의 함수에서 솔루션을 찾을 수 있습니다.

    있습니다 (코드 프로젝트에서) 도움이 구분 된 문자열 구문 분석에 SQL 사용자 정의 함수에서 솔루션을 찾을 수 있습니다.

    이 간단한 논리를 사용할 수 있습니다 :

    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
    
  2. ==============================

    2.나는 SQL Server가 UDF보다 내장 분할 기능, 그래서 다른 가지고 있다고 생각하지 않는다, 내가 아는 유일한 대답은 PARSENAME 기능을 납치하는 것입니다 :

    나는 SQL Server가 UDF보다 내장 분할 기능, 그래서 다른 가지고 있다고 생각하지 않는다, 내가 아는 유일한 대답은 PARSENAME 기능을 납치하는 것입니다 :

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

    PARSENAME는 문자열을 받아 기간 문자에 분할합니다. 이것은 두 번째 인수로서 숫자를 취하고, 반환 할 문자열의 개수를 지정하는 것을 세그먼트 (정면에서 위로 작동).

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

    문자열이 이미 기간이 포함 된 경우 명백한 문제입니다. 난 여전히 UDF를 사용하여 ... 다른 제안을하는 가장 좋은 방법이라고 생각?

  3. ==============================

    3.첫째, 함수 생성 (CTE를 사용하여, 공통 테이블 표현식은 임시 테이블에 대한 필요성 페지)

    첫째, 함수 생성 (CTE를 사용하여, 공통 테이블 표현식은 임시 테이블에 대한 필요성 페지)

     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
    

    사용법은 동일하게 유지됩니다.

  4. ==============================

    4.솔루션의 대부분은 여기에있는 동안 루프 또는 재귀 CTE를 사용합니다. 세트 기반의 접근 방식은 공간보다 구분자 기타를 사용할 수 있는지 나는, 약속, 우수한 될 것입니다 :

    솔루션의 대부분은 여기에있는 동안 루프 또는 재귀 CTE를 사용합니다. 세트 기반의 접근 방식은 공간보다 구분자 기타를 사용할 수 있는지 나는, 약속, 우수한 될 것입니다 :

    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을 추가 할 수 있습니다, 그러나 나는 독자에게 연습으로 떠날 것이다.

    더 분할 기능, 왜 (그리고 증거가)에 분할 문자열은 애플리케이션 계층에서 오는 경우 루프와 재귀 CTE를하지 스케일, 그리고 더 나은 대안을 수행하는 동안 :

    위의 SQL 서버 2016에,하지만 당신은 STRING_SPLIT ()와 STRING_AGG ()를 보라 :

  5. ==============================

    5.당신은 문자열의 구문 분석을 할 수있는 번호 테이블을 활용할 수 있습니다.

    당신은 문자열의 구문 분석을 할 수있는 번호 테이블을 활용할 수 있습니다.

    실제 숫자 테이블을 작성 :

        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
    

    사용 (내 노트북에 40 대 출력 3mil 행)

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

    대청소

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

    여기에 성능은 놀라운 것이 아니라 백만 행 테이블에 함수를 호출하는 것은 좋은 생각이 아니다. 문자열을 수행하는 많은 행에 걸쳐 분할하면 나는 기능을 피할 것이다.

  6. ==============================

    6.이 질문은하지만, n 번째 요소를 얻는 방법에 대한 문자열 분할 방법에 관하여이지 않는다.

    이 질문은하지만, n 번째 요소를 얻는 방법에 대한 문자열 분할 방법에 관하여이지 않는다.

    여기에 모든 답이 재귀 CTE를 여러 CHARINDEX, REVERSE 및 PATINDEX 함수를 발명을 사용하여 문자열을 분할 어떤 종류의 일을하는, CLR 방법, 숫자 테이블, CROSS 시만에 대한 호출은 ... 대부분의 답변은 많은 코드를 다룹니다.

    유형의 안전 : - 당신이 정말로 n 번째 요소를 얻기 위해 더 접근보다는 아무것도하지 않으 - 그러나 이것은 실제 한 줄, 아니 UDF, 심지어 하위이-선택 ... 그리고 추가 혜택 등으로 수행 할 수 있습니다

    공백으로 구분 된 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을 : 열을 쿼리의 값에서 직접 위치를 검색하기 위해) :

    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)')
    

    당신의 문자열 (> <사이에서 특히 하나) 금지 문자를 포함 할 수 있습니다 경우에도 이런 식으로 할 수 있습니다. 그냥 암시 적으로 피팅 이스케이프 시퀀스 모든 금지 문자를 대체하기 위해 먼저 문자열을 XML 경로 사용합니다.

    추가 - -이 경우 아주 특수한 경우의 당신의 구분은 세미콜론입니다. 이 경우 내가 먼저 '#의 DLMT 번호'로 구분 기호를 대체하고, 마지막으로 XML 태그에이 대체 :

    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)');
    

    유감스럽게도 개발자는 STRING_SPLIT와 부분의 인덱스를 반환하는 것을 잊었다. 그러나, SQL-Server를 2016+ 사용 JSON_VALUE 및 OPENJSON있다.

    JSON_VALUE으로 우리는 인덱스 '배열과 위치에 전달할 수있다.

    OPENJSON에 대한 설명서 명확하게 진술한다 :

    1,2,3 같은 문자열은 괄호보다 더 아무것도 필요하지 않습니다 : [1,2,3]. 이와 같은 단어의 문자열 [ "이", "에", "예" "는"일례 필요가있을 것이다. 이들은 매우 쉽게 문자열 연산입니다. 그냥 그것을 밖으로 시도 :

    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 정말 빠른 것으로, 다양한 방법을 시험하고 발견했다. 심지어 훨씬 더 빨리 유명한 "delimitedSplit8k ()"방법보다 ...

    우리는 단순히 배로 []를 사용하여 어레이 내에 배열을 사용할 수있다. 이것은 입력 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
    
  7. ==============================

    7.여기에 그것을 할 것 UDF이다. 그것은 구분 된 값의 테이블, 거기에 모든 시나리오를 시도하지 않은하지만 예를 잘 작동 반환합니다.

    여기에 그것을 할 것 UDF이다. 그것은 구분 된 값의 테이블, 거기에 모든 시나리오를 시도하지 않은하지만 예를 잘 작동 반환합니다.

    
    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',' ')
    

    편집하십시오 LEN> 1과와 핸들 delimters에 업데이트 솔루션 :

    
    select * From SplitString('Hello**John**Smith','**')
    
  8. ==============================

    8.여기에 내가 솔루션의 간단한 방법을 게시

    여기에 내가 솔루션의 간단한 방법을 게시

    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',' ')
    
  9. ==============================

    9.제 생각에는 너희들은 너무 복잡하고 있습니다. 그냥 CLR UDF를 작성하고 함께 할 수.

    제 생각에는 너희들은 너무 복잡하고 있습니다. 그냥 CLR UDF를 작성하고 함께 할 수.

    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()));
      }
    };
    
  10. ==============================

    10.무엇 문자열 값 () 문을 사용하는 방법에 대한?

    무엇 문자열 값 () 문을 사용하는 방법에 대한?

    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
    
  11. ==============================

    11.나는 프레드릭의 대답을 사용하지만이 SQL Server 2005에서 작동하지 않았다

    나는 프레드릭의 대답을 사용하지만이 SQL Server 2005에서 작동하지 않았다

    나는 그것을 수정하고 나는 모든 조합으로 선택 사용하고 있는데 작동

    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
    
  12. ==============================

    12.이 패턴은 잘 작동하고 당신은 일반화 할 수 있습니다

    이 패턴은 잘 작동하고 당신은 일반화 할 수 있습니다

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

    FIELD, INDEX 및 TYPE을 확인합니다.

    같은 식별자 일부 테이블을 보자

    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
    

    분할 및 모든 부품을 주조.

  13. ==============================

    13.데이터베이스가 130 이상 호환성 수준이있는 경우 당신은 인덱스로 특정 아이템을 얻기 위해 절을 FETCH OFFSET과 함께 STRING_SPLIT 기능을 사용할 수 있습니다.

    데이터베이스가 130 이상 호환성 수준이있는 경우 당신은 인덱스로 특정 아이템을 얻기 위해 절을 FETCH OFFSET과 함께 STRING_SPLIT 기능을 사용할 수 있습니다.

    인덱스 N (영 기준)에있는 항목을 얻으려면, 다음과 같은 코드를 사용할 수 있습니다

    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';
    
  14. ==============================

    14.나는 나를 위해 작품 아래의 그물에 솔루션과 찾고 있었다. 참조.

    나는 나를 위해 작품 아래의 그물에 솔루션과 찾고 있었다. 참조.

    그리고이 같은 함수를 호출 :

    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
    
  15. ==============================

    15.또 다른 구분 기호 기능에 의해 문자열의 n 번째 부분을 얻을 :

    또 다른 구분 기호 기능에 의해 문자열의 n 번째 부분을 얻을 :

    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
    
  16. ==============================

    16.이 시도:

    이 시도:

    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')
    
  17. ==============================

    17.다음 예는 재귀 CTE를 사용

    다음 예는 재귀 CTE를 사용

    업데이트 2013년 9월 18일

    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
    

    SQLFiddle에 데모

  18. ==============================

    18.

    
    
        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 &LT; 0 Then @Temp Else Left(@Temp, @End) End,
                 -- New @Expression
                 @Expression = REPLACE(@Expression,
                                       @Qualifier + @Temp2 + Case When @End &LT; 0 Then '' Else @Qualifier End,
                                       Replace(@Temp2, @Delimiter, '|||***|||')
                               )
           END
    
           -- Replace all occurences of @Delimiter within @Expression with '</fn_Split>&ltfn;_Split>'
           -- And convert it to XML so we can select from it
           SET
              @X = Cast('&ltfn;_Split>' +
                        Replace(@Expression, @Delimiter, '</fn_Split>&ltfn;_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
    
    
  19. ==============================

    19.나는 오래된 질문 알아요,하지만 난 어떤 사람이 내 솔루션 혜택을 누릴 수 있다고 생각합니다.

    나는 오래된 질문 알아요,하지만 난 어떤 사람이 내 솔루션 혜택을 누릴 수 있다고 생각합니다.

    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
    

    SQL 뿐인

    장점 :

    제한 사항 :

    참고 :이 솔루션은 N.에로 하위 문자열을 제공 할 수 있습니다

    한계를 극복하기 위해 우리는 다음과 같은 심판을 사용할 수 있습니다.

    그러나 다시 위의 솔루션은 테이블에서 사용 할 수 없습니다 (Actaully 내가 그것을 사용할 수 없습니다).

    다시 나는이 솔루션은 일부-일을 도울 수 있기를 바랍니다.

    업데이트 : 기록의 경우는> 50000 성능이 저하됩니다로 루프를 사용하지 않는 것이 좋습니다

  20. ==============================

    20.거의 모든 다른 응답 코드 분할은 폐기물 CPU 사이클을 수행하고, 불필요한 메모리 할당 문자열 인 분할을 대체하고있다.

    거의 모든 다른 응답 코드 분할은 폐기물 CPU 사이클을 수행하고, 불필요한 메모리 할당 문자열 인 분할을 대체하고있다.

    여기 문자열 분할을 할 수있는 더 나은 방법을 다룹니다 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.
    
  21. ==============================

    21.당신은 기능을하지 않고도 SQL에서 문자열을 분할 할 수 있습니다 :

    당신은 기능을하지 않고도 SQL에서 문자열을 분할 할 수 있습니다 :

    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);
    

    당신은 임의의 문자열을 지원해야하는 경우 (XML 특수 문자 포함)

    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); 
    
  22. ==============================

    22.재귀 CTE와 TVF를 사용하여 순수 세트 기반의 솔루션입니다. 당신은 가입하고 데이터 세트에이 기능을 적용 할 수 있습니다.

    재귀 CTE와 TVF를 사용하여 순수 세트 기반의 솔루션입니다. 당신은 가입하고 데이터 세트에이 기능을 적용 할 수 있습니다.

    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
    
  23. ==============================

    23.SQL 서버 2016 우리의 string_split 시작

    SQL 서버 2016 우리의 string_split 시작

    DECLARE @string varchar(100) = 'Richard, Mike, Mark'
    
    SELECT value FROM string_split(@string, ',')
    
  24. ==============================

    24.STRING_SPLIT을 사용하여 현대적인 접근 방식은 SQL 서버 2016 이상이 필요합니다.

    STRING_SPLIT을 사용하여 현대적인 접근 방식은 SQL 서버 2016 이상이 필요합니다.

    DECLARE @string varchar(100) = 'Hello John Smith'
    
    SELECT
        ROW_NUMBER() OVER (ORDER BY value) AS RowNr,
        value
    FROM string_split(@string, ' ')
    

    결과:

    RowNr   value
    1       Hello
    2       John
    3       Smith
    

    지금은 행 번호에서 n 번째 요소를 얻을 수 있습니다.

  25. ==============================

    25.아론 버트 랜드의 대답은 잘하지만 결함이있다. 길이 기능이 후행 공백을 제거합니다 때문에 (원래의 질문의 예이었다로) 그것은 정확하게 구분 기호로 공백을 처리하지 않습니다.

    아론 버트 랜드의 대답은 잘하지만 결함이있다. 길이 기능이 후행 공백을 제거합니다 때문에 (원래의 질문의 예이었다로) 그것은 정확하게 구분 기호로 공백을 처리하지 않습니다.

    다음은 공간 구분 수 있도록 작은 조정과 함께, 자신의 코드입니다 :

    CREATE FUNCTION [dbo].[SplitString]
    (
        @List NVARCHAR(MAX),
        @Delim VARCHAR(255)
    )
    RETURNS TABLE
    AS
        RETURN ( SELECT [Value] FROM 
          ( 
            SELECT 
              [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+'x')-1) = @Delim
          ) AS y
        );
    
  26. ==============================

    26.여기에 분할 문자열 및 접근 항목 X의 문제의 목표를 달성하는 기능은 다음과 같습니다

    여기에 분할 문자열 및 접근 항목 X의 문제의 목표를 달성하는 기능은 다음과 같습니다

    CREATE FUNCTION [dbo].[SplitString]
    (
       @List       VARCHAR(MAX),
       @Delimiter  VARCHAR(255),
       @ElementNumber INT
    )
    RETURNS VARCHAR(MAX)
    AS
    BEGIN
    
           DECLARE @inp VARCHAR(MAX)
           SET @inp = (SELECT REPLACE(@List,@Delimiter,'_DELMTR_') FOR XML PATH(''))
    
           DECLARE @xml XML
           SET @xml = '<split><el>' + REPLACE(@inp,'_DELMTR_','</el><el>') + '</el></split>'
    
           DECLARE @ret VARCHAR(MAX)
           SET @ret = (SELECT
                  el = split.el.value('.','varchar(max)')
           FROM  @xml.nodes('/split/el[string-length(.)>0][position() = sql:variable("@elementnumber")]') split(el))
    
           RETURN @ret
    
    END
    

    용법:

    SELECT dbo.SplitString('Hello John Smith', ' ', 2)
    

    결과:

    John
    
  27. ==============================

    27.구문 분석 이름과 성을위한 간단한 솔루션

    구문 분석 이름과 성을위한 간단한 솔루션

    DECLARE @Name varchar(10) = 'John Smith'
    
    -- Get First Name
    SELECT SUBSTRING(@Name, 0, (SELECT CHARINDEX(' ', @Name)))
    
    -- Get Last Name
    SELECT SUBSTRING(@Name, (SELECT CHARINDEX(' ', @Name)) + 1, LEN(@Name))
    

    내 경우에는 (그리고 보이는 많은 사람들이 ...에), 나는 하나의 공백으로 구분하여 성과 이름의 목록을 가지고있다. 이것은 성과 이름을 구문 분석하는 SELECT 문 내에서 직접 사용할 수 있습니다.

    -- i.e. Get First and Last Name from a table of Full Names
    SELECT SUBSTRING(FullName, 0, (SELECT CHARINDEX(' ', FullName))) as FirstName,
    SUBSTRING(FullName, (SELECT CHARINDEX(' ', FullName)) + 1, LEN(FullName)) as LastName,
    From FullNameTable
    
  28. ==============================

    28.나는 그 말을 알아,하지만 나는 최근에 이러한 요구 사항을했고, 아래의 코드를 함께했다. 나는 사용자 정의 기능을 사용하기 위해서는 선택의 여지가 없어. 도움이 되었기를 바랍니다.

    나는 그 말을 알아,하지만 나는 최근에 이러한 요구 사항을했고, 아래의 코드를 함께했다. 나는 사용자 정의 기능을 사용하기 위해서는 선택의 여지가 없어. 도움이 되었기를 바랍니다.

    SELECT 
        SUBSTRING(
                    SUBSTRING('Hello John Smith' ,0,CHARINDEX(' ','Hello John Smith',CHARINDEX(' ','Hello John Smith')+1)
                            ),CHARINDEX(' ','Hello John Smith'),LEN('Hello John Smith')
                )
    
  29. ==============================

    29.글쎄, 내 모든 것을 간단 아니지만, 여기에 내가 개별 값에 쉼표로 구분 된 입력 변수를 분할하고, 테이블 변수에 넣어하는 데 사용하는 코드입니다. 나는 당신이 당신의 결과를 얻기 위해 해당 테이블 변수에 대한 기본 SELECT 쿼리를 수행 한 후 약간이를 수정할 수있는 공간을 기준으로 분할하고 확신합니다.

    글쎄, 내 모든 것을 간단 아니지만, 여기에 내가 개별 값에 쉼표로 구분 된 입력 변수를 분할하고, 테이블 변수에 넣어하는 데 사용하는 코드입니다. 나는 당신이 당신의 결과를 얻기 위해 해당 테이블 변수에 대한 기본 SELECT 쿼리를 수행 한 후 약간이를 수정할 수있는 공간을 기준으로 분할하고 확신합니다.

    -- Create temporary table to parse the list of accounting cycles.
    DECLARE @tblAccountingCycles table
    (
        AccountingCycle varchar(10)
    )
    
    DECLARE @vchAccountingCycle varchar(10)
    DECLARE @intPosition int
    
    SET @vchAccountingCycleIDs = LTRIM(RTRIM(@vchAccountingCycleIDs)) + ','
    SET @intPosition = CHARINDEX(',', @vchAccountingCycleIDs, 1)
    
    IF REPLACE(@vchAccountingCycleIDs, ',', '') <> ''
    BEGIN
        WHILE @intPosition > 0
        BEGIN
            SET @vchAccountingCycle = LTRIM(RTRIM(LEFT(@vchAccountingCycleIDs, @intPosition - 1)))
            IF @vchAccountingCycle <> ''
            BEGIN
                INSERT INTO @tblAccountingCycles (AccountingCycle) VALUES (@vchAccountingCycle)
            END
            SET @vchAccountingCycleIDs = RIGHT(@vchAccountingCycleIDs, LEN(@vchAccountingCycleIDs) - @intPosition)
            SET @intPosition = CHARINDEX(',', @vchAccountingCycleIDs, 1)
        END
    END
    

    개념은 거의 동일합니다. 또 다른 대안은 SQL Server 2005의 자체 내에서 .NET 호환성을 활용하는 것입니다. 당신은 기본적으로 자신에게 문자열을 분할 한 다음 저장 프로 시저 / 함수로 그 노출 될 수 .NET에서 간단한 방법을 쓸 수 있습니다.

  30. ==============================

    30.이것은 내가 문자열에서 토큰을 특정을 얻기 위해했던 일이다. (2008 MSSQL에서 테스트)

    이것은 내가 문자열에서 토큰을 특정을 얻기 위해했던 일이다. (2008 MSSQL에서 테스트)

    (에서 발견 : 우선, 다음과 같은 기능을 만들어 여기에

    CREATE FUNCTION dbo.SplitStrings_Moden
    (
       @List NVARCHAR(MAX),
       @Delimiter NVARCHAR(255)
    )
    RETURNS TABLE
    WITH SCHEMABINDING AS
    RETURN
      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),
           E2(N)        AS (SELECT 1 FROM E1 a, E1 b),
           E4(N)        AS (SELECT 1 FROM E2 a, E2 b),
           E42(N)       AS (SELECT 1 FROM E4 a, E2 b),
           cteTally(N)  AS (SELECT 0 UNION ALL SELECT TOP (DATALENGTH(ISNULL(@List,1))) 
                             ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E42),
           cteStart(N1) AS (SELECT t.N+1 FROM cteTally t
                             WHERE (SUBSTRING(@List,t.N,1) = @Delimiter OR t.N = 0))
      SELECT Item = SUBSTRING(@List, s.N1, ISNULL(NULLIF(CHARINDEX(@Delimiter,@List,s.N1),0)-s.N1,8000))
        FROM cteStart s;
    

    create FUNCTION dbo.getToken
    (
    @List NVARCHAR(MAX),
    @Delimiter NVARCHAR(255),
    @Pos int
    )
    RETURNS varchar(max)
    as 
    begin
    declare @returnValue varchar(max);
    select @returnValue = tbl.Item from (
    select ROW_NUMBER() over (order by (select null)) as id, * from dbo.SplitStrings_Moden(@List, @Delimiter)
    ) as tbl
    where tbl.id = @Pos
    return @returnValue
    end
    

    당신은 그렇게 사용할 수 있습니다 :

    select dbo.getToken('1111_2222_3333_', '_', 1)
    

    1111을 반환하는

  31. from https://stackoverflow.com/questions/2647/how-do-i-split-a-string-so-i-can-access-item-x by cc-by-sa and MIT license