Массовая вставка с использованием хранимой процедуры - PullRequest
30 голосов
/ 29 октября 2010

У меня есть запрос, который работает нормально:

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 Неправильный синтаксис рядом с ключевым словом «с».Если этот оператор является общим табличным выражением, предложением xmlnamespaces или предложением контекста отслеживания изменений, предыдущий оператор должен заканчиваться точкой с запятой.

Скажите, пожалуйста, что я делаю неправильно и что я могу сделатьсделать, чтобы это работало в хранимой процедуре.

Спасибо

Ответы [ 4 ]

40 голосов
/ 29 октября 2010

В вашем коде хранимой процедуры нет ничего плохого - дело в том, что команда 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
0 голосов
/ 26 декабря 2018
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;
0 голосов
/ 27 сентября 2018

Существует альтернатива динамическому SQL, если у вас есть доступ к SQLCmd exe.

Утилита 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"
0 голосов
/ 11 января 2013

Вы просто попробуйте, я думаю, вам нужно загрузить этот 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
...