2017-02-23 49 views
1

SQL版本SQL逗号分隔值在参数不同的行

对于一个存储过程输入,例如:

  • @CustomerID = '1,2,3,4'
  • @address = '俄勒冈'
  • @city = '波特兰'

。我需要将值插入单独的行中,如下所示:

customerID | address city 
--------------+------------------ 
    1   | Oregon Portland 
    2   | Oregon Portland 
    3   | Oregon Portland 
    4   | Oregon Portland 

我需要帮助,了解如何在单个参数中插入CSV值以分隔行。

+1

检查这个答案您正在使用什么版本的SQL Server http://stackoverflow.com/questions/10914576/t-sql-split-string –

+1

?您的'@ CustomerID'参数是否必须是分隔字符串,或者您可以使用[表值参数](https://msdn.microsoft.com/en-us/library/bb510489(v = sql.100))。 ASPX)? – GarethD

回答

6

杰夫MODEN使用CSV分路器功能:

declare @CustomerId varchar(8000) = '1,2,3,4,' 
     , @Address varchar(64) = 'Oregon' 
     , @City  varchar(64) = 'Portland' 

select 
    CustomerId = d.Item 
    , Address = @Address 
    , City = @City 
from [dbo].[delimitedsplit8K](@CustomerId,',') as d 
where d.Item <> '' 

测试设置:http://rextester.com/COUJVK17338

回报:

+------------+---------+----------+ 
| CustomerId | Address | City | 
+------------+---------+----------+ 
|   1 | Oregon | Portland | 
|   2 | Oregon | Portland | 
|   3 | Oregon | Portland | 
|   4 | Oregon | Portland | 
+------------+---------+----------+ 

分裂ST环引用:

+0

我想你已经错过了Aaron Bertrand关于这个主题的最相关作品 - [Splitting Strings:Now with less T-SQL](https:// sqlperformance。com/2012/08/t-sql-queries/splitting-strings-now-with-less-t-sql) - 实际上最好的做法是避免将所有数据拆分在一起并传递表值函数。这说的仍然是最好的答案,所以得到了我的投票。 – GarethD

+0

@GarethD我没有错过它,但是如果我发布了所有关于Aaron Bertrand的字符串分裂的链接,我认为这些链接是相关的,那么这个列表会有点压倒性的。对于那些感兴趣的人,他们会在这些文章中找到许多与其他文章的链接。这里还有两个。 - [SQL Server 2016中的STRING_SPLIT():后续#1 - Aaron Bertrand](https://sqlperformance.com/2016/04/sql-server-2016/string-split-follow-up-1) - [SQL Server 2016中的STRING_SPLIT():后续#2 - Aaron Bertrand](https://sqlperformance.com/2016/04/sql-server-2016/string-split-follow-up-2) – SqlZim

+0

感谢你的帮助和参考 –

0

使用while循环

WHILE len(@CustomerID) >1 
BEGIN 
insert into MyTable (customerID, Address, City) 
values (left(@CustomerID, charindex(',',@CustomerID)), @Address, @City) 

@CustomerID = substring(@CustomerID, 
         charindex(',',@CustomerID)+1, 
         len(@CustomerID)-charindex(',',@CustomerID)) 

END 
1

一种方法是递归CTE:

with c as (
     select left(@CustomerId, charindex(',', @CustomerId) - 1) as customerid, 
      substring(@CustomerId, charindex(',', @CustomerId) + 1, 8000) as rest 
     union all 
     select left(rest, charindex(',', rest) - 1), 
      substring(rest, charindex(',', rest) + 1, 8000) 
     from c 
     where rest like '%,%' 
    ) 
insert into t(customerid, Address, City) 
    select customerid, @Address, @City 
    from c 
    where customerid <> ''; 
+0

谢谢,这似乎是工作:) –

+0

谢谢你,这似乎是工作,但它只适用于Ids的个位数值,如1,2,3,4但不适用于11, 12,13。我如何动态设置长度选择? –

+0

@Jhjrysmth。 。 。我在CTE的递归部分错过了对@ @ CustomerId的引用。我将其改为“休息”。 –

0

使用XQuery

一个有趣的方式
0

我使用了一个自定义的表值分割函数,它将自定义指定分隔符上的分隔字符串分开,并将结果返回到表变量中。

CREATE FUNCTION dbo.[Split] 
     (
      @List NVARCHAR(2000), 
      @SplitOn NVARCHAR(5) 
    ) 
     RETURNS @RtnValue TABLE 
     (
      Id INT IDENTITY(1,1), 
      Value NVARCHAR(100) 
    ) 
     AS 
     BEGIN 
      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)) 
      RETURN 
     END; 
     GO 

    SELECT * from dbo.Split('1,2,3,1',',') 
    GO 

示例链接:http://rextester.com/FXX54250

0

如果使用SQL Server 2016或更高版本(SQL Server的13.0),你可以使用新的STRING_SPLIT功能。

declare @CustomerID varchar(50) = '1,2,3,4,', 
    @Address varchar(50) = 'Oregon', 
    @City varchar(50) = 'Portland'  

SELECT value as CustomerID, @Address, @City 
FROM STRING_SPLIT(@CustomerID, ',') 
WHERE RTRIM(value) <> ''; 

输出:

CustomerID Address City 
1   Oregon Portland 
2   Oregon Portland 
3   Oregon Portland 
4   Oregon Portland