如何将String传递给Bulk insert而不是文件?

时间:2017-06-13 06:48:17

标签: sql-server insert bulkinsert

我曾经使用批量插入命令来转换Csv文件int table.Resently我在CSV服务器中保存了一个CSV文件作为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字符串插入到表中。

1 个答案:

答案 0 :(得分:0)

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

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

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

现在,对于代码段:

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