(对于不使用Delphi的读者:虽然以下是Delphi编码方面的问题,但我的实际技术问题不是特定于Delphi,而是关于如何找出Sql Server的方法将"理解"提交给它的TransactSql批处理.A" TAdoQuery"是一个Delphi类,它基本上包装了一个ADO命令和一个RecordSet,并将一个TSql批处理提交给一个Sql Server。通常情况下,使用TAdoQuery,批处理是单个语句,但我的q特别关注批处理可能包含多个语句的可能性。)
假设我有一个TAdoQuery,其Sql.Text包含一个TransactSql批处理包含 一个或多个陈述S1 [... Sn]。
我尝试做的是找出而不执行批处理是否a)批处理中的第一个(或唯一)语句S1将返回结果集(甚至如果为空)例如,通过它是一个SELECT语句或调用存储过程或表函数,或者其他什么,和b)服务器认为批处理中有多少语句。
Delphi的TAdoQuery的常规用户会知道,只是通过调用TAdoQuery.Open来测试批处理中的第一个(或唯一的)语句是否返回结果集,这很容易但有些麻烦。如果是,则检索该结果集,但如果没有,则调用.Open将引发异常。
所以,相反,我做了这样的事情:
type
TMyDataSet = class(TDataSet);
procedure TForm1.Button1Click(Sender: TObject);
begin
if AdoQuery1.Active then
AdoQuery1.Close;
AdoQuery1.FieldDefs.Clear;
TMyDataSet(AdoQuery1).OpenCursor(True);
AdoQuery1.FieldDefList.Update;
//AdoQuery1.FieldList.Update;
//Listbox1.Items.Assign(AdoQuery1.FieldList);
end;
调用.OpenCursor并将其InfoQuery参数设置为true会导致AdoQuery的FieldDefs 要填充 iff ,其Sql中的第一个语句将返回结果集,但与调用.Open不同,它不会导致批处理被执行。
到目前为止,这么好。这是我的问题:
如何(通过AdoQuery或其他方式)让Sql Server告诉我有多少 它认为批次包含的陈述? (我想我可能偶然发现了一些方法(需要进行更多的测试),但我对是否有人知道这样做的官方"技术感兴趣。)
顺便说一句,现在我通过其用于Sql Server的OleDB驱动程序使用古董(Sql Server 2000!)服务器。
答案 0 :(得分:3)
您可以使用SET SHOWPLAN_ALL
函数分析SQL Server中的语句,而不是执行查询。请注意,您无法在TADOQuery
中使用此功能,但只能使用TADOCommand
对象(例如TADOConnection.Execute
)。
测试表:
USE [TestCustomer]
GO
CREATE TABLE [dbo].[Tbl_test](
[Id] [int] NULL,
[col1] [varchar](50) NULL
) ON [PRIMARY]
GO
小型演示程序:
program SO27007086;
{$APPTYPE CONSOLE}
uses
ActiveX,
Db,
AdoDb,
SysUtils;
var
DbConn : TADOConnection;
function GetNumberOfStatements(SQLQuery: String): Integer;
var
Rs : _RecordSet;
LastId : Integer;
begin
Result := 0;
LastId := -1;
DbConn.Execute('SET SHOWPLAN_ALL ON');
Rs := DbConn.Execute(SQLQuery, cmdText, []);
while not Rs.EOF do
begin
if Rs.Fields['StmtId'].Value <> LastId then
begin
Inc(Result);
LastId := Rs.Fields['StmtId'].Value;
end;
if Rs.Fields['Parent'].Value = 0 then
Writeln(Rs.Fields['Type'].Value);
Rs.MoveNext;
end;
DbConn.Execute('SET SHOWPLAN_ALL OFF');
end;
begin
try
try
CoInitialize(nil);
DbConn := TADOConnection.Create(nil);
try
DbConn.ConnectionString := 'Provider=SQLOLEDB;Integrated Security=SSPI;Initial Catalog=TestCustomer;Data Source=localhost\SQLEXPRESS;MARS Connection=True;';
DbConn.Connected := True;
Writeln(GetNumberOfStatements('SELECT * FROM Tbl_test'));
Writeln(GetNumberOfStatements('SELECT * FROM Tbl_test DELETE FROM Tbl_test WHERE 1 = 2'));
Writeln(GetNumberOfStatements('SELECT * FROM Tbl_test INSERT INTO Tbl_Test (Id, Col1) VALUES (3, ''c''),(4, ''d'')'#13#10'DELETE FROM Tbl_test WHERE 1 = 2'));
finally
DbConn.Free;
end;
finally
CoUninitialize;
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
输出:
SELECT
1
SELECT
DELETE
2
SELECT
INSERT
DELETE
3