Wie teile ich eine Zeichenfolge, damit ich Artikel x zugreifen kann?

stimmen
442

Verwenden von SQL Server, wie kann ich einen String geteilt, so ich Artikel x zugreifen kann?

Nehmen Sie einen String Hallo John Smith. Wie kann ich teilen Sie die Zeichenfolge durch Raum und Zugriff auf das Element am Index 1, die „John“ zurückgeben sollte?

Veröffentlicht am 05/08/2008 um 19:15
quelle vom benutzer
In anderen Sprachen...                            


43 antworten

stimmen
335

Ich glaube nicht, SQL Server über eine integrierte in Split-Funktion hat, so anders als ein UDF, die einzige andere Antwort, die ich weiß, ist die ParseName Funktion kapern:

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

ParseName nimmt einen String und teilt sie auf den Zeitraum Charakter. Es dauert eine Zahl als zweites Argument, und diese Zahl gibt an, welchen Abschnitt der Zeichenfolge zurückzukehren (von hinten nach vorne in Betrieb).

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

Offensichtliches Problem ist, wenn die Zeichenfolge bereits einen Punkt enthält. Ich denke immer noch ein UDF ist der beste Weg, ... andere Vorschläge?

Beantwortet am 05/08/2008 um 19:45
quelle vom benutzer

stimmen
177

Sie können die Lösung in finden SQL User Defined Function ein Trennzeichen Zeichenfolge zu analysieren nützlich (von The Code Project ).

Sie können diese einfache Logik verwenden:

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
Beantwortet am 05/08/2008 um 19:28
quelle vom benutzer

stimmen
106

Erstellen Sie zunächst eine Funktion (unter Verwendung von CTE, allgemeiner Tabellenausdruck beseitigt die Notwendigkeit für eine temporäre Tabelle weg)

 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

Dann verwenden Sie es als jede Tabelle (oder ändern Sie es in Ihre bestehende gespeicherte Prozedur passen) wie folgt aus.

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

Aktualisieren

Vorherige Version wäre für Eingabezeichenfolge länger als 4000 Zeichen fehlschlagen. Diese Version kümmert sich um die Einschränkung:

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

Verbrauch bleibt gleich.

Beantwortet am 05/08/2008 um 19:57
quelle vom benutzer

stimmen
51

Die meisten Lösungen hier verwenden, während Schleifen oder rekursiven CTEs. Ein Set-basierter Ansatz überlegen sein wird, das verspreche ich:

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)) = @Delim
          ) AS y
        );

Mehr über Split-Funktionen, warum (und den Beweis, dass), während Schleifen und rekursive CTE nicht maßstäblich, und bessere Alternativen, wenn Splitting Strings aus der Anwendungsschicht kommen:

http://www.sqlperformance.com/2012/07/t-sql-queries/split-strings

http://www.sqlperformance.com/2012/08/t-sql-queries/splitting-strings-now-with-less-t-sql

http://sqlblog.com/blogs/aaron_bertrand/archive/2010/07/07/splitting-a-list-of-integers-another-roundup.aspx

Beantwortet am 12/11/2013 um 18:16
quelle vom benutzer

stimmen
37

Sie können eine Nummer Tabelle nutzen, um die Zeichenfolgenanalyse zu tun.

Erstellen Sie eine physikalische Zahlen Tabelle:

    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

Erstellen Sie Testtabelle mit 1000000 Reihen

    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

Erstellen Sie die Funktion

    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

Verbrauch (Ausgänge 3mil Reihen in 40er Jahren auf meinem Laptop)

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

Aufräumen

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

Performance hier ist nicht erstaunlich, aber eine Funktion über eine Million Zeilen Tabelle Aufruf ist nicht die beste Idee. Wenn die Durchführung einer Zeichenfolge viele Zeilen aufgeteilt über würde ich die Funktion vermeiden.

Beantwortet am 27/10/2008 um 17:48
quelle vom benutzer

stimmen
20

Hier ist eine UDF, die es tun werden. Es wird eine Tabelle der begrenzten Werte zurückgeben, haben nicht alle Szenarien auf es versucht, aber Ihr Beispiel funktioniert gut.


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

Sie würde es so nennen:


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

Edit: Aktualisiert Lösung zu handhaben delimters mit einem len> 1, wie in:


select * From SplitString('Hello**John**Smith','**')
Beantwortet am 05/08/2008 um 19:39
quelle vom benutzer

stimmen
16

Kein Code, aber lesen Sie den endgültigen Artikel zu diesem Thema . Alle Lösungen in anderen Antworten sind Aromen von denen , die in diesem Artikel aufgeführt: Arrays und Listen in SQL Server 2005 und darüber hinaus

Persönlich habe ich eine Numbers Tabellen Lösung am häufigsten verwendet, weil sie paßt, was ich zu tun habe ...

Beantwortet am 26/09/2010 um 14:44
quelle vom benutzer

stimmen
15

Hier schreibe ich eine einfache Art und Weise der Lösung

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 IGNORE  INTO @t(val)
          SELECT  r.value('.','varchar(MAX)') as item
          FROM  @xml.nodes('/t') as records(r)
          RETURN
        END


Führen Sie die Funktion wie folgt aus

  select * from dbo.split('Hello John Smith',' ')
Beantwortet am 30/01/2013 um 10:41
quelle vom benutzer

stimmen
12

Diese Frage ist nicht über einen String Split - Ansatz , sondern um , wie das n - te Element zu erhalten .

Alle Antworten hier sind eine Art von String - Splitting mit Rekursion, tun CTEs, mehrere CHARINDEX, REVERSEund PATINDEX, Funktionen zu erfinden, rufen Sie für CLR Methoden, Zahlentabellen, CROSS APPLYs ... Die meisten Antworten viele Zeilen Code.

Aber - wenn Sie wirklich wollen nichts anderes als ein Ansatz , um das n - te Element zu erhalten - dies kann als getan wird reale Einzeiler , keinen UDF, nicht einmal ein Unter wählen ... Und als Zusatznutzen: typsicher

Holen Teil 2 begrenzt durch einen Raum:

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

Natürlich können Sie Variablen verwenden für Trennzeichen und die Position (verwenden Sie sql:columndie Position direkt aus einer Abfrage Wert abgerufen werden ):

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

Wenn Ihr String enthalten kann verbotene Zeichen (vor allem eines unter &><), noch kann man es auf diese Weise tun. Verwenden Sie einfach FOR XML PATHimplizit auf die Zeichenfolge zuerst alle verbotenen Zeichen mit dem passenden Escape - Sequenz zu ersetzen.

Es ist ein ganz besonderer Fall , wenn - zusätzlich - Ihr Trennzeichen das Semikolon ist . In diesem Fall ersetzen ich das Trennzeichen zuerst auf ‚# DLMT #‘, und diese schließlich zu den XML - Tags ersetzen:

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)');
Beantwortet am 08/07/2016 um 20:41
quelle vom benutzer

stimmen
10

Was über die Verwendung stringund values()Aussage?

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 IGNORE  INTO @Splited
EXEC(@str)

SELECT * FROM @Splited

Ergebnis-Satz erreicht.

id  item
1   Hello
2   John
3   Smith
Beantwortet am 01/03/2013 um 17:26
quelle vom benutzer

stimmen
10

Meiner Meinung nach euch machen es viel zu kompliziert. Erstellen Sie einfach eine CLR UDF und mit ihr geschehen.

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()));
  }
};
Beantwortet am 19/07/2012 um 22:46
quelle vom benutzer

stimmen
8

Dieses Muster funktioniert gut und man kann verallgemeinern

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

beachten Sie FIELD , INDEX und TYPE .

Lassen Sie einige Tabelle mit Kennungen wie

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

Dann können Sie schreiben

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

Splitting und alle Teile Gießen.

Beantwortet am 11/11/2014 um 14:31
quelle vom benutzer

stimmen
8

Ich benutze die Antwort von frederic aber nicht in SQL Server 2005 nicht funktioniert

Ich änderte es und ich bin mit selectmit union allund es funktioniert

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 IGNORE  INTO @Splited
EXEC(@str)

SELECT * FROM @Splited

Und das Ergebnis-Satz ist:

id  item
1   Hello
2   John
3   Smith
4   how
5   are
6   you
Beantwortet am 13/08/2013 um 16:11
quelle vom benutzer

stimmen
6

Noch ein anderes bekommen n-ten Teil des Strings von delimeter Funktion:

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

und die Nutzung:

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

die zurückgibt:

c
Beantwortet am 08/01/2016 um 14:30
quelle vom benutzer

stimmen
6

Ich war auf der Suche nach der Lösung auf Netz und die unten angegebenen Arbeiten für mich. Ref .

Und Sie rufen Sie die Funktion wie folgt aus:

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 IGNORE  INTO @temptable(Items) VALUES(@slice)       
        SET @String = RIGHT(@String,len(@String) - @idx)       
        IF len(@String) = 0 break       
    END   
    RETURN       
END
Beantwortet am 20/11/2011 um 07:40
quelle vom benutzer

stimmen
5

Das folgende Beispiel verwendet eine rekursive CTE

Update 2013.09.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 IGNORE  @returns
  SELECT REPLACE(val, ' ','' ) AS val, [level]
  FROM cte
  WHERE val > ''
  RETURN
END

Demo auf SQLFiddle

Beantwortet am 14/03/2013 um 11:18
quelle vom benutzer

stimmen
5

Versuche dies:

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

Testen Sie es wie folgt aus:

select * from SplitWordList('Hello John Smith')
Beantwortet am 05/08/2008 um 19:41
quelle vom benutzer

stimmen
3


    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 IGNORE  @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

Beantwortet am 05/11/2013 um 01:12
quelle vom benutzer

stimmen
2

Wenn Ihre Datenbank hat Kompatibilitätsgrad von 130 oder höher , dann Sie können STRING_SPLIT Funktion zusammen mit OFFSET FETCH Klauseln den bestimmten Artikel durch den Index zu erhalten.

Um das Element mit dem Index 1 zu erhalten, können Sie den folgenden Code verwenden

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

Um den zu überprüfen Kompatibilitätsgrad der Datenbank , führen Sie diesen Code:

SELECT compatibility_level  
FROM sys.databases WHERE name = 'YourDBName';
Beantwortet am 05/04/2018 um 10:23
quelle vom benutzer

stimmen
2

Sie können eine Zeichenfolge in SQL aufgeteilt, ohne eine Funktion zu benötigen:

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

Wenn Sie beliebige Zeichenketten unterstützen müssen (mit XML-Sonderzeichen)

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); 
Beantwortet am 23/10/2015 um 10:07
quelle vom benutzer

stimmen
2

Fast alle anderen Antworten geteilt Code ersetzen die Zeichenfolge geteilt wird, die CPU-Zyklen verschwendet und führt unnötige Speicherzuordnungen.

Ich behandle eine viel bessere Möglichkeit , einen String Split hier zu tun: http://www.digitalruby.com/split-string-sql-server/

Hier ist der Code:

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 IGNORE  @SplitStringTable (Value) VALUES (@SplitValue)
    SET @SplitStartPos = @SplitEndPos + 1
    SET @SplitEndPos = CHARINDEX(@SplitDelim, @StringToSplit, @SplitStartPos)
END

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

SET NOCOUNT OFF

-- You can select or join with the values in @SplitStringTable at this point.
Beantwortet am 26/08/2014 um 17:50
quelle vom benutzer

stimmen
2

Ich weiß, es ist eine alte Frage, aber ich denke, einige von meiner Lösung profitieren kann.

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 FIDDLE

Vorteile:

  • Er trennt alle drei Teilketten deliminator durch ‚‘.
  • Man darf nicht while-Schleife verwenden, da sie die Leistung abnimmt.
  • Keine Notwendigkeit, als alle sich ergebenden Unterkette zu schwenken, wird in einer Zeile angezeigt werden

Einschränkungen:

  • Man muss die Gesamt nicht wissen. von Räumen (sub-string).

Hinweis : Die Lösung geben kann Unterkette bis zu N.

Um die Begrenzung überwanden können wir die folgende verwenden ref .

Aber auch hier die obige Lösung nicht die Verwendung in einer Tabelle sein kann (actaully war ich nicht in der Lage , es zu benutzen).

Auch hier hoffe, dass ich diese Lösung einige-one helfen kann.

Update: Bei Aufzeichnungen> 50000 ist es nicht ratsam , zu verwenden , LOOPSda sie die abbaut Leistung

Beantwortet am 24/01/2013 um 07:43
quelle vom benutzer

stimmen
1

Ich weiß, ihr Ende, aber ich hatte vor kurzem diese Anforderung und kam mit dem Code unten nach oben. Ich habe keine andere Wahl User-definierte Funktion zu verwenden. Hoffe das hilft.

SELECT 
    SUBSTRING(
                SUBSTRING('Hello John Smith' ,0,CHARINDEX(' ','Hello John Smith',CHARINDEX(' ','Hello John Smith')+1)
                        ),CHARINDEX(' ','Hello John Smith'),LEN('Hello John Smith')
            )
Beantwortet am 17/09/2018 um 21:07
quelle vom benutzer

stimmen
1

Einfache Lösung für PARSING ERSTEN UND NAMEN

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

In meinem Fall (und in vielen anderen scheint es, ...), habe ich eine Liste der ersten und der letzten von einem Leerzeichen getrennt Namen. Dies kann direkt in einer select-Anweisung verwendet werden Vor- und Nachnamen zu analysieren.

-- 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
Beantwortet am 20/08/2018 um 18:59
quelle vom benutzer

stimmen
1

Hier ist eine Funktion, die Frage des Ziel eine Zeichenfolge Aufspalten und den Zugriff auf Artikel X erreichen wird:

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

Verwendung:

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

Ergebnis:

John
Beantwortet am 26/04/2018 um 21:16
quelle vom benutzer

stimmen
1

Aaron Bertrandsche Antwort ist groß, aber fehlerhaft. Es ist nicht genau ein Leerzeichen als Trennzeichen behandeln (wie das Beispiel in der ursprünglichen Frage war), da die Länge Funktionsstreifen Leerzeichen.

Hier finden Sie seinen Code, mit einer kleinen Anpassung für ein Raumtrennzeichen zu ermöglichen:

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
    );
Beantwortet am 22/03/2018 um 14:38
quelle vom benutzer

stimmen
1

Beginnend mit SQL Server 2016 wir STRING_SPLIT

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

SELECT value FROM string_split(@string, ',')
Beantwortet am 04/09/2017 um 21:52
quelle vom benutzer

stimmen
1

Reines Set-basierte Lösung unter Verwendung von TVFmit rekursiven CTE. Sie können JOINund APPLYdiese Funktion zu jedem Datenmenge.

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

Verwendung:

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

Ergebnis:

value   index
-------------
John    1
Beantwortet am 13/01/2015 um 06:37
quelle vom benutzer

stimmen
0

Sie können mit STRING_SPLITFunktion in SQL Server 2016 oder höher. Beachten Sie , dass es keine Garantie dafür gibt , dass der Teil wird in einer bestimmten Reihenfolge zurückgegeben werden.

WITH testdata(id, string) AS (
    SELECT 1, NULL UNION ALL
    SELECT 2, 'a' UNION ALL
    SELECT 3, 'a b' UNION ALL
    SELECT 4, 'a b c' UNION ALL
    SELECT 5, 'a b c d'
)
SELECT testdata.id, testdata.string, (
    SELECT value AS substr FROM STRING_SPLIT(testdata.string, ' ') FOR XML PATH(''), TYPE
).value('substr[2]', 'VARCHAR(100)') AS [2nd_substr]
FROM testdata

Woher:

  • STRING_SPLIT gibt eine Tabelle mit einer Spalte mit dem Namen value
  • FOR XML PATH('') transformiert die Zeilen <substr>a</substr><substr>b</substr>...
  • TYPEwandelt die oben XMLDatentyp
  • value('substr[2]', 'VARCHAR(100)')läuft XPATH - Ausdruck auf der oben und gibt VARCHARDatentyp

Ergebnis:

| id | string  | 2nd_substr |
|----|---------|------------|
| 1  | NULL    | NULL       |
| 2  | a       | NULL       |
| 3  | a b     | b          |
| 4  | a b c   | b          |
| 5  | a b c d | b          |
Beantwortet am 24/01/2018 um 12:27
quelle vom benutzer

stimmen
0

Ein moderner Ansatz STRING_SPLIT , erfordert SQL Server 2016 und höher.

DECLARE @string varchar(100) = 'Hello John Smith'

SELECT
    ROW_NUMBER() OVER (ORDER BY value) AS RowNr,
    value
FROM string_split(@string, ' ')

Ergebnis:

RowNr   value
1       Hello
2       John
3       Smith

Nun ist es möglich ten n-te Element aus der Zeilennummer zu erhalten.

Beantwortet am 02/01/2018 um 15:02
quelle vom benutzer

stimmen
0

Gebäude auf @NothingsImpossible Lösung, oder vielmehr auf die meisten Stimmen Antwort Kommentar (knapp unterhalb der akzeptierten eins), fand ich die folgende schnelle und unsaubere Lösung meine eigenen Bedürfnisse erfüllen - es einen Vorteil, dass sie nur innerhalb SQL Domain hat.

ein String gegeben „erste, zweite, dritte, vierte, fünfte“, sagen wir, ich möchte das dritte Token erhalten. Dies funktioniert nur, wenn wir wissen, wie viele Zeichen der Zeichenfolge haben wird - in diesem Fall ist es 5. so meine Art und Weise der Aktion ist es, die letzten zwei Token entfernt (innere Abfrage) zu hacken, und dann die ersten beiden Token weg zu hacken ( äußere Abfrage)

Ich weiß, dass dieser hässlichen und deckt die spezifischen Bedingungen war ich in, aber es ist Entsendung nur falls jemand es nützlich findet. Prost

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
Beantwortet am 31/10/2016 um 14:18
quelle vom benutzer

stimmen
0
declare @strng varchar(max)='hello john smith'
select (
    substring(
        @strng,
        charindex(' ', @strng) + 1,
        (
          (charindex(' ', @strng, charindex(' ', @strng) + 1))
          - charindex(' ',@strng)
        )
    ))
Beantwortet am 14/07/2016 um 05:29
quelle vom benutzer

stimmen
0

Ich devoloped dies,

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

die einzige Aufmerksamkeit sollten Sie ist Punkt ‚‘ dass Ende des @x wird, sollte immer da sein.

Beantwortet am 15/10/2015 um 10:50
quelle vom benutzer

stimmen
0

wenn jemand will, nur einen Teil des seperatured Text bekommen können dies nutzen,

select * from fromSplitStringSep ( 'Word1 wordr2 word3',‘‚)

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
  )
Beantwortet am 13/02/2015 um 09:14
quelle vom benutzer

stimmen
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 IGNORE  INTO @output (splitdata)  
        VALUES(SUBSTRING(@string, @start, @end - @start)) 
        SET @start = @end + 1 
        SET @end = CHARINDEX(@delimiter, @string, @start)

    END 
    RETURN 
END

Und es verwenden,

select *from dbo.fnSplitString('Querying SQL Server','')
Beantwortet am 20/12/2014 um 11:58
quelle vom benutzer

stimmen
0

während ähnlich wie die XML-basierte Antwort von josejuan, fand ich, dass nur ein einziges Mal den XML-Pfad verarbeitet, dann mäßig effizienter war Schwenk:

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

lief in 8.30

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

lief in 9.20

Beantwortet am 08/12/2014 um 03:59
quelle vom benutzer

stimmen
0

Rekursive CTE Lösung mit Server Schmerz, testen

MS SQL Server 2008 - Schema - Setup :

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

Abfrage 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

Ergebnisse :

|    A_L | N |
|--------|---|
| Hello  | 0 |
|  John  | 1 |
| Smith  | 2 |
Beantwortet am 16/01/2014 um 11:38
quelle vom benutzer

stimmen
0

Dies ist etwas, was ich tat, um einen bestimmten Token in einer Zeichenfolge zu erhalten. (Getestet in MSSQL 2008)

Erstens die Schaffung folgende Funktionen: (gefunden in: hier

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;

und

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

dann kann man es so verwenden:

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

die 1111 zurückgeben

Beantwortet am 25/07/2013 um 12:07
quelle vom benutzer

stimmen
0

Nun, mir ist gar nicht so einfacher, aber hier ist der Code, den ich verwenden, um eine kommagetrennte Eingangsgröße in einzelne Werte zu teilen, und steckte es in eine Tabelle Variable. Ich bin sicher, dass Sie diese leicht Split auf einen Raum verändern könnten basierend und dann eine grundlegende SELECT-Abfrage für diese Tabelle Variable zu tun, um Ihre Ergebnisse zu erhalten.

-- 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 IGNORE  INTO @tblAccountingCycles (AccountingCycle) VALUES (@vchAccountingCycle)
        END
        SET @vchAccountingCycleIDs = RIGHT(@vchAccountingCycleIDs, LEN(@vchAccountingCycleIDs) - @intPosition)
        SET @intPosition = CHARINDEX(',', @vchAccountingCycleIDs, 1)
    END
END

Das Konzept ist so ziemlich das gleiche. Eine andere Alternative ist die .NET-Kompatibilität innerhalb von SQL Server 2005 selbst zu nutzen. Sie können sich im wesentlichen eine einfache Methode in .NET schreiben, die die Zeichenfolge aufgeteilt würde und dann aussetzen, dass als eine gespeicherte Prozedur / Funktion.

Beantwortet am 05/08/2008 um 19:36
quelle vom benutzer

stimmen
-1

Ich habe seit einiger Zeit vzczc Antwort mit rekursiven CTE wurde verwenden, aber haben wollte, sie aktualisieren eine variable Länge Separator zu handhaben und auch Strings mit den führenden und hinken „Separatoren“ wie zu handhaben, wenn Sie eine CSV-Datei mit Datensätzen haben wie :

"Bob", "Smith", "Sunnyvale", "CA"

oder wenn Sie mit sechs Teil fqn der handelt wie unten gezeigt. Ich benutze diese in großem Umfang für die Protokollierung der subject_fqn für die Prüfung, Fehlerbehandlung usw. und ParseName Griffe nur aus vier Teilen:

[netbios_name].[machine_name].[instance].[database].[schema].[table].[column]

Hier ist meine aktualisierte Version, und dank vzczc der für seinen ursprünglichen Beitrag!

select * from [utility].[split_string](N'"this"."string"."gets"."split"."and"."removes"."leading"."and"."trailing"."quotes"', N'"."', N'"', N'"');

select * from [utility].[split_string](N'"this"."string"."gets"."split"."but"."leaves"."leading"."and"."trailing"."quotes"', N'"."', null, null);

select * from [utility].[split_string](N'[netbios_name].[machine_name].[instance].[database].[schema].[table].[column]', N'].[', N'[', N']');

create function [utility].[split_string] ( 
  @input       [nvarchar](max) 
  , @separator [sysname] 
  , @lead      [sysname] 
  , @lag       [sysname]) 
returns @node_list table ( 
  [index]  [int] 
  , [node] [nvarchar](max)) 
  begin 
      declare @separator_length [int]= len(@separator) 
              , @lead_length    [int] = isnull(len(@lead), 0) 
              , @lag_length     [int] = isnull(len(@lag), 0); 
      -- 
      set @input = right(@input, len(@input) - @lead_length); 
      set @input = left(@input, len(@input) - @lag_length); 
      -- 
      with [splitter]([index], [starting_position], [start_location]) 
           as (select cast(@separator_length as [bigint]) 
                      , cast(1 as [bigint]) 
                      , charindex(@separator, @input) 
               union all 
               select [index] + 1 
                      , [start_location] + @separator_length 
                      , charindex(@separator, @input, [start_location] + @separator_length) 
               from   [splitter] 
               where  [start_location] > 0) 
      -- 
      insert into @node_list 
                  ([index],[node]) 
        select [index] - @separator_length                   as [index] 
               , substring(@input, [starting_position], case 
                                                            when [start_location] > 0 
                                                                then 
                                                              [start_location] - [starting_position] 
                                                            else 
                                                              len(@input) 
                                                        end) as [node] 
        from   [splitter]; 
      -- 
      return; 
  end; 
go 
Beantwortet am 19/08/2014 um 20:45
quelle vom benutzer

stimmen
-1

Ein einfacher Algorithmus optimiert:

ALTER FUNCTION [dbo].[Split]( @Text NVARCHAR(200),@Splitor CHAR(1) )
RETURNS @Result TABLE ( value NVARCHAR(50)) 
AS
BEGIN
    DECLARE @PathInd INT
    Set @Text+=@Splitor
    WHILE LEN(@Text) > 0
    BEGIN
        SET @PathInd=PATINDEX('%'+@Splitor+'%',@Text)
        INSERT IGNORE  INTO  @Result VALUES(SUBSTRING(@Text, 0, @PathInd))
        SET @Text= SUBSTRING(@Text, @PathInd+1, LEN(@Text))
    END
        RETURN 
END
Beantwortet am 01/05/2014 um 07:26
quelle vom benutzer

stimmen
-1

Hier ist eine SQL UDF, die einen String und greifen nur ein bestimmtes Stück aufspalten.

create FUNCTION [dbo].[udf_SplitParseOut]
(
    @List nvarchar(MAX),
    @SplitOn nvarchar(5),
    @GetIndex smallint
)  
returns varchar(1000)
AS  

BEGIN

DECLARE @RtnValue table 
(

    Id int identity(0,1),
    Value nvarchar(MAX)
) 


    DECLARE @result varchar(1000)

    While (Charindex(@SplitOn,@List)>0)
    Begin
        Insert Into @RtnValue (value)
        Select Value = ltrim(rtrim(Substring(@List,1,Charindex(@SplitOn,@List)-1)))
        Set @List = Substring(@List,Charindex(@SplitOn,@List)+len(@SplitOn),len(@List))
    End

    Insert Into @RtnValue (Value)
    Select Value = ltrim(rtrim(@List))

    select @result = value from @RtnValue where ID = @GetIndex

    Return @result
END
Beantwortet am 20/03/2014 um 15:41
quelle vom benutzer

stimmen
-1

Hier ist meine Lösung, die jemand helfen kann. Änderung der Jonesinator Antwort oben.

Wenn ich eine Reihe von begrenzten INT Werten und will eine Tabelle von INTs zurück (was ich kann dann kommen auf). zB ‚1,20,3,343,44,6,8765‘

Erstellen Sie eine UDF:

IF OBJECT_ID(N'dbo.ufn_GetIntTableFromDelimitedList', N'TF') IS NOT NULL
    DROP FUNCTION dbo.[ufn_GetIntTableFromDelimitedList];
GO

CREATE FUNCTION dbo.[ufn_GetIntTableFromDelimitedList](@String NVARCHAR(MAX),                 @Delimiter CHAR(1))

RETURNS @table TABLE 
(
    Value INT NOT NULL
)
AS 
BEGIN
DECLARE @Pattern NVARCHAR(3)
SET @Pattern = '%' + @Delimiter + '%'
DECLARE @Value NVARCHAR(MAX)

WHILE LEN(@String) > 0
    BEGIN
        IF PATINDEX(@Pattern, @String) > 0
        BEGIN
            SET @Value = SUBSTRING(@String, 0, PATINDEX(@Pattern, @String))
            INSERT IGNORE  INTO @table (Value) VALUES (@Value)

            SET @String = SUBSTRING(@String, LEN(@Value + @Delimiter) + 1, LEN(@String))
        END
        ELSE
        BEGIN
            -- Just the one value.
            INSERT IGNORE  INTO @table (Value) VALUES (@String)
            RETURN
        END
    END

RETURN
END
GO

Dann erhält die Tabellenergebnisse:

SELECT * FROM dbo.[ufn_GetIntTableFromDelimitedList]('1,20,3,343,44,6,8765', ',')

1
20
3
343
44
6
8765

Und in einem Join-Anweisung:

SELECT [ID], [FirstName]
FROM [User] u
JOIN dbo.[ufn_GetIntTableFromDelimitedList]('1,20,3,343,44,6,8765', ',') t ON u.[ID] = t.[Value]

1    Elvis
20   Karen
3    David
343  Simon
44   Raj
6    Mike
8765 Richard

Wenn Sie eine Liste von NVARCHARs statt INTs zurückkehren wollen, dann nur die Tabellendefinition ändern:

RETURNS @table TABLE 
(
    Value NVARCHAR(MAX) NOT NULL
)
Beantwortet am 20/06/2013 um 00:42
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more