Sql-Server

在分隔符之間提取/解析資訊

  • April 6, 2022

我有一列,其中有 10 個由管道字元分隔的“欄位”,如下所示:

特克斯 | 更多文字 | 某事這裡 | 更多資訊 | 更多這裡 | 等| 等|

我一直在嘗試提取管道之間的內容,我可以做前兩個,但在那之後,我的大腦陷入了一個初始循環,我無法繞開它。

例如。表名是 MyTable,列是 MyColumn

SELECT TOP 10  MyTable.ItemsID, MyTable.MyColumn
(SELECT SUBSTRING (MyTable.MyColumn,1,CHARINDEX('|', MyColumn)-1))as Pos1,
(SELECT SUBSTRING(MyTable.MyColumn, CHARINDEX('|', MyColumn)+1,CHARINDEX('|', MyColumn))) as Pos2
FROM MyTable

我得到了位置 1 和 2 所需的東西,但是對於其餘的,我不知道該怎麼做。

我在想我需要獲取我的第三個管道的索引位置,但我的大腦凍結了,我嘗試了以下變化:

SELECT SUBSTRING(MyTable.MyColumn, CHARINDEX(SUBSTRING(MyTable.MyColumn, CHARINDEX('|', MyColumn)+1,CHARINDEX('|', MyColumn)))) as Pos3

我剛剛研究了 REPLACE 和 PARSENAME 函式。通過替換,我可以用點或句點替換管道字元,以便 PARSENAME 可以解析點分隔值。但是,我發現 PARSENAME 被限制為 4 個值。

我使用 STRING_SPLIT 得到了不錯的結果,但是,此功能需要兼容級別 130,我無法更改數據庫。我與它的互動是通過 API。

SELECT value
FROM STRING_SPLIT ((select mytable.mycolumn from dbo.mytable), '|'); 

我通常使用這個腳本:

create table #temp (id int, val varchar(50))
insert into #temp (id,val)
values
(1,'aaa|bbb|ccc|ddd'),
(2,'aaa|bbb|ccc|ddd'),
(3,'aaa|bbb|ccc|ddd'),
(4,'aaa|bbb|ccc|ddd')

select * from (
select * from #temp as t 
cross apply (select num=Row_Number()
                 over (Order by (SELECT NULL)),
               value
            from string_split(t.val, '|') ) d) s 
pivot (max(value) for s.num in([1],[2],[3],[4])) a

您只需要再添加 6 個欄位。

此解決方案依賴於自 sql server 2016 以來可用的 STRING_SPLIT。

對此進行中繼以獲取替代方案:

關聯

您可以使用人們以前使用的字元串拆分功能STRING_SPLIT之一。

如果你不想在你的數據庫中創建一個函式,或者只是想實現它CHARINDEX用於教育目的,看看這個:

DECLARE @MyTable table 
(
   ItemsID integer PRIMARY KEY, 
   MyColumn varchar(100) NOT NULL
);

INSERT @MyTable 
   (ItemsID, MyColumn)
VALUES
   (1, '1|2|3|4|5|6|7|8|9|0'),
   (2, 'AB|CD|EF|GH|IJ|KL|MN|OP|QR|ST');

SELECT
   MT.ItemsID,
   MT.MyColumn,
   Splits.Item1,
   Splits.Item2,
   Splits.Item3,
   Splits.Item4,
   Splits.Item5,
   Splits.Item6,
   Splits.Item7,
   Splits.Item8,
   Splits.Item9,
   Splits.Item10 
FROM @MyTable AS MT
CROSS APPLY 
(
   SELECT
       Item1 = LEFT(MT.MyColumn, CA1.p1 - 1),
       Item2 = SUBSTRING(MT.MyColumn, CA1.p1 + 1, CA2.p2 - CA1.p1 - 1),
       Item3 = SUBSTRING(MT.MyColumn, CA2.p2 + 1, CA3.p3 - CA2.p2 - 1),
       Item4 = SUBSTRING(MT.MyColumn, CA3.p3 + 1, CA4.p4 - CA3.p3 - 1),
       Item5 = SUBSTRING(MT.MyColumn, CA4.p4 + 1, CA5.p5 - CA4.p4 - 1),
       Item6 = SUBSTRING(MT.MyColumn, CA5.p5 + 1, CA6.p6 - CA5.p5 - 1),
       Item7 = SUBSTRING(MT.MyColumn, CA6.p6 + 1, CA7.p7 - CA6.p6 - 1),
       Item8 = SUBSTRING(MT.MyColumn, CA7.p7 + 1, CA8.p8 - CA7.p7 - 1),
       Item9 = SUBSTRING(MT.MyColumn, CA8.p8 + 1, CA9.p9 - CA8.p8 - 1),
       Item10 = RIGHT(MT.MyColumn, LEN(MT.MyColumn) - CA9.p9)
   FROM (SELECT CHARINDEX('|', MT.MyColumn)) AS CA1 (p1)
   CROSS APPLY (SELECT CHARINDEX('|', MT.MyColumn, CA1.p1 + 1)) AS CA2 (p2)
   CROSS APPLY (SELECT CHARINDEX('|', MT.MyColumn, CA2.p2 + 1)) AS CA3 (p3)
   CROSS APPLY (SELECT CHARINDEX('|', MT.MyColumn, CA3.p3 + 1)) AS CA4 (p4)
   CROSS APPLY (SELECT CHARINDEX('|', MT.MyColumn, CA4.p4 + 1)) AS CA5 (p5)
   CROSS APPLY (SELECT CHARINDEX('|', MT.MyColumn, CA5.p5 + 1)) AS CA6 (p6)
   CROSS APPLY (SELECT CHARINDEX('|', MT.MyColumn, CA6.p6 + 1)) AS CA7 (p7)
   CROSS APPLY (SELECT CHARINDEX('|', MT.MyColumn, CA7.p7 + 1)) AS CA8 (p8)
   CROSS APPLY (SELECT CHARINDEX('|', MT.MyColumn, CA8.p8 + 1)) AS CA9 (p9)
) AS Splits;

輸出:

引用自:https://dba.stackexchange.com/questions/310531