如何从Delphi运行数据库脚本文件?

7
我想要做以下事情。 1)创建一个数据库。 2)在创建表、存储过程等时运行一个脚本(此脚本是通过SMS“生成脚本”选项创建的)。
我找到了以下代码:http://www.delphipages.com/forum/showthread.php?t=181685,并将其修改为以下内容:

try

ADOQuery.ConnectionString := 'Provider=SQLOLEDB.1;Password=' +

edtPassword.Text + ';Persist Security Info=True;User ID=' + edtUser.Text + ';Initial Catalog=master;Data Source=' + edtServerName.Text;

ADOQuery.SQL.Clear;
ADOQuery.SQL.Text := 'create DataBase ' + edtWebDBName.Text;
ADOQuery.ExecSQL; // should check existance of database
ADOWeb.Connected := false;
ADOWeb.ConnectionString := 'Provider=SQLOLEDB.1;Password=' +

edtPassword.Text + ';Persist Security Info=True;User ID=' + edtUser.Text + ';Initial Catalog=' + edtWebDBName.Text + ';Data Source=' + edtServerName.Text; ADOWeb.Connected := true;

ADOQuery.Connection := ADOWeb;
ADOQuery.SQL.Clear;
ADOQuery.SQL.LoadFromFile(edtScriptFileName.Text);
ADOQuery.ExecSQL;   except
这个方法可以一直运行到脚本文件执行的时候,然后会产生一个异常:在“GO”附近有语法错误。如果我在新创建的数据库上在SMS中运行脚本,就没有问题。这个问题是由于一次运行多个SQL命令引起的吗(该脚本实质上是一长串命令/GO语句)?如何解决?
另外,有没有快速检查新数据库是否存在的想法呢?(或者说这不是必要的,因为如果创建失败,它会生成异常?)

所有这些答案都是可行的。我认为对于SMS生成的脚本,运行sqlcmd是正确的方法。此外,我使用以下代码来获取数据库计数。ADOQuery.SQL.Text:='SELECT COUNT(*) FROM sys.databases WHERE name='+chr(39)+edtWebDBName.Text+chr(39); ADOQuery.Open; 如果ADOQuery.Fields [0] .AsInteger = 0,则不存在数据库。 - Rob
3个回答

10

Rob,ADO不承认GO语句,因此在执行脚本之前必须将其删除。

现在要检查数据库是否存在,您可以执行像这样的查询

select COUNT(*) from sys.databases where name='yourdatabasename'

请检查这个非常基础的示例

假设你有一个如下的脚本

CREATE TABLE Dummy.[dbo].tblUsers(ID INT, UserName VARCHAR(50))
GO
INSERT INTO Dummy.[dbo].tblUsers (ID, UserName) VALUES (1, 'Jill')
GO
INSERT INTO Dummy.[dbo].tblUsers (ID, UserName) VALUES (2, 'John')
GO
INSERT INTO Dummy.[dbo].tblUsers (ID, UserName) VALUES (3, 'Jack')
GO

现在要执行这个语句,你可以像这样做

const
//in this case the script is inside of a const string but can be loaded from a file as well
Script=
'CREATE TABLE Dummy.[dbo].tblUsers(ID INT, UserName VARCHAR(50)) '+#13#10+
'GO '+#13#10+
'INSERT INTO Dummy.[dbo].tblUsers (ID, UserName) VALUES (1, ''Jill'') '+#13#10+
'GO '+#13#10+
'INSERT INTO Dummy.[dbo].tblUsers (ID, UserName) VALUES (2, ''John'') '+#13#10+
'GO '+#13#10+
'INSERT INTO Dummy.[dbo].tblUsers (ID, UserName) VALUES (3, ''Jack'') '+#13#10+
'GO ';

var
  DatabaseExist : Boolean;
  i             : Integer;
begin
  try
    //check the connection
     if not ADOConnection1.Connected then
      ADOConnection1.Connected:=True;
      //make the query to check if the database called Dummy exist  
      ADOQuery1.SQL.Add(Format('select COUNT(*) from sys.databases where name=%s',[QuotedStr('Dummy')]));
      ADOQuery1.Open;
      try
       //get the returned value, if is greater than 0 then exist 
       DatabaseExist:=ADOQuery1.Fields[0].AsInteger>0;
      finally
       ADOQuery1.Close;
      end;


      if not DatabaseExist then
      begin
       //create the database if not exist
       ADOQuery1.SQL.Text:=Format('Create Database %s',['Dummy']);
       ADOQuery1.ExecSQL;
       ADOQuery1.Close;

       //load the script, remember can be load from a file too  
       ADOQuery1.SQL.Text:=Script;
       //parse the script to remove the GO statements
        for i := ADOQuery1.SQL.Count-1 downto 0 do
          if StartsText('GO',ADOQuery1.SQL[i]) then
           ADOQuery1.SQL.Delete(i);
       //execute the script
       ADOQuery1.ExecSQL;
       ADOQuery1.Close;
      end;
  except
      on E:Exception do
        ShowMessage(E.Message);
  end;

end;

为什么这里是-1?有任何合理的原因吗? - user532231
@daemon_x,别担心;)我已经习惯了匿名的踩票者,对我没有影响了。 - RRUZ

4
那个GO仅对某些微软实用程序意味着批处理的结束,它不是一个合适的T-SQL语句。尝试删除脚本中每个GO的出现,然后执行它。那个GO将在脚本末尾为您执行ADOQuery.ExecSQL
至于您的第二个问题; 您可以使用例如SQL函数DB_ID来检查您的数据库是否存在(当然您必须在同一服务器上)。此函数返回数据库ID; 否则为NULL,因此如果以下SQL语句返回NULL,则说明您的数据库创建失败。
ADOQuery.SQL.Text := 'SELECT DB_ID(' + edtWebDBName.Text + ')';
ADOQuery.Open;

if ADO_Query.Fields[0].IsNull then
  ShowMessage('Database creation failed');

1

脚本可能包含的不仅仅是SQL DDL/DML命令。它们可以包含变量、小代码块、事务管理语句等。通常有多个语句,由终止符(分号、Oracle斜杠、MSSQL GO等,取决于您使用的数据库及其脚本语法)分隔。要正确执行脚本,您必须解析输入文件,分离每个命令,并将其正确地提供给数据库。您可以寻找库来完成这项工作(有一些库可用,如果我没记错的话),或者尝试使用MS SQL命令行工具通过它来提供脚本。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接