BALK INSERT来自逗号分隔的字符串

时间:2012-05-10 20:02:23

标签: sql-server-2008 csv bulkinsert

我在一列中有一个包含以下数据的表:

abc,2,2,34,5,3,2,34,32,2,3,2,2
def,2,2,34,5,3,2,34,32,2,3,2,2

我想获取这些数据并将其插入到另一个表中,使用逗号作为分隔符,就像在FIELDTERMINATOR语句中指定BULK INSERT一样。

有没有办法使用T-SQL执行此操作?

3 个答案:

答案 0 :(得分:3)

您需要使用Split函数将字符串拆分为表变量,然后将这些值插入表中。

那些分裂功能有,各种优缺点和各种参数等等。

Here is one that I quite like - 做得非常好,清楚解释。

使用该功能,您可以毫不费力地将列转换为其他表的单个条目。

答案 1 :(得分:3)

我不确定在T-SQL中是否有任何直接的方法,但是如果你想使用批量插入,你可以使用sqlcmd导出到CSV文件,然后将文件导回到服务器使用批量插入。

创建dbo.Split功能,您可以在此处参考split string into multiple record 有很多很好的例子。

如果您想以批处理方式执行,可以执行sqlcmd和'批量插入'

sqlcmd -S MyServer -d myDB -E -Q "select dbo.Split(col1) from SomeTable" 
       -o "MyData.csv" -h-1 -s"," -w 700

-s"," sets the column seperator to 

bulk insert destTable
from "MyData.csv"
with 
(
  FIELDTERMINATOR = ',',
  ROWTERMINATOR = '\n'
)

否则,您可以直接在T-SQL中进行操作,但是如果您具有相同的列定义标识。

 INSERT INTO DestinationTable
 SELECT dbo.Split(col1) FROM SomeTable

答案 2 :(得分:0)

编辑:允许多个字符分隔符

这是我解决它的方法,有两个函数可以拆分成列(如果你想要一个更完整的解决方案,也可以使用行分割,see my other post here)。它涉及:

  • 标量函数(fSubstrNth),用于在给定分隔符的情况下提取行的第n个字段
  • 用于查找分隔符的第n个索引的标量函数(fPatIndexMulti
  • (可选)替代Right函数以接受负值
  • 最后,在您的解决方案中使用一些特定代码,因为SQL不允许动态表函数定义(换句话说,您可以从具有动态列的函数中SELECT

现在,对于代码段:

<强> fSubstrNth

-- =============================================
-- Author:      Bernardo A. Dal Corno
-- Create date: 18/07/2017
-- Description: substring com 2 PatIndex limitando inicio e fim
-- =============================================
CREATE FUNCTION fSubstrNth
(
  @Text varchar(max),
  @Sep varchar(3),
  @N int --Nth campo
)
RETURNS varchar(max)
AS
BEGIN
  DECLARE @Result varchar(max)

  IF @N<1 RETURN ''
  IF @N=1
    SET @Result = substring(@Text, 1, dbo.fPatIndexMulti(@Sep,@Text,1)-1)
  ELSE
    SET @Result = substring(@Text, dbo.fPatIndexMulti(@Sep,@Text,@N-1)+LEN(@Sep), CASE WHEN dbo.fPatIndexMulti(@Sep,@Text,@N)>0 THEN dbo.fPatIndexMulti(@Sep,@Text,@N)-dbo.fPatIndexMulti(@Sep,@Text,@N-1)-LEN(@Sep) ELSE LEN(@Text)+1 END)

  RETURN @Result
END

<强> fPatIndexMulti

-- =============================================
-- Author:      Bernardo A. Dal Corno
-- Create date: 17/07/2017
-- Description: recursive patIndex
-- =============================================
CREATE FUNCTION [dbo].[fPatIndexMulti]
(
  @Find varchar(max),
  @In varchar(max),
  @N tinyint
)
RETURNS int
AS
BEGIN
  DECLARE @lenFind int, @Result int, @Texto varchar(max), @index int
  DECLARE @i tinyint=1

  SET @lenFind = LEN(@Find)-1
  SET @Result = 0
  SET @Texto = @In
  WHILE (@i <= @N) BEGIN
    SET @index = patindex('%'+@Find+'%',@Texto)
      IF @index = 0 RETURN 0
    SET @Result = @Result + @index
    SET @Texto = dbo.xRight(@Texto, (@index + @lenFind)*-1)

    SET @i = @i + 1
  END
  SET @Result = @Result + @lenFind*(@i-2)

  RETURN @Result
END

<强> Xright确定

-- =============================================
-- Author:      Bernardo A. Dal Corno
-- Create date: 06/01/2015
-- Description: Right inverso (para nros < 0)
-- =============================================
CREATE FUNCTION [dbo].[xRight] 
(
  @Texto varchar(8000),
  @Qntd int
)
RETURNS varchar(8000)
AS
BEGIN
  DECLARE @Result varchar(8000)

  IF (Len(@Texto) = 0) OR (@Qntd = 0)
    SET @Result = ''
  ELSE IF (@Qntd > 0) 
      SET @Result = Right(@Texto, @Qntd)
    ELSE IF (@Qntd < 0)
    SET @Result = Right(@Texto, Len(@Texto) + @Qntd)

  RETURN @Result
END

特定代码

SELECT 
     acolumn = 'any value',
     field1 = dbo.fSubstrNth(table.datacolumn,',',1),
     field2 = dbo.fSubstrNth(table.datacolumn,',',2),
     anothercolumn = 'set your query as you would normally do',
     field3 = (CASE dbo.fSubstrNth(table.datacolumn,',',3) WHEN 'C' THEN 1 ELSE 0 END)
FROM table

请注意:

  • fSubstrNth收到第n个字段,以便从数据列中提取&#39;
  • 查询可以像任何其他查询一样。这意味着它可以存储在过程,表格函数,视图等中。您可以按照您希望的任何顺序提取部分或全部字段,然后按需处理
  • 如果在存储过程中使用,您可以创建一种创建查询和临时表的通用方法,该表使用动态列加载字符串,但您必须调用另一个过程来使用数据或创建特定查询像上面的相同程序(这将使它非通用,只是更可重复使用)