我有一个小问题,我找不到答案。我需要从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语句,因为我正在尝试在多个数据库上执行脚本。
答案 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,因为您可以加载到备忘录中(尽管您可能更喜欢保持两个用途分开)。