SQL Server - 按固定分隔符拆分每个表行

时间:2015-12-22 10:19:34

标签: sql-server

拥有字符串“abcd | efg | hijkl”我需要将其拆分为以下三个值:“abcd”,“efg”和“hijkl”。这很简单 - 考虑到分隔符可以改变它的位置,下面的代码将起作用:

DECLARE @id VARCHAR(100), @line1 INT, @line2 INT
SET @id = 'abcd|efg|hijkl'
SET @line1 = (SELECT CHARINDEX('|', @id))+1
SET @line2 = (SELECT CHARINDEX('|', @id, CHARINDEX('|', @id)+1))

SELECT LEFT(@id, CHARINDEX('|', @id)-1) AS First
  ,SUBSTRING(@id, @line1, @line2-@line1) AS Middle
  ,SUBSTRING(@id, @line2+1, len(@id)-@line2) AS Last

现在,假设我有一个类似字符串的表,我想检索由'First','Middle'和'Last'列组成的表,每个列都有适当的值。 我知道我可以用@ line1和@ line2代替select查询,但代码将不再可读了...怎么做?

3 个答案:

答案 0 :(得分:1)

使用 XML

尝试使用此代码一次

带有样本值的临时表

create table #YOUR_TABLE
    (
    [Name] varchar(100)
    )

    insert into #YOUR_TABLE values('abcd|efg|hijkl'),('a|e|hij')

使用XML查询所需的输出:

DECLARE @delimiter VARCHAR(100)

SET @delimiter='|' --IN This Variable you can change your required delimeter
;

WITH CTE
     AS (SELECT [Name],
                Cast('<M>'
                     + Replace([Name], @delimiter, '</M><M>')
                     + '</M>' AS XML) AS [Name XML]
         FROM   #YOUR_TABLE)
SELECT [Name],
       [Name XML].value('/M[1]', 'varchar(100)') AS [First Name],
       [Name XML].value('/M[2]', 'varchar(100)') AS [Middle Name],
       [Name XML].value('/M[3]', 'varchar(100)') AS [Last Name]
FROM   CTE 

<强>输出

Name            First Name  Middle Name Last Name
abcd|efg|hijkl   abcd        efg          hijkl
a|e|hij          a           e            hij

这里的第一步是将该字符串转换为XML并替换分隔符(即&#39; |&#39;在您的情况下使用一些开始和结束XML标记。这里我将delimeter替换为&#39; &#39;标签。

答案 1 :(得分:1)

如果总有3个字符串,那么您可以使用PARSENAME函数:

DECLARE @s VARCHAR(100) = 'abcd|efg|hijkl'

SELECT PARSENAME(REPLACE(@s, '|', '.'), 3),
       PARSENAME(REPLACE(@s, '|', '.'), 2),
       PARSENAME(REPLACE(@s, '|', '.'), 1)

答案 2 :(得分:0)

您可以使用outer apply存储中间卡路里结果(假设此处列的名称也为id):

select
    LEFT(id, CHARINDEX('|', id)-1) AS First
    ,SUBSTRING(id, line1.Value, line2.Value - line1.Value) AS Middle
    ,SUBSTRING(id, line2.Value + 1, len(id) - line2.Value) AS Last
from your_table
    outer apply (SELECT CHARINDEX('|', id) + 1 as Value) as line1
    outer apply (SELECT CHARINDEX('|', id, CHARINDEX('|', id) + 1) as Value) as line2

这样可以防止对同一表达式进行多次复制粘贴,并且您的代码仍然可读。