【问题标题】:How to pass String to Bulk insert instead of file?如何将字符串传递给批量插入而不是文件?
【发布时间】:2017-11-14 19:13:58
【问题描述】:

我曾经使用批量插入命令来转换 Csv 文件 int 表。最近我将 CSV 文件保存为 sql server 中的 VarBinary 值。现在我可以通过使用 CAST 和 CONVERT 函数将其类型转换为 Varchar 从 Varbinary 文件中获取数据.但是现在我遇到了一个问题,我无法使用批量插入将这个包含 csv 内容的 Varchar 字符串转换为表格。任何人都可以帮助我 我的示例代码如下:

--@String contains varchar value of CSV file content.  
SET @sql = 'BULK INSERT TempCsv
FROM  ''' + @String  + '''
WITH
(
    FIRSTROW = 2,
    FIELDTERMINATOR = '','',  
    ROWTERMINATOR = ''\n'',   
    TABLOCK
)'

请帮助我。是否有任何方法或替代方法可以将数据从 csv 字符串插入到表中。

【问题讨论】:

    标签: sql-server insert bulkinsert


    【解决方案1】:

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

    我就是这样解决的。它涉及:

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

    现在,对于代码 sn-ps:

    xftSplit

    -- =============================================
    -- Author:      Bernardo A. Dal Corno
    -- Create date: 15/07/2014
    -- Description: Quebra valores a partir de caracteres e retorna lista em tabela
    -- =============================================
    CREATE FUNCTION [dbo].[xftSplit] 
    (
        @Texto varchar(max),
        @Splitter varchar(3)
    )
    RETURNS 
    @Lista TABLE 
    (
        ValoresQuebrados varchar(8000)
    )
    AS
    BEGIN
    DECLARE @Pos Smallint
    
      While len(@Texto)>0 BEGIN
        SET @Pos = Patindex('%'+@Splitter+'%',@Texto)
    
        IF @Pos > 0 BEGIN
          INSERT INTO @Lista
          SELECT left(@Texto, @Pos-1)
    
          SET @Texto = right(@Texto, len(@Texto)-@Pos)
        END
        ELSE BEGIN
          INSERT INTO @Lista
          SELECT @Texto
    
          SET @Texto = ''
        END
      End
    
      RETURN 
    END
    

    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(line,',',1),
         field2 = dbo.fSubstrNth(line,',',2),
         anothercolumn = 'set your query as you would normally do',
         field3 = (CASE dbo.fSubstrNth(line,',',3) WHEN 'C' THEN 1 ELSE 0 END)
    FROM (
      SELECT line = ValoresQuebrados FROM dbo.xftSplit(@StringVariable, char(10))
    ) lines
    

    注意:

    • fSubstrNth 接收要从行中提取的第 n 个字段
    • xftSplit 接收一个变量,其中包含您要批量处理的字符串(无论来源)和一个 char(10) 作为 \n 的拆分器,但它可以是其他任何东西
    • 查询可以是任何其他查询。这意味着它可以存储在过程、表格函数、视图等中。您可以按您希望的任何顺序提取部分或全部字段,并按您的意愿进行处理
    • 如果在存储过程中使用,您可以创建一个通用的方法来创建一个查询和临时表来加载带有动态列的字符串,但是您必须调用另一个过程来使用数据或创建一个特定的查询像上面一样在相同的过程中(这将使其非泛型,只是更可重用)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-24
      • 1970-01-01
      • 2018-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-16
      相关资源
      最近更新 更多