使用Delphi创建/更改程序

时间:2016-02-17 11:06:51

标签: sql-server delphi stored-procedures

我有一个小问题,我找不到答案。我需要从Delphi创建/修改一些程序。

所以这是我的代码,它从文件中获取代码并尝试执行它。

procedure TfrmMainApp.actRulezaScriptExecute(Sender: TObject);
var
  j: Int32;
  sql: string;
  commandFile: TextFile;
  Linie: string;
  affRows: Int32;
  err: string;
begin

  for j := 0 to filesToExecute.Count - 1 do
  begin
    sql := 'USE ' + DBName + #10#13;
    sql := sql + '  GO ' + #10#13;
    AssignFile(commandFile, filesToExecute[j]);
    Reset(commandFile);
    while not EOF(commandFile) do
    begin
      Readln(commandFile, Linie);
      sql := sql + #10#13 + Linie;
    end;
    dmMainScriptRun.ExecuteCommand(sql, err, affRows);
    if err <> '' then
      break;
    Memo1.Lines.Add('Affected rows:' + IntToStr(affRows));
  end;

end;


function TdmMainScriptRun.ExecuteCommand(sqlCommand: string; var err: string;
  var affRows: Int32): Boolean;
begin
  err := '';
  try
    with cmd do
    begin
      CommandText := sqlCommand;
      Execute(affRows, EmptyParam);
    end;
  except
    on E: Exception do
    begin
      err := E.Message;
    end;
  end;
end;

所以我的文件看起来像这样

CREATE PROCEDURE sp_TestSebi
AS

    print ('testSebi')

我的命令看起来像这样(它是从SQL Server Profiler中获取的)

USE Test

  GO 


CREATE PROCEDURE sp_TestSebi

AS


    print ('testSebi')

执行此命令会返回运行脚本的错误Incorrect syntax near 'GO',而不会因为USE子句而使GO语句返回错误CREATE/ALTER PROCEDURE' must be the first statement in a query batch

有没有办法从Delphi创建程序?我需要use语句,因为我正在尝试在多个数据库上执行脚本。

2 个答案:

答案 0 :(得分:1)

您可以每次删除连接并在参数中指定USE。事实上,如果你聪明,你可以为每个数据库建立一个连接并并行化整个事物。

答案 1 :(得分:1)

您尝试此操作的方式可以通过多种方式进行改进。

首先,试试这个:

  • 创建新的VCL项目

  • 在表单上删除TAdoConnection和TAdoQuery。还要将TButton放在上面。

  • 将TAdoQuery连接到TAdoConnection。

  • 设置TAdoConnection以连接到您的Sql Server

  • 在下面的代码中,修改scUse常量以引用目标数据库 和scCreateView引用数据库中不存在的视图一个有效的表。这是为了确保创建视图不会因视图已存在或表不存在而失败。

运行代码,您会收到一条投诉,称创建视图引用了无效的对象名称,因为当创建视图执行时,AdoConnection未连接到目标数据库。

然后将KeepConnection更改为True并重新测试。这次应该成功创建视图。

const
  scUse ='use m4common';
  scCreateView = 'create view vwtest as select * from btnames';

procedure TForm1.Button1Click(Sender: TObject);
begin
  AdoConnection1.DefaultDatabase := 'Master';
  // The point of changing the default database in the line above
  // is to ensure for demo purposes that the 'Use' statement 
  //  is necessary to change to the correct db.

  AdoConnection1.KeepConnection := False;  // retest with this set to True
  AdoQuery1.SQL.Text := scUse;
  AdoQuery1.ExecSQL;

  AdoQuery1.SQL.Text := scCreateView;
  AdoQuery1.ExecSQL;
end;

因此,KeepConnection的要点是允许您在同一连接上下文中执行两个或多个Sql批处理,并使服务器满足Create View语句(或类似)可以作为批处理中的第一个语句,并且同时,创建视图所适用的数据库与您同时使用的数据库&#34; USEd&#34;在上一批中。

其次,你的AssignFile ......而不是Eof是不必要的冗长和容易出错。尝试这样的事情:

var
  TL : TStringList;
begin
  TL := TStringList.Create;
  try
    for j := 0 to filesToExecute.Count - 1 do
    begin
      sql := 'USE ' + DBName + #13#10;
      sql := sql + '  GO ' + #13#10;
      TL.BeginUpdate;  // for better performance with longer scripts
      TL.LoadFromFile(filesToExecute[j]);
      TL.Insert(0, sql);
      TL.EndUpdate;  
      // execute the Sql here etc
    end;
  finally
    TL.Free;
  end;
end;

请注意,我已经颠倒了#10和#13的顺序,以便它是正确的。

另一点是,由于Memo的Lines属性已经有了LoadFromFile方法,因此您不需要我的临时TStringList,TL,因为您可以加载到备忘录中(尽管您可能更喜欢保持两个用途分开)。