สตริงการแยก T-SQL


139

ฉันมีคอลัมน์ SQL Server 2008 R2 ที่มีสตริงซึ่งฉันต้องแยกด้วยเครื่องหมายจุลภาค ฉันเห็นคำตอบมากมายเกี่ยวกับ StackOverflow แต่ไม่มีคำตอบใด ๆ ใน R2 ฉันแน่ใจว่าฉันได้เลือกการอนุญาตในตัวอย่างฟังก์ชันแยกใด ๆ ความช่วยเหลือใด ๆ ที่ชื่นชมอย่างมาก


7
นี่เป็นหนึ่งในล้านคำตอบที่ฉันชอบstackoverflow.com/a/1846561/227755
nurettin

2
คุณหมายถึง "ไม่มีใครทำงาน" คุณจะเจาะจงมากขึ้นได้ไหม?
Aaron Bertrand

แอนดี้ชี้ให้ฉันในทิศทางที่ถูกต้องขณะที่ฉันกำลังใช้งานฟังก์ชั่นไม่ถูกต้อง นี่คือเหตุผลที่ไม่มีคำตอบสแต็คอื่นทำงาน ความผิดของฉัน.
Lee Grindon

2
เป็นไปได้ที่ซ้ำกันของสตริงการแยกใน SQL
Luv

มีmdq.RegexSplitฟังก์ชั่นในส่วนเสริม "บริการข้อมูลหลัก" ซึ่งอาจช่วยได้ แน่นอนมูลค่าการตรวจสอบ
jpaugh

คำตอบ:


233

ฉันใช้ SQL นี้มาก่อนซึ่งอาจเหมาะกับคุณ: -

CREATE FUNCTION dbo.splitstring ( @stringToSplit VARCHAR(MAX) )
RETURNS
 @returnList TABLE ([Name] [nvarchar] (500))
AS
BEGIN

 DECLARE @name NVARCHAR(255)
 DECLARE @pos INT

 WHILE CHARINDEX(',', @stringToSplit) > 0
 BEGIN
  SELECT @pos  = CHARINDEX(',', @stringToSplit)  
  SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1)

  INSERT INTO @returnList 
  SELECT @name

  SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)-@pos)
 END

 INSERT INTO @returnList
 SELECT @stringToSplit

 RETURN
END

และใช้มัน: -

SELECT * FROM dbo.splitstring('91,12,65,78,56,789')

1
เป็นคนดีนี่คือสิ่งที่ฉันกำลังมองหาขอบคุณมาก
Lee Grindon

2
ขอบคุณมากแอนดี้ ฉันได้ทำการปรับปรุงเล็กน้อยให้กับสคริปต์ของคุณเพื่ออนุญาตให้ฟังก์ชันส่งคืนรายการที่ดัชนีเฉพาะในสตริงการแยก มันจะมีประโยชน์เฉพาะในสถานการณ์เมื่อคุณโครงสร้างของคอลัมน์หนึ่งแยกวิเคราะห์ gist.github.com/klimaye/8147193
CF_Maintainer

1
ผมโพสต์การปรับปรุงบางส่วน (กับกรณีทดสอบการสนับสนุน) ไปยังหน้า GitHub ของฉันที่นี่ ผมจะโพสต์เป็นคำตอบในการนี้กองมากเกินด้ายเมื่อฉันมีตัวแทนพอที่จะเกิน "การป้องกัน" โพสต์
mpag

8
แม้ว่านี่จะเป็นคำตอบที่ยอดเยี่ยม แต่มันล้าสมัย ... วิธีการดำเนินการ (โดยเฉพาะลูป) เป็นสิ่งที่ต้องหลีกเลี่ยง ... มันคุ้มค่าที่จะดูคำตอบที่ใหม่กว่า ...
Shnugo

2
ฉันเห็นด้วยกับ @Shnugo โดยสิ้นเชิง ตัวแยกลูปทำงานได้ แต่ช้ามาก บางอย่างเช่นsqlservercentral.com/articles/Tally+Table/72993นี้ดีกว่ามาก ตัวเลือกที่ยอดเยี่ยมตามชุดอื่น ๆ สามารถพบได้ที่นี่ sqlperformance.com/2012/07/t-sql-queries/split-strings
Sean Lange

61

แทนที่จะเป็น CTE แบบเรียกซ้ำและในขณะที่ลูปมีใครคิดว่าเป็นวิธีการตั้งค่าที่มากขึ้น? โปรดทราบว่าฟังก์ชั่นนี้ถูกเขียนขึ้นสำหรับคำถามที่ซึ่งอยู่บนพื้นฐาน SQL Server 2008 และจุลภาคเป็นตัวคั่น ใน SQL Server 2016 และสูงกว่า (และในระดับความเข้ากัน 130 ขึ้นไป) เป็นตัวเลือกที่ดีกว่าSTRING_SPLIT()

CREATE FUNCTION dbo.SplitString
(
  @List     nvarchar(max),
  @Delim    nvarchar(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_columns) AS x WHERE Number <= LEN(@List)
      AND SUBSTRING(@Delim + @List, [Number], DATALENGTH(@Delim)/2) = @Delim
    ) AS y
  );
GO

หากคุณต้องการหลีกเลี่ยงข้อ จำกัด ของความยาวของสตริงที่เป็น <= จำนวนแถวในsys.all_columns(9,980 ในmodelใน SQL Server 2017; สูงกว่ามากในฐานข้อมูลผู้ใช้ของคุณเอง) คุณสามารถใช้วิธีอื่นในการหาตัวเลขเช่น การสร้างของคุณเองตารางของตัวเลข คุณสามารถใช้ CTE แบบเรียกซ้ำในกรณีที่คุณไม่สามารถใช้ตารางระบบหรือสร้างของคุณเอง:

CREATE FUNCTION dbo.SplitString
(
  @List     nvarchar(max),
  @Delim    nvarchar(255)
)
RETURNS TABLE WITH SCHEMABINDING
AS
   RETURN ( WITH n(n) AS (SELECT 1 UNION ALL SELECT n+1 
       FROM n WHERE n <= LEN(@List))
       SELECT [Value] = SUBSTRING(@List, n, 
       CHARINDEX(@Delim, @List + @Delim, n) - n)
       FROM n WHERE n <= LEN(@List)
      AND SUBSTRING(@Delim + @List, n, DATALENGTH(@Delim)/2) = @Delim
   );
GO

แต่คุณจะต้องผนวกOPTION (MAXRECURSION 0)(หรือMAXRECURSION <longest possible string length if < 32768>) ลงในคิวรีด้านนอกเพื่อหลีกเลี่ยงข้อผิดพลาดกับการเรียกซ้ำสตริง> 100 ตัวอักษร หากนั่นไม่ใช่ทางเลือกที่ดีก็ให้ดูคำตอบนี้ตามที่ระบุไว้ในความคิดเห็น

(นอกจากนี้ตัวคั่นจะต้องเป็นNCHAR(<=1228)ยังคงค้นคว้าสาเหตุ)

เพิ่มเติมเกี่ยวกับฟังก์ชั่นแยกทำไม (และพิสูจน์ว่า) ในขณะที่ลูปและ CTE แบบเรียกซ้ำไม่ปรับขนาดและทางเลือกที่ดีกว่าถ้าแยกสตริงที่มาจากชั้นแอปพลิเคชัน:


1
มีข้อบกพร่องเล็ก ๆ ในขั้นตอนนี้สำหรับกรณีที่จะมีค่า Null ที่ส่วนท้ายของสตริง - เช่นใน '1,2, 4,' - เนื่องจากค่าสุดท้ายไม่ได้แยกวิเคราะห์ หากต้องการแก้ไขข้อผิดพลาดนี้นิพจน์ "WHERE Number <= LEN (@List)" ควรถูกแทนที่ด้วย "WHERE Number <= LEN (@List) + 1"
SylvainL

@SylvainL ฉันเดาว่าขึ้นอยู่กับพฤติกรรมที่คุณต้องการ จากประสบการณ์ของฉันคนส่วนใหญ่ต้องการละเว้นเครื่องหมายจุลภาคต่อท้ายเนื่องจากไม่ได้แสดงองค์ประกอบจริง (คุณต้องการสตริงว่างจำนวนสำเนาเท่าไร) อย่างไรก็ตามวิธีที่แท้จริงในการทำเช่นนี้ - ถ้าคุณไปตามลิงค์ที่สอง - คือการทำขั้นตอนที่ยุ่งเหยิงด้วยการแยกสตริงที่น่าเกลียดขนาดใหญ่ใน T-SQL ที่ช้า
Aaron Bertrand

1
อย่างที่คุณพูดไว้คนส่วนใหญ่ต้องการละเว้นคอมม่าที่ต่อท้าย แต่ก็ไม่ใช่ทั้งหมด ฉันคิดว่าโซลูชันที่สมบูรณ์ยิ่งขึ้นคือการเพิ่มพารามิเตอร์เพื่อระบุสิ่งที่ต้องทำในกรณีนี้ แต่ความคิดเห็นของฉันเป็นเพียงเล็กน้อยเพื่อให้แน่ใจว่าไม่มีใครลืมความเป็นไปได้นี้เนื่องจากอาจเป็นจริงได้ในหลายกรณี
SylvainL

ฉันมีพฤติกรรมแปลก ๆ กับฟังก์ชั่นนั้น ถ้าฉันใช้สตริงโดยตรงเป็นพารามิเตอร์ - มันใช้งานได้ ถ้าฉันมี varchar มันไม่ได้ คุณสามารถสร้างใหม่ได้อย่างง่ายดาย: ประกาศ invarchar เป็นชุด varchar invarchar = 'ta; aa; qq' เลือกค่าจาก [dbo] [SplitString] (invarchar, ';') เลือกค่าจาก [dbo] [SplitString] ('ta; aa; qq ','; ')
Patrick Desjardins

ฉันชอบวิธีการนี้ แต่ถ้าจำนวนของวัตถุที่ส่งคืนโดยsys.all_objectsน้อยกว่าจำนวนอักขระในสายป้อนแล้วมันจะตัดทอนสตริงและค่าจะหายไป เนื่องจากsys.all_objectsเพิ่งถูกใช้เป็นบิตของการแฮ็กเพื่อสร้างแถวดังนั้นจึงมีวิธีการที่ดีกว่าเช่นคำตอบนี้
สนับมือ

56

ในที่สุดการรออยู่ในSQL Server 2016พวกเขาได้แนะนำฟังก์ชั่นสตริงการแยก:STRING_SPLIT

select * From STRING_SPLIT ('a,b', ',') cs 

วิธีอื่น ๆ ทั้งหมดในการแยกสตริงเช่น XML, Tally table, ขณะที่ loop ฯลฯ ได้ถูกพัดพาไปโดยSTRING_SPLITฟังก์ชั่นนี้

นี่คือบทความที่ยอดเยี่ยมพร้อมการเปรียบเทียบประสิทธิภาพ: ประสิทธิภาพที่น่าประหลาดใจและข้อสันนิษฐาน: STRING_SPLIT


5
เห็นได้ชัดว่าตอบคำถามเกี่ยวกับวิธีการแยกสตริงสำหรับเซิร์ฟเวอร์ที่อัปเดต แต่พวกเรายังคงติดอยู่กับ 2008 / 2008R2 จะต้องไปด้วยหนึ่งในคำตอบอื่น ๆ ที่นี่
mpag

2
คุณต้องดูที่ระดับความเข้ากันได้ในฐานข้อมูลของคุณ หากต่ำกว่า 130 คุณจะไม่สามารถใช้ฟังก์ชัน STRING_SPLIT
Luis Teijon

จริง ๆ แล้วถ้าความเข้ากันได้ไม่ใช่ 130 และคุณกำลังใช้งาน 2016 (หรือ Azure SQL) คุณสามารถตั้งค่าความเข้ากันได้สูงสุด 130 โดยใช้: แก้ไขฐานข้อมูลชื่อฐานข้อมูล SET SET COMPATIBILITY_LEVEL = 130
Michieal

23

วิธีที่ง่ายที่สุดคือการใช้XMLรูปแบบ

1. การแปลงสตริงเป็นแถวโดยไม่มีตาราง

QUERY

DECLARE @String varchar(100) = 'String1,String2,String3'
-- To change ',' to any other delimeter, just change ',' to your desired one
DECLARE @Delimiter CHAR = ','    

SELECT LTRIM(RTRIM(Split.a.value('.', 'VARCHAR(100)'))) 'Value' 
FROM  
(     
     SELECT CAST ('<M>' + REPLACE(@String, @Delimiter, '</M><M>') + '</M>' AS XML) AS Data            
) AS A 
CROSS APPLY Data.nodes ('/M') AS Split(a)

ผลลัพธ์

 x---------x
 | Value   |
 x---------x
 | String1 |
 | String2 |
 | String3 |
 x---------x

2. แปลงเป็นแถวจากตารางที่มี ID สำหรับแต่ละแถว CSV

ตารางที่มา

 x-----x--------------------------x
 | Id  |           Value          |
 x-----x--------------------------x
 |  1  |  String1,String2,String3 |
 |  2  |  String4,String5,String6 |     
 x-----x--------------------------x

QUERY

-- To change ',' to any other delimeter, just change ',' before '</M><M>' to your desired one
DECLARE @Delimiter CHAR = ','

SELECT ID,LTRIM(RTRIM(Split.a.value('.', 'VARCHAR(100)'))) 'Value' 
FROM  
(     
     SELECT ID,CAST ('<M>' + REPLACE(VALUE, @Delimiter, '</M><M>') + '</M>' AS XML) AS Data            
     FROM TABLENAME
) AS A 
CROSS APPLY Data.nodes ('/M') AS Split(a)

ผลลัพธ์

 x-----x----------x
 | Id  |  Value   |
 x-----x----------x
 |  1  |  String1 |
 |  1  |  String2 |  
 |  1  |  String3 |
 |  2  |  String4 |  
 |  2  |  String5 |
 |  2  |  String6 |     
 x-----x----------x

วิธีการนี้จะพังถ้า@Stringมีตัวอักษรต้องห้าม ... ฉันเพิ่งโพสต์คำตอบเพื่อเอาชนะปัญหานี้
Shnugo

9

ผมจำเป็นต้องมีวิธีที่รวดเร็วในการกำจัดของ+4จากรหัสไปรษณีย์

UPDATE #Emails 
  SET ZIPCode = SUBSTRING(ZIPCode, 1, (CHARINDEX('-', ZIPCODE)-1)) 
  WHERE ZIPCode LIKE '%-%'

ไม่มี proc ... no UDF ... เพียงหนึ่งคำสั่งแบบอินไลน์เล็กน้อยที่ทำสิ่งที่มันต้องทำ ไม่แฟนซีไม่สง่างาม

เปลี่ยนตัวคั่นตามต้องการ ฯลฯ และมันจะทำงานเพื่ออะไร


4
นี่ไม่ใช่คำถามที่เกี่ยวกับ OP มีค่าเช่น '234,542,23' และพวกเขาต้องการที่จะแบ่งออกเป็นสามแถว ... แถวที่ 1: 234, แถวที่ 2: 542, แถวที่ 3: 23 มันเป็นเรื่องยากที่จะทำใน SQL
codeulike

7

ถ้าคุณเปลี่ยน

WHILE CHARINDEX(',', @stringToSplit) > 0

กับ

WHILE LEN(@stringToSplit) > 0

คุณสามารถกำจัดเม็ดมีดสุดท้ายหลังจากวนลูป!

CREATE FUNCTION dbo.splitstring ( @stringToSplit VARCHAR(MAX) )
RETURNS
 @returnList TABLE ([Name] [nvarchar] (500))
AS
BEGIN

 DECLARE @name NVARCHAR(255)
 DECLARE @pos INT

 WHILE LEN(@stringToSplit) > 0
 BEGIN
  SELECT @pos  = CHARINDEX(',', @stringToSplit)


if @pos = 0
        SELECT @pos = LEN(@stringToSplit)


  SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1)

  INSERT INTO @returnList 
  SELECT @name

  SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)-@pos)
 END

 RETURN
END

สิ่งนี้จะส่งผลให้อักขระตัวสุดท้ายขององค์ประกอบสุดท้ายถูกตัดทอน เช่น "AL, AL" จะกลายเป็น "AL" | "A" คือ "ABC, ABC, ABC" จะกลายเป็น "ABC" | "ABC" | "AB"
พัฒนา Microsoft

ผนวก+1จะSELECT @pos = LEN(@stringToSplit)ปรากฏขึ้นเพื่อแก้ไขปัญหาที่ อย่างไรก็ตามค่าSELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)-@pos)จะส่งกลับInvalid length parameter passed to the LEFT or SUBSTRING functionเว้นแต่คุณ+1จะเพิ่มพารามิเตอร์ที่สามของ SUBSTRING เช่นกัน หรือคุณสามารถแทนที่การมอบหมายนั้นด้วยSET @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, 4000) --MAX len of nvarchar is 4000
mpag

1
ผมโพสต์การปรับปรุงบางส่วน (กับกรณีทดสอบการสนับสนุน) ไปยังหน้า GitHub ของฉันที่นี่ ผมจะโพสต์เป็นคำตอบในการนี้กองมากเกินด้ายเมื่อฉันมีตัวแทนพอที่จะเกิน "การป้องกัน" โพสต์
mpag

ฉันก็สังเกตเห็นปัญหาที่ชี้โดยเทอร์รี่ข้างต้น แต่ตรรกะที่กำหนดโดย @AviG นั้นยอดเยี่ยมจนไม่ได้ล้มเหลวในช่วงกลางสำหรับรายการโทเค็นที่มีความยาว ลองเรียกใช้การทดสอบนี้เพื่อตรวจสอบ (การโทรนี้ควรส่งคืนโทเค็น 969 ​​รายการ) เลือก * จาก dbo.splitstring ('token1, token2 ,,,,,,,,,, token969') จากนั้นฉันลองใช้รหัสที่กำหนดโดย mpag เพื่อตรวจสอบผลลัพธ์เดียวกัน โทรไปด้านบนและพบว่าสามารถส่งโทเค็นได้เพียง 365 รายการ ในที่สุดฉันก็แก้ไขโค้ดโดย AviG ด้านบนและโพสต์ฟังก์ชั่น bug ฟรีเป็นคำตอบใหม่ด้านล่างเนื่องจากความคิดเห็นที่นี่อนุญาตเฉพาะข้อความที่ จำกัด ตรวจสอบคำตอบภายใต้ชื่อของฉันเพื่อลอง
Gemunu R Wickremasinghe

3

ฟังก์ชันทั้งหมดสำหรับการแยกสตริงที่ใช้ Loop-ing (การวนซ้ำ) บางประเภทมีประสิทธิภาพต่ำ ควรแทนที่ด้วยโซลูชันที่ตั้งค่าไว้

รหัสนี้รันดีมาก

CREATE FUNCTION dbo.SplitStrings
(
   @List       NVARCHAR(MAX),
   @Delimiter  NVARCHAR(255)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
   RETURN 
   (  
      SELECT Item = y.i.value('(./text())[1]', 'nvarchar(4000)')
      FROM 
      ( 
        SELECT x = CONVERT(XML, '<i>' 
          + REPLACE(@List, @Delimiter, '</i><i>') 
          + '</i>').query('.')
      ) AS a CROSS APPLY x.nodes('i') AS y(i)
   );
GO

วิธีการนี้จะพังถ้า@Listมีตัวอักษรต้องห้าม ... ฉันเพิ่งโพสต์คำตอบเพื่อเอาชนะปัญหานี้
Shnugo

ฉันยกระดับการตอบสนองของคุณเพราะคุณทำงานกับพื้นที่ในฐานะตัวคั่นและผู้โหวตสูงสุดไม่ได้
KMC

3

วิธีการที่ใช้บ่อยกับองค์ประกอบ XML แบ่งในกรณีของตัวอักษรต้องห้าม นี่เป็นวิธีการที่จะใช้วิธีนี้กับตัวละครทุกชนิดแม้จะมีเครื่องหมายอัฒภาคเป็นตัวคั่น

เคล็ดลับคือก่อนอื่นให้ใช้SELECT SomeString AS [*] FOR XML PATH('')เพื่อให้ได้อักขระที่ต้องห้ามทั้งหมดได้อย่างปลอดภัย นั่นคือเหตุผลที่ทำไมฉันแทนที่ตัวคั่นเป็นค่าวิเศษเพื่อหลีกเลี่ยงปัญหาด้วย;ตัวคั่น

DECLARE @Dummy TABLE (ID INT, SomeTextToSplit NVARCHAR(MAX))
INSERT INTO @Dummy VALUES
 (1,N'A&B;C;D;E, F')
,(2,N'"C" & ''D'';<C>;D;E, F');

DECLARE @Delimiter NVARCHAR(10)=';'; --special effort needed (due to entities coding with "&code;")!

WITH Casted AS
(
    SELECT *
          ,CAST(N'<x>' + REPLACE((SELECT REPLACE(SomeTextToSplit,@Delimiter,N'§§Split$me$here§§') AS [*] FOR XML PATH('')),N'§§Split$me$here§§',N'</x><x>') + N'</x>' AS XML) AS SplitMe
    FROM @Dummy
)
SELECT Casted.ID
      ,x.value(N'.',N'nvarchar(max)') AS Part 
FROM Casted
CROSS APPLY SplitMe.nodes(N'/x') AS A(x)

ผลลัพธ์

ID  Part
1   A&B
1   C
1   D
1   E, F
2   "C" & 'D'
2   <C>
2   D
2   E, F

2

ฉันต้องเขียนอะไรแบบนี้เมื่อไม่นานมานี้ นี่คือทางออกที่ฉันคิดขึ้นมา มันวางอยู่ทั่วไปสำหรับสตริงตัวคั่นและฉันคิดว่ามันจะทำงานได้ดีขึ้นเล็กน้อย:

CREATE FUNCTION [dbo].[SplitString] 
    ( @string nvarchar(4000)
    , @delim nvarchar(100) )
RETURNS
    @result TABLE 
        ( [Value] nvarchar(4000) NOT NULL
        , [Index] int NOT NULL )
AS
BEGIN
    DECLARE @str nvarchar(4000)
          , @pos int 
          , @prv int = 1

    SELECT @pos = CHARINDEX(@delim, @string)
    WHILE @pos > 0
    BEGIN
        SELECT @str = SUBSTRING(@string, @prv, @pos - @prv)
        INSERT INTO @result SELECT @str, @prv

        SELECT @prv = @pos + LEN(@delim)
             , @pos = CHARINDEX(@delim, @string, @pos + 1)
    END

    INSERT INTO @result SELECT SUBSTRING(@string, @prv, 4000), @prv
    RETURN
END

1

วิธีการแก้ปัญหาโดยใช้ CTE หากใครก็ตามต้องการมัน (นอกเหนือจากฉันที่เห็นได้ชัดว่านั่นคือเหตุผลที่ฉันเขียนมัน)

declare @StringToSplit varchar(100) = 'Test1,Test2,Test3';
declare @SplitChar varchar(10) = ',';

with StringToSplit as (
  select 
      ltrim( rtrim( substring( @StringToSplit, 1, charindex( @SplitChar, @StringToSplit ) - 1 ) ) ) Head
    , substring( @StringToSplit, charindex( @SplitChar, @StringToSplit ) + 1, len( @StringToSplit ) ) Tail

  union all

  select
      ltrim( rtrim( substring( Tail, 1, charindex( @SplitChar, Tail ) - 1 ) ) ) Head
    , substring( Tail, charindex( @SplitChar, Tail ) + 1, len( Tail ) ) Tail
  from StringToSplit
  where charindex( @SplitChar, Tail ) > 0

  union all

  select
      ltrim( rtrim( Tail ) ) Head
    , '' Tail
  from StringToSplit
  where charindex( @SplitChar, Tail ) = 0
    and len( Tail ) > 0
)
select Head from StringToSplit

1

สิ่งนี้ปรับให้แคบลงกว่าเดิม เมื่อฉันทำสิ่งนี้ฉันมักจะมีรายการรหัสที่คั่นด้วยจุลภาค (INT หรือ BIGINT) ซึ่งฉันต้องการใช้เป็นตารางเพื่อใช้เป็นการรวมภายในกับตารางอื่นที่มีคีย์หลักของ INT หรือ BIGINT ฉันต้องการฟังก์ชั่นตารางมูลค่ากลับมาเพื่อให้ฉันได้เข้าร่วมที่มีประสิทธิภาพมากที่สุด

การใช้งานตัวอย่างจะเป็น:

 DECLARE @IDs VARCHAR(1000);
 SET @IDs = ',99,206,124,8967,1,7,3,45234,2,889,987979,';
 SELECT me.Value
 FROM dbo.MyEnum me
 INNER JOIN dbo.GetIntIdsTableFromDelimitedString(@IDs) ids ON me.PrimaryKey = ids.ID

ฉันขโมยความคิดจากhttp://sqlrecords.blogspot.com/2012/11/converting-delimited-list-to-table.htmlเปลี่ยนให้เป็นแบบตารางที่มีมูลค่าและใช้ INT

create function dbo.GetIntIDTableFromDelimitedString
    (
    @IDs VARCHAR(1000)  --this parameter must start and end with a comma, eg ',123,456,'
                        --all items in list must be perfectly formatted or function will error
)
RETURNS TABLE AS
 RETURN

SELECT
    CAST(SUBSTRING(@IDs,Nums.number + 1,CHARINDEX(',',@IDs,(Nums.number+2)) - Nums.number - 1) AS INT) AS ID 
FROM   
     [master].[dbo].[spt_values] Nums
WHERE Nums.Type = 'P' 
AND    Nums.number BETWEEN 1 AND DATALENGTH(@IDs)
AND    SUBSTRING(@IDs,Nums.number,1) = ','
AND    CHARINDEX(',',@IDs,(Nums.number+1)) > Nums.number;

GO

1

มีรุ่นที่ถูกต้องอยู่ที่นี่ แต่ฉันคิดว่ามันจะดีที่จะเพิ่มความผิดพลาดเล็กน้อยในกรณีที่พวกเขามีเครื่องหมายจุลภาคต่อท้ายรวมทั้งทำให้คุณสามารถใช้มันไม่ได้เป็นฟังก์ชั่น แต่เป็นส่วนหนึ่งของรหัสขนาดใหญ่ . ในกรณีที่คุณใช้เพียงครั้งเดียวและไม่ต้องการฟังก์ชั่น นี่เป็นจำนวนเต็มด้วย (ซึ่งเป็นสิ่งที่ฉันต้องการ) ดังนั้นคุณอาจต้องเปลี่ยนชนิดข้อมูลของคุณ

DECLARE @StringToSeperate VARCHAR(10)
SET @StringToSeperate = '1,2,5'

--SELECT @StringToSeperate IDs INTO #Test

DROP TABLE #IDs
CREATE TABLE #IDs (ID int) 

DECLARE @CommaSeperatedValue NVARCHAR(255) = ''
DECLARE @Position INT = LEN(@StringToSeperate)

--Add Each Value
WHILE CHARINDEX(',', @StringToSeperate) > 0
BEGIN
    SELECT @Position  = CHARINDEX(',', @StringToSeperate)  
    SELECT @CommaSeperatedValue = SUBSTRING(@StringToSeperate, 1, @Position-1)

    INSERT INTO #IDs 
    SELECT @CommaSeperatedValue

    SELECT @StringToSeperate = SUBSTRING(@StringToSeperate, @Position+1, LEN(@StringToSeperate)-@Position)

END

--Add Last Value
IF (LEN(LTRIM(RTRIM(@StringToSeperate)))>0)
BEGIN
    INSERT INTO #IDs
    SELECT SUBSTRING(@StringToSeperate, 1, @Position)
END

SELECT * FROM #IDs

ถ้าคุณจะไปSET @StringToSeperate = @StringToSeperate+','ก่อนWHILEลูปฉันคิดว่าคุณสามารถกำจัดบล็อก "เพิ่มค่าล่าสุด" ดู sol'n ของฉันบน github ด้วย
mpag

คำตอบนี้ขึ้นอยู่กับอะไร มีคำตอบมากมายที่นี่และมันค่อนข้างสับสน ขอบคุณ
jpaugh

1

ฉันแก้ไข + ฟังก์ชั่นของ Andy Robinson นิดหน่อย ตอนนี้คุณสามารถเลือกได้เฉพาะส่วนที่ต้องการจากตารางส่งคืน:

CREATE FUNCTION dbo.splitstring ( @stringToSplit VARCHAR(MAX) )

RETURNS

 @returnList TABLE ([numOrder] [tinyint] , [Name] [nvarchar] (500)) AS
BEGIN

 DECLARE @name NVARCHAR(255)

 DECLARE @pos INT

 DECLARE @orderNum INT

 SET @orderNum=0

 WHILE CHARINDEX('.', @stringToSplit) > 0

 BEGIN
    SELECT @orderNum=@orderNum+1;
  SELECT @pos  = CHARINDEX('.', @stringToSplit)  
  SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1)

  INSERT INTO @returnList 
  SELECT @orderNum,@name

  SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)-@pos)
 END
    SELECT @orderNum=@orderNum+1;
 INSERT INTO @returnList
 SELECT @orderNum, @stringToSplit

 RETURN
END


Usage:

SELECT Name FROM dbo.splitstring('ELIS.YD.CRP1.1.CBA.MDSP.T389.BT') WHERE numOrder=5


1

หากคุณต้องการวิธีแก้ปัญหาแบบเร่งด่วนสำหรับกรณีทั่วไปที่มีรหัสขั้นต่ำ CTE แบบสองบรรทัดที่เรียกซ้ำนี้จะทำดังนี้

DECLARE @s VARCHAR(200) = ',1,2,,3,,,4,,,,5,'

;WITH
a AS (SELECT i=-1, j=0 UNION ALL SELECT j, CHARINDEX(',', @s, j + 1) FROM a WHERE j > i),
b AS (SELECT SUBSTRING(@s, i+1, IIF(j>0, j, LEN(@s)+1)-i-1) s FROM a WHERE i >= 0)
SELECT * FROM b

ใช้สิ่งนี้เป็นคำสั่งแบบสแตนด์อโลนหรือเพียงแค่เพิ่ม CTE ข้างต้นลงในแบบสอบถามของคุณและคุณจะสามารถเข้าร่วมตารางผลลัพธ์ bกับผู้อื่นเพื่อใช้ในการแสดงออกเพิ่มเติม

แก้ไข (โดย Shnugo)

หากคุณเพิ่มตัวนับคุณจะได้รับดัชนีตำแหน่งพร้อมกับรายการ:

DECLARE @s VARCHAR(200) = '1,2333,344,4'

;WITH
a AS (SELECT n=0, i=-1, j=0 UNION ALL SELECT n+1, j, CHARINDEX(',', @s, j+1) FROM a WHERE j > i),
b AS (SELECT n, SUBSTRING(@s, i+1, IIF(j>0, j, LEN(@s)+1)-i-1) s FROM a WHERE i >= 0)
SELECT * FROM b;

ผลลัพธ์:

n   s
1   1
2   2333
3   344
4   4

ฉันชอบวิธีนี้ ฉันหวังว่าคุณจะไม่รังเกียจที่ฉันเพิ่มการปรับปรุงบางอย่างโดยตรงในคำตอบของคุณ เพียงแค่รู้สึกอิสระที่จะแก้ไขสิ่งนี้ในวิธีที่สะดวก ...
Shnugo

1

ฉันใช้เส้นทาง xml โดยห่อค่าเป็นองค์ประกอบ (M แต่อะไรก็ได้):

declare @v nvarchar(max) = '100,201,abcde'

select 
    a.value('.', 'varchar(max)')
from
    (select cast('<M>' + REPLACE(@v, ',', '</M><M>') + '</M>' AS XML) as col) as A
    CROSS APPLY A.col.nodes ('/M') AS Split(a)

0

นี่คือรุ่นที่สามารถแยกออกเป็นแพทเทิร์นโดยใช้ patindex ซึ่งเป็นการดัดแปลงโพสต์ด้านบน ฉันมีกรณีที่ฉันต้องการแยกสตริงที่มีตัวคั่นหลายตัว


alter FUNCTION dbo.splitstring ( @stringToSplit VARCHAR(1000), @splitPattern varchar(10) )
RETURNS
 @returnList TABLE ([Name] [nvarchar] (500))
AS
BEGIN

 DECLARE @name NVARCHAR(255)
 DECLARE @pos INT

 WHILE PATINDEX(@splitPattern, @stringToSplit) > 0
 BEGIN
  SELECT @pos  = PATINDEX(@splitPattern, @stringToSplit)  
  SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1)

  INSERT INTO @returnList 
  SELECT @name

  SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)-@pos)
 END

 INSERT INTO @returnList
 SELECT @stringToSplit

 RETURN
END
select * from dbo.splitstring('stringa/stringb/x,y,z','%[/,]%');

ผลลัพธ์จะมีลักษณะเช่นนี้

stringa stringb x y z


0

ส่วนตัวฉันใช้ฟังก์ชั่นนี้:

ALTER FUNCTION [dbo].[CUST_SplitString]
(
    @String NVARCHAR(4000),
    @Delimiter NCHAR(1)
)
RETURNS TABLE 
AS
RETURN 
(
    WITH Split(stpos,endpos) 
    AS(
        SELECT 0 AS stpos, CHARINDEX(@Delimiter,@String) AS endpos
        UNION ALL
        SELECT endpos+1, CHARINDEX(@Delimiter,@String,endpos+1) 
        FROM Split
        WHERE endpos > 0
    )
    SELECT 'Id' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
        'Data' = SUBSTRING(@String,stpos,COALESCE(NULLIF(endpos,0),LEN(@String)+1)-stpos)
    FROM Split
)

0

ผมได้พัฒนา Splitter คู่ (ใช้ตัวละครทั้งสองแยก) ตามที่ร้องขอต่อไป อาจเป็นค่าบางอย่างในชุดข้อความนี้ซึ่งจะมีการอ้างอิงมากที่สุดสำหรับแบบสอบถามที่เกี่ยวข้องกับการแยกสตริง

CREATE FUNCTION uft_DoubleSplitter 
(   
    -- Add the parameters for the function here
    @String VARCHAR(4000), 
    @Splitter1 CHAR,
    @Splitter2 CHAR
)
RETURNS @Result TABLE (Id INT,MId INT,SValue VARCHAR(4000))
AS
BEGIN
DECLARE @FResult TABLE(Id INT IDENTITY(1, 1),
                   SValue VARCHAR(4000))
DECLARE @SResult TABLE(Id INT IDENTITY(1, 1),
                   MId INT,
                   SValue VARCHAR(4000))
SET @String = @String+@Splitter1

WHILE CHARINDEX(@Splitter1, @String) > 0
    BEGIN
       DECLARE @WorkingString VARCHAR(4000) = NULL

       SET @WorkingString = SUBSTRING(@String, 1, CHARINDEX(@Splitter1, @String) - 1)
       --Print @workingString

       INSERT INTO @FResult
       SELECT CASE
            WHEN @WorkingString = '' THEN NULL
            ELSE @WorkingString
            END

       SET @String = SUBSTRING(@String, LEN(@WorkingString) + 2, LEN(@String))

    END
IF ISNULL(@Splitter2, '') != ''
    BEGIN
       DECLARE @OStartLoop INT
       DECLARE @OEndLoop INT

       SELECT @OStartLoop = MIN(Id),
            @OEndLoop = MAX(Id)
       FROM @FResult

       WHILE @OStartLoop <= @OEndLoop
          BEGIN
             DECLARE @iString VARCHAR(4000)
             DECLARE @iMId INT

             SELECT @iString = SValue+@Splitter2,
                   @iMId = Id
             FROM @FResult
             WHERE Id = @OStartLoop

             WHILE CHARINDEX(@Splitter2, @iString) > 0
                BEGIN
                    DECLARE @iWorkingString VARCHAR(4000) = NULL

                    SET @IWorkingString = SUBSTRING(@iString, 1, CHARINDEX(@Splitter2, @iString) - 1)

                    INSERT INTO @SResult
                    SELECT @iMId,
                         CASE
                         WHEN @iWorkingString = '' THEN NULL
                         ELSE @iWorkingString
                         END

                    SET @iString = SUBSTRING(@iString, LEN(@iWorkingString) + 2, LEN(@iString))

                END

             SET @OStartLoop = @OStartLoop + 1
          END
       INSERT INTO @Result
       SELECT MId AS PrimarySplitID,
            ROW_NUMBER() OVER (PARTITION BY MId ORDER BY Mid, Id) AS SecondarySplitID ,
            SValue
       FROM @SResult
    END
ELSE
    BEGIN
       INSERT INTO @Result
       SELECT Id AS PrimarySplitID,
            NULL AS SecondarySplitID,
            SValue
       FROM @FResult
    END
RETURN

การใช้งาน:

--FirstSplit
SELECT * FROM uft_DoubleSplitter('ValueA=ValueB=ValueC=ValueD==ValueE&ValueA=ValueB=ValueC===ValueE&ValueA=ValueB==ValueD===','&',NULL)

--Second Split
SELECT * FROM uft_DoubleSplitter('ValueA=ValueB=ValueC=ValueD==ValueE&ValueA=ValueB=ValueC===ValueE&ValueA=ValueB==ValueD===','&','=')

การใช้งานที่เป็นไปได้ (รับค่าที่สองของแต่ละการแยก):

SELECT fn.SValue
FROM uft_DoubleSplitter('ValueA=ValueB=ValueC=ValueD==ValueE&ValueA=ValueB=ValueC===ValueE&ValueA=ValueB==ValueD===', '&', '=')AS fn
WHERE fn.mid = 2

0

นี่คือตัวอย่างที่คุณสามารถใช้เป็นฟังก์ชั่นหรือคุณสามารถใส่ตรรกะเดียวกันในกระบวนการ - เลือก * จาก [dbo] .fn_SplitString;

CREATE FUNCTION [dbo].[fn_SplitString]
(@CSV VARCHAR(MAX), @Delimeter VARCHAR(100) = ',')
       RETURNS @retTable TABLE 
(

    [value] VARCHAR(MAX) NULL
)AS

BEGIN

DECLARE
       @vCSV VARCHAR (MAX) = @CSV,
       @vDelimeter VARCHAR (100) = @Delimeter;

IF @vDelimeter = ';'
BEGIN
    SET @vCSV = REPLACE(@vCSV, ';', '~!~#~');
    SET @vDelimeter = REPLACE(@vDelimeter, ';', '~!~#~');
END;

SET @vCSV = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@vCSV, '&', '&amp;'), '<', '&lt;'), '>', '&gt;'), '''', '&apos;'), '"', '&quot;');

DECLARE @xml XML;

SET @xml = '<i>' + REPLACE(@vCSV, @vDelimeter, '</i><i>') + '</i>';

INSERT INTO @retTable
SELECT
       x.i.value('.', 'varchar(max)') AS COLUMNNAME
  FROM @xml.nodes('//i')AS x(i);

 RETURN;
END;

วิธีการนี้จะพังถ้า@vCSVมีตัวอักษรต้องห้าม ... ฉันเพิ่งโพสต์คำตอบเพื่อเอาชนะปัญหานี้
Shnugo

0

โซลูชันที่เรียกใช้ cte แบบเรียกซ้ำ

declare @T table (iden int identity, col1 varchar(100));
insert into @T(col1) values
       ('ROOT/South America/Lima/Test/Test2')
     , ('ROOT/South America/Peru/Test/Test2')
     , ('ROOT//South America/Venuzuala ')
     , ('RtT/South America / ') 
     , ('ROOT/South Americas// '); 
declare @split char(1) = '/';
select @split as split;
with cte as 
(  select t.iden, case when SUBSTRING(REVERSE(rtrim(t.col1)), 1, 1) = @split then LTRIM(RTRIM(t.col1)) else LTRIM(RTRIM(t.col1)) + @split end  as col1, 0 as pos                             , 1 as cnt
   from @T t
   union all 
   select t.iden, t.col1                                                                                                                              , charindex(@split, t.col1, t.pos + 1), cnt + 1 
   from cte t 
   where charindex(@split, t.col1, t.pos + 1) > 0 
)
select t1.*, t2.pos, t2.cnt
     , ltrim(rtrim(SUBSTRING(t1.col1, t1.pos+1, t2.pos-t1.pos-1))) as bingo
from cte t1 
join cte t2 
  on t2.iden = t1.iden 
 and t2.cnt  = t1.cnt+1
 and t2.pos > t1.pos 
order by t1.iden, t1.cnt;

0

นี้ขึ้นอยู่กับคำตอบของ Andy Robertson ฉันต้องการตัวคั่นอื่นที่ไม่ใช่จุลภาค

CREATE FUNCTION dbo.splitstring ( @stringToSplit nvarchar(MAX), @delim nvarchar(max))
RETURNS
 @returnList TABLE ([value] [nvarchar] (MAX))
AS
BEGIN

 DECLARE @value NVARCHAR(max)
 DECLARE @pos INT

 WHILE CHARINDEX(@delim, @stringToSplit) > 0
 BEGIN
  SELECT @pos  = CHARINDEX(@delim, @stringToSplit)  
  SELECT @value = SUBSTRING(@stringToSplit, 1, @pos - 1)

  INSERT INTO @returnList 
  SELECT @value

  SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos + LEN(@delim), LEN(@stringToSplit) - @pos)
 END

 INSERT INTO @returnList
 SELECT @stringToSplit

 RETURN
END
GO

และใช้มัน:

SELECT * FROM dbo.splitstring('test1 test2 test3', ' ');

(ทดสอบบน SQL Server 2008 R2)

แก้ไข: รหัสทดสอบที่ถูกต้อง


0

/ *

คำตอบของT-SQL split string
อ้างอิงจากคำตอบจากAndy RobinsonและAviG
Enhanced function อ้างอิง: ฟังก์ชั่น LEN ไม่รวมช่องว่างต่อท้ายใน SQL Server
'file' นี้ควรจะใช้ได้ทั้งไฟล์ markdown และไฟล์ SQL


*/

    CREATE FUNCTION dbo.splitstring ( --CREATE OR ALTER
        @stringToSplit NVARCHAR(MAX)
    ) RETURNS @returnList TABLE ([Item] NVARCHAR (MAX))
    AS BEGIN
        DECLARE @name NVARCHAR(MAX)
        DECLARE @pos BIGINT
        SET @stringToSplit = @stringToSplit + ','             -- this should allow entries that end with a `,` to have a blank value in that "column"
        WHILE ((LEN(@stringToSplit+'_') > 1)) BEGIN           -- `+'_'` gets around LEN trimming terminal spaces. See URL referenced above
            SET @pos = COALESCE(NULLIF(CHARINDEX(',', @stringToSplit),0),LEN(@stringToSplit+'_')) -- COALESCE grabs first non-null value
            SET @name = SUBSTRING(@stringToSplit, 1, @pos-1)  --MAX size of string of type nvarchar is 4000 
            SET @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, 4000) -- With SUBSTRING fn (MS web): "If start is greater than the number of characters in the value expression, a zero-length expression is returned."
            INSERT INTO @returnList SELECT @name --additional debugging parameters below can be added
            -- + ' pos:' + CAST(@pos as nvarchar) + ' remain:''' + @stringToSplit + '''(' + CAST(LEN(@stringToSplit+'_')-1 as nvarchar) + ')'
        END
        RETURN
    END
    GO

/*

กรณีทดสอบ: ดู URL ที่อ้างถึงว่าเป็น "ฟังก์ชันการทำงานขั้นสูง" ด้านบน

SELECT *,LEN(Item+'_')-1 'L' from splitstring('a,,b')

Item | L
---  | ---
a    | 1
     | 0
b    | 1

SELECT *,LEN(Item+'_')-1 'L' from splitstring('a,,')

Item | L   
---  | ---
a    | 1
     | 0
     | 0

SELECT *,LEN(Item+'_')-1 'L' from splitstring('a,, ')

Item | L   
---  | ---
a    | 1
     | 0
     | 1

SELECT *,LEN(Item+'_')-1 'L' from splitstring('a,, c ')

Item | L   
---  | ---
a    | 1
     | 0
 c   | 3

* /


ย้อนกลับไปเป็นเกียรติ "ไฟล์" นี้ควรถูกต้องทั้งไฟล์มาร์ก
อัป

-1
ALTER FUNCTION [dbo].func_split_string
(
    @input as varchar(max),
    @delimiter as varchar(10) = ";"

)
RETURNS @result TABLE
(
    id smallint identity(1,1),
    csv_value varchar(max) not null
)
AS
BEGIN
    DECLARE @pos AS INT;
    DECLARE @string AS VARCHAR(MAX) = '';

    WHILE LEN(@input) > 0
    BEGIN           
        SELECT @pos = CHARINDEX(@delimiter,@input);

        IF(@pos<=0)
            select @pos = len(@input)

        IF(@pos <> LEN(@input))
            SELECT @string = SUBSTRING(@input, 1, @pos-1);
        ELSE
            SELECT @string = SUBSTRING(@input, 1, @pos);

        INSERT INTO @result SELECT @string

        SELECT @input = SUBSTRING(@input, @pos+len(@delimiter), LEN(@input)-@pos)       
    END
    RETURN  
END

-1

คุณสามารถใช้ฟังก์ชั่นนี้:

        CREATE FUNCTION SplitString
        (    
           @Input NVARCHAR(MAX),
           @Character CHAR(1)
          )
            RETURNS @Output TABLE (
            Item NVARCHAR(1000)
          )
        AS
        BEGIN

      DECLARE @StartIndex INT, @EndIndex INT
      SET @StartIndex = 1
      IF SUBSTRING(@Input, LEN(@Input) - 1, LEN(@Input)) <> @Character
      BEGIN
            SET @Input = @Input + @Character
      END

      WHILE CHARINDEX(@Character, @Input) > 0
      BEGIN
            SET @EndIndex = CHARINDEX(@Character, @Input)

            INSERT INTO @Output(Item)
            SELECT SUBSTRING(@Input, @StartIndex, @EndIndex - 1)

            SET @Input = SUBSTRING(@Input, @EndIndex + 1, LEN(@Input))
      END

      RETURN
END
GO

-1

ด้วยความเคารพจาก @AviG ทั้งหมดนี้เป็นรุ่นที่ไม่มีข้อบกพร่องของฟังก์ชั่นที่พัฒนาโดยเขาเพื่อส่งสัญญาณโทเค็นทั้งหมดให้เต็ม

IF EXISTS (SELECT * FROM sys.objects WHERE type = 'TF' AND name = 'TF_SplitString')
DROP FUNCTION [dbo].[TF_SplitString]
GO

-- =============================================
-- Author:  AviG
-- Amendments:  Parameterize the delimeter and included the missing chars in last token - Gemunu Wickremasinghe
-- Description: Tabel valued function that Breaks the delimeted string by given delimeter and returns a tabel having split results
-- Usage
-- select * from   [dbo].[TF_SplitString]('token1,token2,,,,,,,,token969',',')
-- 969 items should be returned
-- select * from   [dbo].[TF_SplitString]('4672978261,4672978255',',')
-- 2 items should be returned
-- =============================================
CREATE FUNCTION dbo.TF_SplitString 
( @stringToSplit VARCHAR(MAX) ,
  @delimeter char = ','
)
RETURNS
 @returnList TABLE ([Name] [nvarchar] (500))
AS
BEGIN

    DECLARE @name NVARCHAR(255)
    DECLARE @pos INT

    WHILE LEN(@stringToSplit) > 0
    BEGIN
        SELECT @pos  = CHARINDEX(@delimeter, @stringToSplit)


        if @pos = 0
        BEGIN
            SELECT @pos = LEN(@stringToSplit)
            SELECT @name = SUBSTRING(@stringToSplit, 1, @pos)  
        END
        else 
        BEGIN
            SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1)
        END

        INSERT INTO @returnList 
        SELECT @name

        SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)-@pos)
    END

 RETURN
END

-3

วิธีที่ง่ายที่สุด:

  1. ติดตั้ง SQL Server 2016
  2. ใช้ STRING_SPLIT https://msdn.microsoft.com/en-us/library/mt684588.aspx

มันทำงานได้แม้ใน Express Edition :)


อย่าลืมตั้ง "ระดับความเข้ากันได้" เป็น SQL Server 2016 (130) - ในสตูดิโอจัดการคลิกขวาที่ฐานข้อมูลคุณสมบัติ / ตัวเลือก / ระดับความเข้ากันได้
Tomino

1
โพสต์ต้นฉบับกล่าวว่าสำหรับ SQL 2008 R2 การติดตั้ง SQL 2016 อาจไม่ใช่ตัวเลือก
Shawn Gavett
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.