【问题标题】:Bulk insert using stored procedure使用存储过程批量插入
【发布时间】:2011-05-02 08:03:57
【问题描述】:

我有一个运行良好的查询:

BULK INSERT ZIPCodes 
FROM  'e:\5-digit Commercial.csv' 
WITH 
( 
     FIRSTROW = 2 ,
    FIELDTERMINATOR = ',', 
    ROWTERMINATOR = '\n' 
)

但现在我想为它创建一个存储过程。

我写了下面的代码来制作它的存储过程:

create proc dbo.InsertZipCode
@filepath varchar(500)='e:\5-digit Commercial.csv'
as
begin
BULK INSERT ZIPCodes 
FROM  @filepath 
WITH 
( 
     FIRSTROW = 2 ,
    FIELDTERMINATOR = ',', 
    ROWTERMINATOR = '\n' 
)
end

但显示错误:

消息 102,级别 15,状态 1,程序 InsertZipCode,第 6 行 语法错误 在“@filepath”附近。

消息 319,级别 15,状态 1,程序 InsertZipCode,第 7 行 语法错误 在关键字'with'附近。如果这 语句是一个公共表 表达式、xmlnamespaces 子句或 更改跟踪上下文子句, 必须终止先前的语句 用分号。

请告诉我我做错了什么以及我可以做些什么来使它在存储过程中工作。

谢谢

【问题讨论】:

    标签: sql sql-server-2008 stored-procedures bulkinsert


    【解决方案1】:

    您的存储过程代码没有任何问题 - 重点是:BULK INSERT 命令不能接受文件名作为变量。

    这确实有效:

    BULK INSERT ZIPCodes 
    FROM  'e:\5-digit Commercial.csv' 
    WITH 
    

    但这永远不会起作用 - 是否在存储过程中:

    DECLARE @filename VARCHAR(255)
    SET @filename = 'e:\5-digit Commercial.csv' 
    
    BULK INSERT ZIPCodes 
    FROM @filename
    WITH 
    

    不幸的是,您不能这样做。您可以考虑将 BULK INSERT 语句构建为字符串(具有固定文件名),然后将其作为动态 SQL 执行 - 但我真的没有看到任何其他解决方案。

    DECLARE @filepath nvarchar(500)
    SET @filepath = N'e:\5-digit Commercial.csv'
    
    DECLARE @bulkinsert NVARCHAR(2000)
    
    SET @bulkinsert = 
           N'BULK INSERT ZIPCodes FROM ''' + 
           @filepath + 
           N''' WITH (FIRSTROW = 2, FIELDTERMINATOR = '','', ROWTERMINATOR = ''\n'')'
    
    EXEC sp_executesql @bulkinsert
    

    【讨论】:

    • 感谢我已经将它作为一个字符串完成并使用 exec 运行它,但我认为可能还有其他一些解决方案。非常感谢。
    • marc_s 但我可以从过程中执行 EXEC sp_executesql @bulkinsert 吗?所以我的 C# 接口将调用我的 SQL 过程,将参数(文件路径,表名)传递到,它会创建字符串并调用动态 SQL?
    【解决方案2】:

    你试试看,我想你需要把这个 CSV 文件直接上传到“E”盘。为此,我认为您需要拥有管理员权限,或者询问从事数据库管理的人员。

    create procedure dbo.InsertZipCode
    AS
    BEGIN
    SET NOCOUNT ON;
     BULK
       INSERT ZIPCodes from 'e:\5-digit Commercial.csv'
    WITH
    (
        FIELDTERMINATOR = ',',
        ROWTERMINATOR = '\n'
    )
    END
    

    【讨论】:

      【解决方案3】:

      如果您有权访问 SQLCmd exe,则可以使用动态 SQL 的替代方法。

      SqlCmd 实用程序允许您使用 -v 参数传递字符串替换变量。

      您可以使用名为“filepath”的模板变量,当您通过 cmdline 执行脚本时,该变量将被替换。

      SQL 脚本如下所示:

      BULK INSERT ZIPCodes 
      FROM  '$(filepath)' 
      WITH 
      ( 
           FIRSTROW = 2 ,
          FIELDTERMINATOR = ',', 
          ROWTERMINATOR = '\n' 
      )
      end
      

      然后,您可以使用以下命令从命令行执行脚本:

      sqlcmd -b -S SERVER\INSTANCEHERE -E -i "PATH\FILENAMEHERE.Sql" -v FilePath = "e:\5-digit Commercial.csv" -s "|"
      

      示例的重要部分是 -v 参数:

      -v FilePath = "e:\5-digit Commercial.csv"
      

      【讨论】:

        【解决方案4】:
        create PROC TestInsert
            (
              @stuName NVARCHAR(50) ,
              @XmlData XML
            )
        AS
            BEGIN
                BEGIN TRY 
                    INSERT  INTO dbo.Test_Student
                            ( stuName 
                            )
                    VALUES  ( @stuName
                            );
                    DECLARE @id BIGINT;
                    SET @id = ( SELECT  SCOPE_IDENTITY()
                              ); 
                    INSERT  INTO dbo.Test_Qual
                            ( stuid ,
                              stuclass ,
                              InstituteId ,
                              obtmark ,
                              totalmark ,
                              per
                            )
                            SELECT  @id ,
                                    col.value('stuclass[1]', 'nvarchar(50)') AS stuclass ,
                                    col.value('InstituteId[1]', 'int') AS InstituteId ,
                                    col.value('obtmark[1]', 'nvarchar(100)') AS obtmark ,
                                    col.value('totalmark[1]', 'nvarchar(50)') AS totalmark ,
                                    col.value('per[1]', 'nvarchar(50)') AS per
                            FROM    @XmlData.nodes('Parent/child') AS Doc ( col );  
        
                    SELECT  @id AS RegisIdNUH ,
                            1 AS Flag ,
                            'Save' AS Msg
                    FROM    dbo.Test_Student R
                    WHERE   R.stuid = @id;
        
                END TRY
                BEGIN CATCH
                    SELECT  0 AS Flag ,
                            'Some Error occur' AS Msg;
                    ROLLBACK;
                END CATCH;
            END;
        

        【讨论】:

        • 这到底是什么?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-14
        • 1970-01-01
        • 2010-12-29
        • 1970-01-01
        相关资源
        最近更新 更多