关于批量执行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.

 

 

你可能感兴趣的:(sql语句)