2011-05-12 61 views
6

我想要做以下事情。 1)创建一个数据库。 2)时创建表,存储程序等运行脚本(该脚本由SMS产生“生成脚本”选项)如何从Delphi运行数据库脚本文件?

我发现以下代码:http://www.delphipages.com/forum/showthread.php?t=181685 并将其修改成这样:

尝试

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

edtPassword.Text + ';持续安全信息= TRUE;用户ID =' + edtUser.Text + ';初始目录=主人;数据源=' + edtSe​​rverName.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 + ';持续安全信息= TRUE;用户ID =' + edtUser.Text + ';初始目录=' + edtWebDBName.Text + ';数据源=' + edtSe​​rverName 。文本; ADOWeb.Connected:= true;

ADOQuery.Connection := ADOWeb; 
ADOQuery.SQL.Clear; 
ADOQuery.SQL.LoadFromFile(edtScriptFileName.Text); 
ADOQuery.ExecSQL; except 

这工作,直到运行脚本文件的点。然后它会产生一个异常:“GO”附近的语法错误。如果我在新创建的数据库上运行SMS中的脚本,那很好。这个问题是由于一次运行多个SQL命令(脚本本质上是一长串命令/ GO语句?如何解决它?)

哦,作为奖励,任何关于快速检查的想法在发送脚本之前查看新数据库是否真实存在?(或者是否不必要,因为如果创建失败,它将生成异常?)

+0

所有这些答案都可以使用。我认为对于SMS生成的脚本,运行sqlcmd是一种方法。此外,我用下面的数据来获得数据。 (39)+ edtWebDBName.Text + chr(39);其中,数据库的名称是数据库的名称。 ADOQuery.Open; if ADOQuery.Fields [0] .AsInteger = 0 then // DB不存在 – Rob 2011-05-13 15:28:58

回答

10

Rob GO语句不被ADO识别,所以您必须在执行前从您的脚本中删除。

我们检查数据库是否存在,您可以执行这样

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; 
+0

为什么在这里?任何明智的理由呢? – 2011-05-14 14:07:55

+0

@daemon_x,别担心;),我习惯了匿名的选民,不再影响我。 – RRUZ 2011-05-14 14:47:51

4

GO表示仅针对特定Microsoft实用程序的批处理结束不是正确的T-SQL语句,请尝试删除脚本中的每个发生的GO然后执行它GO将在脚本结尾为您执行ADOQuery.ExecSQL

对于你的第二个问题;你可以使用例如SQL函数DB_ID来检查你的DB是否存在(当然你必须在同一个服务器上)。该函数返回数据库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等分开,取决于您使用的数据库及其脚本语法)。要正确执行脚本,您必须解析输入文件,分隔每个命令,并将其正确提供给数据库。你可以寻找库来做到这一点(有一些,IIRC),或者你可以尝试使用MS SQL命令行工具通过它来提供脚本。