获取TransactSql批处理中语句数的计数

时间:2014-11-19 00:54:42

标签: sql-server tsql delphi ado

(对于不使用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!)服务器。

1 个答案:

答案 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