关于批量执行SQL语句

在数据库应用中,一般我们是用企业管理器来创建数据库,表,存储过程,触发器等。然后再导出SQL语句到一个 *.sql 文件里。然后我们在查询分析器执行这些语句即可。

当然,我们更想在程序中去执行这些语句,而不是再去打开查询分析器。

当我们要在程序中批量执行SQL时,需要明白AdoConnection,或AdoQuery(假设我们使用ADO组件)可以执行的语句有什么要求。

1、在查询分析器里,一条SQL语句,我们可以直接写成

Select * from aTable where ID=123

或者

Select * from aTable where ID=123;

这两条语句结果相同。不同的地方只是第二条多了一个“;”,用来表示一条语句结束。

2、在查询分析器里,多条SQL语句的写法

insert into aTable(Field1,Field2) values( '值一','值二')

go

这里的 go 表示一个批处理

 

根据以上两点,我们可以看出,我们要在程序中批量执行SQL语句,需要判断一个完整的操作包含几条语句,这些语句是不是可以单独执行等。

下面是一个示例程序(程序中不涉及到Select操作)

代码
unit BatchSQL; 

   批量执行SQL脚本 
   E
-main: goldli@163.com 

interface 
uses 
  SysUtils,ADODB,Classes; 

type 
   TOnException 
= procedure(const E: Exception) of object
   TOnSQLExecute 
= procedure(const strSQL: string;const RowsAffected:Integer) of object

type 
  {完整的SQL语句} 
  TSQLString 
= class 
  
private 
    FBuffer:
string
    FSQL:TStrings; 
    FChanged:Boolean; 
    function GetSQL:
string
  
public 
    constructor Create; 
    destructor  Destroy;
override
    procedure   Append(
const StrSQL:string); 
    property    SQL:
string read GetSQL; 
  end; 

  TBatchSQL 
= class 
  
private 
    FConnection:TADOConnection; 
    FSQLList:TList; 
    FOnException:TOnException; 
    FOnSQLExecute:TOnSQLExecute; 
  
public 
    constructor Create(
const AConnection:TADOConnection); 
    destructor  Destroy;
override
    property  Connection:TADOConnection write FConnection; 
    procedure LoadFromFile(
const FileName:string); 
    procedure Execute; 
    property  OnException:TOnException write FOnException; 
    property  OnSQLExecute:TOnSQLExecute write FOnSQLExecute; 
  end; 

implementation 

{ TSQLString } 

procedure TSQLString.Append(
const StrSQL: string); 
begin 
  FSQL.Append(StrSQL); 
  FChanged:
=True; 
end; 

constructor TSQLString.Create; 
begin 
  FSQL:
=TStringList.Create; 
end; 

destructor TSQLString.Destroy; 
begin 
  FSQL.Free; 
  inherited; 
end; 

function TSQLString.GetSQL: 
string
begin 
  
if FChanged then 
  begin 
    FBuffer:
=FSQL.Text; 
    FChanged:
=False; 
  end; 
  Result:
=FBuffer; 
end; 

{ TBatchSQL } 

constructor TBatchSQL.Create(
const AConnection: TADOConnection); 
begin 
  
if Assigned(AConnection) then 
    FConnection:
=AConnection; 
  FSQLList:
=TList.Create; 
end; 

destructor TBatchSQL.Destroy; 
var 
  i:Integer; 
begin 
  FConnection:
=nil; 
  
for i:= FSQLList.Count -1 downto 0 do 
    TSQLString(FSQLList.Items[i]).Free; 
  FSQLList.Free; 
  inherited; 
end; 

procedure TBatchSQL.Execute; 
var 
  i:Integer; 
  Qry:TADOQuery; 
  SQLString:TSQLString; 
begin 
  Assert(Assigned(FConnection),
'数据库连接不能为nil.'); 
  Assert(FSQLList.count 
> 0,'请先加载SQL文件.'); 
  FConnection.LoginPrompt:
=False; 
  FConnection.Connected:
=True; 
  Qry:
=TADOQuery.Create(nil); 
  with Qry 
do 
  begin 
    Connection:
=FConnection; 
    Prepared:
=True; 
    
for i:=0 to FSQLList.Count -1 do 
    begin 
      SQLString:
=TSQLString(FSQLList.Items[i]); 
      SQL.Clear; 
      SQL.Add(SQLString.SQL); 
      
try 
        ExecSQL; 
        
if Assigned(FOnSQLExecute) then 
          FOnSQLExecute(SQLString.SQL,RowsAffected); 
      except 
        on E:Exception 
do 
          
if Assigned(FOnException) then 
            FOnException(E) 
          
else 
            raise Exception.Create(
'SQL语句出错:' + sLineBreak + SQLString.SQL); 
      end; 
    end; 
    Free; 
  end;  
end; 

procedure TBatchSQL.LoadFromFile(
const FileName: string); 
var 
  SqlStr,Tmp:
string
  F:TextFile; 
  SQLString:TSQLString; 
begin 
  Assert(FileExists(FileName),
'SQL文件不存在,不能加载.');  
  AssignFile(F,FileName); 
  Reset(f); 
  Repeat 
    Readln(F,Tmp); 
    
if Tmp='GO' then 
    begin 
      SQLString:
=TSQLString.Create; 
      SQLString.Append(SqlStr); 
      FSQLList.Add(SQLString); 
      SqlStr:
=''
      Tmp:
=''
    end; 
    SqlStr:
=SqlStr + Tmp; 
  Until eof(F); 
  Closefile(F); 
end; 

end.

 

 

posted @ 2010-05-23 14:17  (大贤者模式)  阅读(5034)  评论(2编辑  收藏  举报