delphi中對MS SQL Server 2000的操作組件

unit DataBaseOptionsComp;

interface

uses    //使用到的包
  SysUtils, Classes,DB,ADODB,Variants,ComObj,winsvc,Registry,Windows,Messages,Dialogs,IniOptionsComp;

//const   //---常量定義

type
  TDataBaseOptions = class(TComponent)    //---定義組件,繼承於TComponen

  private

    //------------------- 屬性定義 ---------------------//

    FADOConnection : TADOConnection ;       //--  操作的ADO對象
    FIniOptions : TIniOptions ;

  public
    constructor Create(AOwner: TComponent); override;    //-- 重寫create 方法,對屬性進行初始化
    destructor Destroy; override;                        //-- 重寫Destroy 方法,釋放資源

    //------------------- 功能方法定義-----------------------//
    procedure SetADOConnection(const ADOConn:TADOConnection);
    procedure SetIniOptions(const IniOps: TIniOptions);

    Function ConnADO2DBServer:Boolean;
    Function ConnADO2DataBase:Boolean;overload;
    Function ConnADO2DataBase(DBName:string):Boolean;overload;
    function ClearADOConn:Boolean;
    Function GetLANSQLServerList:TStrings;
    Function GetSqlServerStatus:Integer;
    Function IsExistsMSSQL: Boolean;
    Function StartMSSQL:Boolean;
    function StopMSSQL:Boolean;
    function GetDataBaseNameList:TStrings;
    function AttachDataBase(DBName,DataBaseFilePath,LogFilePath:String):Boolean;
    function DetachDataBase(DBName:string):Boolean;
    function IsExistsDataBase(DBName:string):Boolean;
    function IsExistsProcedure(DBName,procName:string):Boolean;
    function DeleteProcedure(DBName,procName:string):Boolean;
    function CreateSpKillProcOnMaster:Boolean;
    function GetDBConnCount(DBName:string):Integer;
    function DelDBConnCount(DBName:string):Boolean;
    function BackUpDataBase(DBName,BackUpFilePath:String):boolean;
    function RestoreDataBase(DBName,restoreFilePath:String):Boolean;

  published
    { Published declarations }
   
    //--- 對屬性值進行讀取和保存操作,如 Get和Set
    property ADOConnection: TADOConnection read FADOConnection write SetADOConnection;
    property IniOptions: TIniOptions read FIniOptions write SetIniOptions;

  end;

  procedure Register;


implementation

 { Property Access }
//-------------------- 對屬性值的存取方法 --------------------//

procedure TDataBaseOptions.SetADOConnection(const ADOConn:TADOConnection);
begin
  FADOConnection := ADOConn;
  //ShowMessage('setADOConection');
end;

procedure TDataBaseOptions.SetIniOptions(const IniOps: TIniOptions);
begin
  FIniOptions := IniOps;
  //ShowMessage('SetIniOptions');
  if FIniOptions.AutoLogon then
  begin
     ConnADO2DataBase;
  end;
end;

//------------------------------------------------------------//

constructor TDataBaseOptions.Create(AOwner:TComponent);
begin
  inherited Create(AOwner);
  FADOConnection := TADOConnection.create(nil);      //-- 初始化一個ADO對象
  FIniOptions := TIniOptions.Create(nil);
  ShowMessage('111create');
end;

destructor TDataBaseOptions.Destroy;
begin
  ClearADOConn;
  FADOConnection.Free;
  FIniOptions.Free;
  inherited Destroy;
end;

procedure Register;
begin
  RegisterComponents('ADO', [TDataBaseOptions]);
end;

Function TDataBaseOptions.IsExistsMSSQL: Boolean;
//-------------------------------------------------------//
//------          IsExistsMSSQL 函數說明           ------//
//------  函數作用:檢測是否安裝SQL Server         ------//
//------  返回值:true:已安裝 ; false :未安裝     ------//
//-------------------------------------------------------//
var
  TmpReg: Tregistry;
begin
  TmpReg := Tregistry.Create;
  try
    try
      TmpReg.RootKey := HKEY_LOCAL_MACHINE;
      if not TmpReg.OpenKey('Software\Microsoft\MSSQLServer\Setup', False) then
        abort;
      Result := (TmpReg.ReadString('SQLPath') <> '');
      TmpReg.CloseKey;
    except
      Result := False;
    end;
  finally
    TmpReg.Free;
  end;
end;

{TODO:檢測SQLService服務的狀態。}
Function TDataBaseOptions.GetSqlServerStatus:Integer;
//-------------------------------------------------------//
//------      GetSqlServerStatus 函數說明          ------//
//------  函數作用:檢測當前SQL Server服務器狀態   ------//
//------  返回值:   0:服務器已關閉                ------//
//------      1:服務器正在運行  2:服務器已暫停     ------//
//------      3:服務器正在啓動(關閉-->啓動)        ------//
//------      4:服務器正在關閉.(啓動-->關閉)       ------//
//------      5:服務器正在繼續 (暫停-->啓動)       ------//
//------      6:服務器正在暫停  (啓動-->暫停)      ------//
//-------------------------------------------------------//
var
  ServiceStatus:Integer;
  SrvHandle: SC_HANDLE;                 //這些都在winsvc單元中定義的
  Service_Status: _SERVICE_STATUS;      //在winsvc單元中有定義
  SrvStatus: Integer;
begin
  ServiceStatus := -1 ;
  //取sql server的狀態,如果sql server正在運行則返回true ,否則返回 false
  SrvHandle := OpenSCManager('', SERVICES_ACTIVE_DATABASE,SC_MANAGER_ALL_ACCESS);
  SrvHandle := OpenService(SrvHandle, PChar('MSSQLServer'), SERVICE_QUERY_STATUS or SERVICE_START);
  if QueryServiceStatus(SrvHandle,Service_Status) then
  begin
    //判斷Sql Server服務的狀態
    SrvStatus := Service_Status.dwCurrentState;
    case SrvStatus of
      SERVICE_STOPPED: ServiceStatus := 0;          //服務器已關閉
      SERVICE_RUNNING: ServiceStatus := 1;          //服務器正在運行
      SERVICE_PAUSED:  ServiceStatus := 2;          // 服務器已暫停
      SERVICE_START_PENDING: ServiceStatus := 3;    //服務器正在啓動(關閉-->啓動)
      SERVICE_STOP_PENDING: ServiceStatus := 4;     //服務器正在關閉.(啓動-->關閉)
      SERVICE_CONTINUE_PENDING: ServiceStatus := 5; //服務器正在繼續 (暫停-->啓動)
      SERVICE_PAUSE_PENDING: ServiceStatus := 6;    //服務器正在暫停  (啓動-->暫停)
    end;
  end ;
  result := ServiceStatus ;
end;

function TDataBaseOptions.StartMSSQL:Boolean;
//-------------------------------------------------------//
//------            StartMSSQL 函數說明            ------//
//------  函數作用:啓動 SQL Server 服務器         ------//
//------  返回值:true:啓動成功 ;false :啓動失敗  ------//
//-------------------------------------------------------//
const
  MSSQL_98StartCommand = 'scm -action 1 -pwd "%s "';
  MSSQL_NTStartCommand = 'net start mssqlserver';
var
  cmdCom:string;
  Pass:string;
begin
  Pass := '';
  if not ((Win32MajorVersion >= 4) and (Win32Platform = VER_PLATFORM_WIN32_NT)) then
    cmdCom := Format(MSSQL_98StartCommand,[Pass])
  else
    cmdCom := MSSQL_NTStartCommand;
  try
    WinExec(PChar(cmdCom),SW_HIDE);
    Result := True;
  except
    Result := False;
  end;

end;

function TDataBaseOptions.StopMSSQL:Boolean;
//-------------------------------------------------------//
//------            StopMSSQL 函數說明             ------//
//------  函數作用:關閉 SQL Server 服務器         ------//
//------  返回值:true:關閉成功 ;false :關閉失敗  ------//
//------         如果當前服務器未啓動,返回true    ------//
//-------------------------------------------------------//
const
  MSSQL_98StopCommand = 'scm  -action  6';
  MSSQL_NTStopCommand = 'net stop mssqlserver';
begin
  try
    if not ((Win32MajorVersion >= 4) and (Win32Platform = VER_PLATFORM_WIN32_NT)) then
      WinExec(MSSQL_98StopCommand,SW_HIDE)
    else
      WinExec(MSSQL_NTStopCommand,SW_HIDE);
    Result := True;
  except
    Result := False;
  end;
end;

Function TDataBaseOptions.ConnADO2DBServer:Boolean;
//-------------------------------------------------------//
//------         ConnADO2DBServer 函數說明         ------//
//------  函數作用:連接 SQL Server 服務器         ------//
//------  返回值:true:連接成功 ;false :連接失敗  ------//
//------         如果當前服務器未啓動,返回false   ------//
//-------------------------------------------------------//
begin
  if GetSqlServerStatus=1 then
  begin
    with FADOConnection do
    begin
      Connected:=false;
      ShowMessage('22');
      if (FIniOptions.AuthenticateBySQLServer) then
        ConnectionString:=Format('Provider=SQLOLEDB.1;Password=%s;Persist Security Info=True;User ID=%s;Data Source=%s',[FIniOptions.Password,FIniOptions.UserID,FIniOptions.ServerName])
      else
        ConnectionString:=Format('Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Data Source=%s',[FIniOptions.ServerName]);
      try
        Connected:=true;
        result := True;
      except
        ConnectionString := '';
        Connected:=false;
        result := false;
      end;
    end;
  end
  else
    Result := false;
end;

Function TDataBaseOptions.ConnADO2DataBase:Boolean;
//-------------------------------------------------------//
//------         ConnADO2DataBase 函數說明         ------//
//------  函數作用:連接SQL Server服務器上的數據庫 ------//
//------           根據屬性FDataBaseName的值去連接 ------//
//------  返回值:true:連接成功 ;false :連接失敗  ------//
//------         如果當前服務器未啓動,返回false   ------//
//-------------------------------------------------------//
begin
  if GetSqlServerStatus=1 then
  begin
    if ConnADO2DBServer then
    begin
      with FADOConnection do
      begin
        Connected:=false;
        if( FIniOptions.AuthenticateBySQLServer )then
          ConnectionString:=Format('Provider=SQLOLEDB.1;Password=%s;Persist Security Info=True;User ID=%s;Initial Catalog=%s;Data Source=%s',[FIniOptions.Password,FIniOptions.UserID,FIniOptions.DataBaseName,FIniOptions.ServerName])
        else
          ConnectionString:=Format('Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=%s;Data Source=%s',[FIniOptions.DataBaseName,FIniOptions.ServerName]);
        try
          Connected:=true;
          result := True;
        except
          ConnectionString := '';
          Connected:=false;
          result := false;
        end;
      end;
    end
    else Result := False;
  end
  else  Result := false;
end;

Function TDataBaseOptions.ConnADO2DataBase(DBName:string):Boolean;
//-------------------------------------------------------//
//------         ConnADO2DataBase 函數說明         ------//
//------  函數作用:連接SQL Server服務器上的數據庫 ------//
//------           根據傳入的參數:DBName 去連接   ------//
//------  返回值:true:連接成功 ;false :連接失敗  ------//
//------         如果當前服務器未啓動,返回false   ------//
//-------------------------------------------------------//
begin
  if GetSqlServerStatus=1 then
  begin
    if ConnADO2DBServer then
    begin
      with FADOConnection do
      begin
        Connected:=false;
        if(FIniOptions.AuthenticateBySQLServer)then
          ConnectionString:=Format('Provider=SQLOLEDB.1;Password=%s;Persist Security Info=True;User ID=%s;Initial Catalog=%s;Data Source=%s',[FIniOptions.Password,FIniOptions.UserID,DBName,FIniOptions.ServerName])
        else
          ConnectionString:=Format('Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=%s;Data Source=%s',[DBName,FIniOptions.ServerName]);
        try
          Connected:=true;
          result := True;
        except
          ConnectionString := '';
          Connected:=false;
          result := false;
        end;
      end;
    end
    else Result := False;
  end
  else  Result := false;
end;

function TDataBaseOptions.ClearADOConn:Boolean;
//-------------------------------------------------------//
//------           ClearADOConn 函數說明           ------//
//------  函數作用:斷開並清除FADOConnection的連接 ------//
//------  返回值:true:清除成功 ;false :清除失敗  ------//
//------      如果當前ADO正處於連接狀態,則先關閉  ------//
//-------------------------------------------------------//
begin
  with FADOConnection do
  begin
    if connected then
    begin
      try
        connected := False;
        ConnectionString := '';
        result := true;
      except
        result := False;
      end;
    end
    else
    begin
      ConnectionString := '';
      result := True;
    end;
  end;
end;

Function TDataBaseOptions.GetLANSQLServerList:TStrings;
//-------------------------------------------------------//
//------       GetLANSQLServerList 函數說明        ------//
//------  函數作用:獲取局域網SQL Server服務器列表 ------//
//------  返回值:SQL Server服務器名稱列表         ------//
//------       (有時無法獲取本機的服務器名稱)      ------//
//-------------------------------------------------------//
var
  SQLServerObject,ServerList:Variant;
  i,nServers:integer;
  SQLServersName:TStrings;
begin
  SQLServersName := tstringlist.Create;
  try
    SQLServerObject := CreateOleObject('SQLDMO.Application');
    ServerList := SQLServerObject.ListAvailableSQLServers;
    nServers:=ServerList.Count;
    for i := 1 to nservers do
    begin
      SQLServersName.Add(ServerList.Item(i));
    end;
  finally
    SQLServerObject:=Unassigned;
    serverList:=Unassigned;
  end;
  Result := SQLServersName;
end;

function TDataBaseOptions.GetDataBaseNameList:TStrings;
//-------------------------------------------------------//
//------       GetDataBaseNameList 函數說明        ------//
//------  函數作用:獲取服務器上的數據庫列表       ------//
//------  返回值:數據庫名稱列表                   ------//
//------      先連接服務器,再獲取數據庫列表       ------//
//-------------------------------------------------------//
var
  adoQ_temp:TADOQuery ;
  DataBaseNameList:TStrings;
begin
  DataBaseNameList := TStringlist.Create;
  if ConnADO2DBServer then
  begin
    adoQ_temp:= TADOQuery.Create(nil);
    adoQ_temp.Connection := FADOConnection ;
    with adoQ_temp do
    begin
      Close;
      SQL.Clear;
      SQL.Add(' select name from  master..sysdatabases');
      try
        Open;
        while not Eof do
        begin
          DataBaseNameList.Add(Fields[0].AsString);
          Next;
        end;
      finally
        free;
        result := DataBaseNameList;
      end;
    end;
  end
  else  Result := DataBaseNameList;
end;

function TDataBaseOptions.AttachDataBase(DBName,DataBaseFilePath,LogFilePath:String):Boolean;
//-------------------------------------------------------//
//------          AttachDataBase 函數說明          ------//
//------  函數作用:附加指定路徑,指定名稱的數據庫 ------//
//------  返回值:是否附加成功                     ------//
//------      先連接服務器,再附加數據庫           ------//
//-------------------------------------------------------//
var
  adoQ_temp:TADOQuery ;
begin
  adoQ_temp:= TADOQuery.Create(nil);
  adoQ_temp.Connection := FADOConnection ;
  if ConnADO2DBServer then
  begin
    with adoQ_temp do
    begin
      Close;
      SQL.Clear;
      SQL.Add(format('EXEC sp_attach_db ''%s'' , ''%s'' , ''%s''',[DBName,DataBaseFilePath,LogFilePath]));
      try
        execsql;
        result := true;
      except
        result := false;
      end;
      Free;
    end;
  end
  else  result := False;
end;

function TDataBaseOptions.DetachDataBase(DBName:string):Boolean;
//-------------------------------------------------------//
//------          DetachDataBase 函數說明          ------//
//------  函數作用:分離指定名稱的數據庫           ------//
//------  返回值:是否分離成功                     ------//
//------      先連接服務器,然後清楚數據庫存在的   ------//
//------      連接,再附加數據庫                   ------//
//-------------------------------------------------------//
var
  adoQ_temp:TADOQuery ;
begin
  adoQ_temp:= TADOQuery.Create(nil);
  adoQ_temp.Connection := FADOConnection ;
  if ConnADO2DBServer then
  begin
    if DelDBConnCount(DBName) then
    begin
      with adoQ_temp do
      begin
        Close;
        SQL.Clear;
        SQL.Add(format('exec sp_detach_db ''%s''',[DBName]));
        try
          execsql;
          result := true;
        except
          result := false;
        end;
        Free;
      end;
    end
    else result := False;
  end
  else result := False;
end;

function TDataBaseOptions.IsExistsDataBase(DBName:string):Boolean;
//-------------------------------------------------------//
//------          IsExistsDataBase 函數說明        ------//
//------  函數作用:判斷指定名稱的數據庫是否存在   ------//
//------  返回值:存在爲true,不存在爲false        ------//
//------      先連接服務器,再判斷數據庫是否存在   ------//
//-------------------------------------------------------//
var
  adoQ_temp:TADOQuery ;
begin
  adoQ_temp:= TADOQuery.Create(nil);
  adoQ_temp.Connection := FADOConnection ;
  if ConnADO2DBServer then
  begin
    with adoQ_temp do
    begin
      Close;
      SQL.Clear;
      sql.add('use master;');
      sql.add(format('select count(name) as DB_Count from sysdatabases where name=''%s''',[DBName]));
      try
        open;
        if (FieldByName('DB_Count').Value) then
           result := True
        else
           result := False;
      except
        result := false;
      end;
      Free;
    end;
  end
  else  result := False;
end;

function TDataBaseOptions.IsExistsProcedure(DBName,procName:string):Boolean;
//---------------------------------------------------------------------//
//------                 IsExistsProcedure 函數說明              ------//
//------  函數作用:判斷指定數據庫上是否存在指定的存儲過程       ------//
//------  返回值:存在爲true,不存在爲false                      ------//
//------      先連接服務器,再判斷存儲過程是否存在               ------//
//---------------------------------------------------------------------//
var
  adoQ_temp:TADOQuery ;
begin
  adoQ_temp:= TADOQuery.Create(nil);
  adoQ_temp.Connection := FADOConnection ;
  if ConnADO2DBServer then
  begin
    with adoQ_temp do
    begin
      Close;
      SQL.Clear;
      sql.add(format('use %s;',[DBName]));
      sql.add('select * from sysobjects');
      sql.add(format(' where id = object_id(N''[%s]'') ',[procName]));
      sql.add('and OBJECTPROPERTY(id, N''IsProcedure'') = 1 ');
      try
        open;
        if not EOF then
           result := True
        else
           result := False;
      except
        result := false;
      end;                  
      Free;
    end;
  end
  else  result := False;
end;

function TDataBaseOptions.DeleteProcedure(DBName,procName:string):Boolean;
//---------------------------------------------------------------------//
//------                 DeleteProcedure 函數說明                ------//
//------  函數作用:刪除指定數據庫上指定的存儲過程               ------//
//------  返回值:刪除成功爲true,不成功爲false                  ------//
//------      先連接服務器,再判斷存儲過程是否存在,存在再刪除   ------//
//---------------------------------------------------------------------//
var
  adoQ_temp:TADOQuery ;
begin
  adoQ_temp:= TADOQuery.Create(nil);
  adoQ_temp.Connection := FADOConnection ;
  if ConnADO2DBServer then
  begin
    if IsExistsProcedure(DBName,procName) then
    begin
      with adoQ_temp do
      begin
        Close;
        SQL.Clear;
        sql.add(format('use %s;',[DBName]));
        sql.add(format('drop procedure %s',[procName]));
        try
          execsql;
          result := true;
        except
          result := false;
        end;
        Free;
      end;
    end
    else result := false;
  end
  else  result := False;
end;

function TDataBaseOptions.CreateSpKillProcOnMaster:Boolean;
var
  adoQ_temp:TADOQuery ;
begin
  adoQ_temp:= TADOQuery.Create(nil);
  adoQ_temp.Connection := FADOConnection ;
  if ConnADO2DBServer then
  begin
    with adoQ_temp do
    begin
      Close;
      SQL.Clear;
      sql.add('use master;');
      try
        ExecSQL;
      except
        result := false;
      end;
      SQL.Clear;
      sql.add('create procedure sp_kill_processes(@dbname varchar(100))');
      sql.add('as begin                                                ');
      sql.add('  declare @pro_kill nvarchar(255)                       ');
      sql.add('  declare tasklist_cursor cursor for select ''kill '' + ');
      sql.add('  convert(varchar(5),spid) + '' -- '' + p.loginame      ');
      sql.add('       from sysprocesses p,sysdatabases d               ');
      sql.add('       where p.dbid = d.dbid and d.name = @dbname       ');
      sql.add('  open tasklist_cursor                                  ');
      sql.add('  fetch next from tasklist_cursor into @pro_kill        ');
      sql.add('  while(@@fetch_status = 0)                             ');
      sql.add('  begin                                                 ');
      sql.add('    exec(@pro_kill)                                     ');
      sql.add('    if(@@error <> 0) return 0                           ');
      sql.add('    fetch next from tasklist_cursor into @pro_kill      ');
      sql.add('  end                                                   ');
      sql.add('  close tasklist_cursor                                 ');
      sql.add('  deallocate tasklist_cursor                            ');
      sql.add('  return 1                                              ');
      sql.add('end                                                     ');
      try
        execsql;
        result := true;
      except
        result := false;
      end;
      free;
    end;
  end
  else  result := False;
end;

function TDataBaseOptions.GetDBConnCount(DBName:string):Integer;
var
  adoQ_temp:TADOQuery ;
begin
  adoQ_temp:= TADOQuery.Create(nil);
  adoQ_temp.Connection := FADOConnection ;
  if ConnADO2DBServer then
  begin
    with adoQ_temp do
    begin
      Close;
      SQL.Clear;
      sql.add('use master;');
      sql.Add('select count(*) as connCount');
      sql.Add('from [master].[dbo].[sysprocesses]');
      sql.Add('where dbid in ( select dbid from [master].[dbo].[sysdatabases]');
      sql.Add(format('where name=''%s'')',[DBName]));
      try
        open;
        result := FieldByName('connCount').Value ;
      except
        result := -1;
      end;
      Free;
    end;
  end
  else  result := -1;
end;

function TDataBaseOptions.DelDBConnCount(DBName:string):Boolean;
var
  adoQ_temp:TADOQuery ;
begin
  adoQ_temp:= TADOQuery.Create(nil);
  adoQ_temp.Connection := FADOConnection ;
  if ConnADO2DBServer then
  begin
    if not IsExistsProcedure('master','sp_kill_processes') then
    begin
      if not CreateSpKillProcOnMaster then
        result := False;
    end;
    with adoQ_temp do
    begin
      Close;
      SQL.Clear;
      sql.add('use master;');
      sql.Add(format('exec [master].[dbo].[sp_kill_processes] %s',[DBName]));
      try
        execsql;
        result := True ;
      except
        result := False;
      end;
      Free;
    end;
  end
  else  result := False;
end;

function TDataBaseOptions.BackUpDataBase(DBName,backUpFilePath:String):Boolean;
var
  adoQ_temp:TADOQuery ;
begin
  adoQ_temp:= TADOQuery.Create(nil);
  adoQ_temp.Connection := FADOConnection ;
  if ConnADO2DBServer then
  begin
    with adoQ_temp do
    begin
      Close;
      SQL.Clear;
      sql.Add(format('backup database %s to disk=''%s''',[DBName,backUpFilePath]));
      try
        execsql;
        result := True ;
      except
        result := False;
      end;
      Free;
    end;
  end
  else  result := False;
end;

function TDataBaseOptions.RestoreDataBase(DBName,restoreFilePath:String):Boolean;
var
  adoQ_temp:TADOQuery ;
begin
  adoQ_temp:= TADOQuery.Create(nil);
  adoQ_temp.Connection := FADOConnection ;
  if DelDBConnCount(DBName) then
  begin
    with adoQ_temp do
    begin
      Close;
      SQL.Clear;
      SQL.ADD('use master;');
      SQL.ADD(format('restore database  %s from disk=''%s''',[DBName,restoreFilePath]));
      try
        execsql;
        result := True ;
      except
        result := False;
      end;
      Free;
    end;
  end
  else result := false;
end;


end.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章