Обновление № 2: См. https://social.msdn.microsoft.com/Forums/sqlserver/en-US/e652377d-0607-45ca-b4a0-274361bff85a/how-to-set-identityinsert-in-dynamic-sql?forum=transactsql
Я еще не полностью переварил его, но проблема ОП кажется очень похожей.
Я пытался сконструировать SQL для использования EXEC
FDQuery1.SQL.Text := 'EXEC (' + ''''+ sSetIIOn + ';' + sInsert + ';' + sSetIIOff + '''' + ')';
, чтобы избежать использования sp_executesql, но, к сожалению, FD не может правильно проанализировать SQL, поэтому он выдает «аргумент вне диапазона»ошибка при настройке параметров.
Обновление: Curiouser и curiouser ...
Следующий код выполняется без ошибок на SS2014 и вставляет ожидаемые 10 строк:
const
sEmptyTable = 'delete from dbo.identtest';
sSetIIOn = 'set identity_insert dbo.identtest ON';
sSetIIOff = 'set identity_insert dbo.identtest OFF';
sSelect = 'select * from dbo.identtest';
sInsert = 'insert dbo.identtest (ID, Name) values(%d, %s)';
procedure TForm2.TestIdentityInsert;
var
i : Integer;
S : String;
begin
FDQuery1.ExecSql(sEmptyTable);
FDQuery1.ExecSql(sSetIIOn);
for i := 1 to 10 do begin
S := Format(sInsert, [i, '''Name' + IntToStr(i) + '''']);
FDQuery1.ExecSQL(S);
end;
FDQuery1.ExecSql(sSetIIOff);
FDQuery1.Sql.Text := sSelect;
FDQuery1.Open;
end;
procedure TForm2.Button1Click(Sender: TObject);
begin
TestIdentityInsert;
end;
Однако , замена цикла for
на
FDQuery1.SQL.Text := sSetIIOn + ';' + sInsert + ';' + sSetIIOff;
FDQuery1.Params.ArraySize := Rows;
for i := 0 to Rows - 1 do begin
FDQuery1.Params[0].AsIntegers[i] := i;
FDQuery1.Params[1].AsStrings[i] := 'Name' + IntToStr(i);
end;
приводит к исключению, которое вы цитируете. С помощью SSMS Profiler я проверил, что SQL, отправленный на сервер, кажется правильным (и не то, что fi корректируется слоем MDac, как это иногда бывает):
exec sp_executesql N'set identity_insert dbo.identtest ON;insert dbo.identtest values(@P1, @P2);set identity_insert dbo.identtest OFF',N'@P1 int,@P2 nvarchar(4000)',0,N'Name0' [etc, repeated 9 times]
, поэтому возникает вопрос, почемуне используете sp_executesql
уважайте настройку Identity_Insert и есть ли другой способ, который делает?