在执行包含多个INSERT,UPDATE,...语句的SQL脚本时,我遇到Delphi / ADO错误处理的困难。只有当脚本的第一个SQL语句失败时,才会在Delphi中出现异常。如果第一个语句通过,则Delphi中不会有任何异常,无论脚本中发生什么变化。
这是我使用的Delphi代码:
var
DataSet: TADOQuery;
begin
...
try
DataSet.Close;
DataSet.ParamCheck := true;
DataSet.SQL.LoadFromFile(FileName);
DataSet.Prepared := true;
try
DataSet.ExecSQL;
finally
DataSet.Close;
end;
except
on E: Exception do
Logging.AddText(E.ClassName + ' error raised when executing ' + FileName + '. Message: ' + E.Message);
end;
...
end;
为了测试我使用了这个简单的脚本:
INSERT INTO TESTTABLE
VALUES ('John', 24);
INSERT INTO TESTTABLE
VALUES ('Ed', '32');
其中TESTTABLE只是一个包含两列的简单表:Name NVARCHAR(50)和Age INT。
当您更换时,例如,24岁以及24岁以下。在第一个INSERT语句中并使用Delphi代码运行脚本,Delphi / ADO将引发异常。但是,当您更换时,例如,32,三十二,三十二,等等。在第二个INSERT语句中,不会有异常。
我尝试通过将脚本放在存储过程中来解决这个问题" dbo.ErrorHandling"并发送
EXEC dbo.ErrorHandling
到ADO,但没有帮助。
CREATE PROCEDURE dbo.ErrorHandling
AS
BEGIN
INSERT INTO TESTTABLE
VALUES ('John', 24);
INSERT INTO TESTTABLE
VALUES ('Ed', '32');
END
我可以通过在脚本中使用TRY和CATCH来解决问题,并让它将错误记录到LOGGING表中。每次执行脚本后,Delphi都可以检查此表是否存在新错误。
但是,是否有可能在Delphi中捕获所有SQL服务器错误,或者我是否必须逐个执行INSERTS,UPDATES ......?
我使用Delphi XE6和SQLServer 2008 R2
答案 0 :(得分:1)
我不会看看AdoConnection的错误集合。 TAdoConnection.Errors
答案 1 :(得分:0)
我从来没有找到任何方法可以一次可靠地处理多个查询并明智地检测出问题。我认为正确的解决方案是一次执行一个语句。
这是我的一个程序中的代码,正是J__在评论中描述的内容。它在每个语句后使用GO处理SQL Server样式脚本。你可以替换" GO"检测器与声明结束的一些其他指示。它将整个事务批量化为单个全有或全无交易。最后一个终于有一些代码将最后一个查询保存到屏幕备忘录中,这样你就可以看到如果有异常则会失败。
procedure TDupFrame.LoadButtonClick(Sender: TObject);
var
Query: TADOQuery;
Reader: TStreamReader;
Line: string;
begin
Query := TADOQuery.Create(nil);
try
Query.Connection := ConfModule.ADOConnection;
Query.Connection.BeginTrans;
if ScriptOpenDialog.Execute(Self.Handle) then
begin
Reader := TStreamReader.Create(ScriptOpenDialog.FileName);
try
Query.SQL.BeginUpdate;
while not Reader.EndOfStream do
begin
Line := Reader.ReadLine;
if not SameText(Line, 'GO') then
begin
Query.SQL.Add(Line);
end
else
begin
Query.SQL.EndUpdate;
Query.ExecSQL;
Query.SQL.Clear;
Query.SQL.BeginUpdate;
end;
end;
Query.SQL.EndUpdate;
if Query.SQL.Count > 0 then Query.ExecSQL;
finally
Reader.Free;
end;
Query.Connection.CommitTrans;
end;
finally
SQLMemo.Lines.Assign(Query.SQL);
// rollback if we have missed the commit (ie an exception occurred)
if Query.Connection.InTransaction then
Query.Connection.RollbackTrans;
Query.Free;
end;
end;
答案 2 :(得分:0)
您需要使用ExecuteNoRecords选项配置TADOQuery或TADOCommand:
Query := TADOQuery.Create(nil);
Query.ExecuteOptions := [eoExecuteNoRecords];
在.NET中也是如此。如果在SqlCommand上使用ExecuteReader()或ExecuteScalar(),则如果单个命令中的第一个语句序列成功,则不会引发异常 - 无论后续语句有多少失败。
但是,如果调用ExecuteNonQuery(),则无论如何都会抛出正确的异常。