【问题标题】:BULK INSERT from comma delimited stringBULK INSERT 从逗号分隔的字符串
【发布时间】:2012-05-10 20:02:23
【问题描述】:

我有一个表格,其中一列包含以下数据:

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

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

有没有办法使用 T-SQL 做到这一点?

【问题讨论】:

    标签: sql-server-2008 csv bulkinsert


    【解决方案1】:

    我不确定在 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
    

    【讨论】:

    • 谢谢。在考虑了更多之后,我想到了这样做。打算先试试 split 功能,然后看看我是否需要这样做。
    【解决方案2】:

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

    那里有 的这些拆分函数,具有各种优缺点以及各种数量的参数等等。

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

    使用该功能,您应该可以轻松地将列转换为其他表的单独条目。

    【讨论】:

    • 谢谢。我会再调查一下。
    • 我无法弄清楚如何将字符串拆分为列而不是行。这可能吗?
    【解决方案3】:

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

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

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

    现在,对于代码 sn-ps:

    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 个字段
    • 查询可以是任何其他查询。这意味着它可以存储在过程、表格函数、视图等中。您可以按您希望的任何顺序提取部分或全部字段,并按您的意愿进行处理
    • 如果在存储过程中使用,您可以创建一个通用的方法来创建一个查询和临时表来加载带有动态列的字符串,但是您必须调用另一个过程来使用数据或创建一个特定的查询像上面一样在相同的过程中(这将使它成为非通用的,只是更可重用)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-21
      • 1970-01-01
      • 2011-09-07
      相关资源
      最近更新 更多