如何在 Delphi 中执行包含许多 GO 语句的大型 SQL 脚本? [关闭]

Posted

技术标签:

【中文标题】如何在 Delphi 中执行包含许多 GO 语句的大型 SQL 脚本? [关闭]【英文标题】:How do I execute a large SQL Script with many GO statements from within Delphi? [closed] 【发布时间】:2013-08-08 00:45:21 【问题描述】:

我们有一个更新程序应用程序,它在 SQL Server 数据库上执行超过 30,000 行代码的 SQL 脚本。在这个脚本中有大量的GO 语句。我习惯使用的 ADO 组件不支持GO 语句。我们在更新服务器时总是使用OSQL 命令行,这很难发现问题(输出一个文本文件,然后我们必须对其进行解析以查找错误和结果)。如果 Delphi 中的某些东西能够找到那些 GO 语句并一次执行每个块,那将更加理想。

我明白GO 语句是特定于能够执行它们的MS 工具。同样,该脚本有超过 30,000 行代码,至少有 500 条 GO 语句。我们在 SQL Management Studio 和 OSQL 中为更新程序使用相同的脚本。但是 OSQL 并没有为我们提供我们需要的结果 - 它是执行此类脚本的一种草率方式。

是否有任何现有的用于 Delphi 的 SQL Server 兼容工具可以识别GO 语句?我不是在谈论解析器(尽管我确信会涉及解析),我在谈论一个现成的实用程序来执行包含GO 语句的 SQL 脚本并返回每个脚本块的结果。

例如,一个块可能会创建一个表,然后是GO,然后为该表和另一个GO 创建一个存储过程。代码是如此复杂,以至于在this question 这样的代码中实现它是完全不可能的。

更新

我已经成功编写了一小段工作代码来执行此操作,但是它没有考虑注释块中的GO 语句。

Code found here

我没有在这个问题上进一步询问,只是想我会分享我在哪里。

【问题讨论】:

简单地查找字符串GO 也行不通,因为其中可能有一个字符串正在插入/更新一些带有单词“go”的文本 答案,我不知道,但我建议将整个脚本放入一个存储过程中并稍作修改,以便将每个操作的结果写入一组专用临时表每次运行时都会重写,这样脚本的结果就可以通过对这些临时表的特定查询来识别。我在数据仓库工作的日子教会了我临时表在冗长而复杂的数据库操作中的价值,尤其是当 DBMS 本身进行大量处理时。只是一个建议。 HTH。 所以答案是由我来决定如何执行 SQL 脚本。甜的!现在我可以为此编写自己的组件了。 更糟糕的是,GO 本身并不持久。你可以例如configure your own batch terminator 在 Management Studio 中,因此您可以使用 GOJOHNNYGO 分隔符生成脚本,例如 How to run a database script file from Delphi?的可能重复 【参考方案1】:

将脚本加载到TStringList 中会起作用。在一行中单独查找单词GO(这避免了包含GO 的嵌入文本)作为每个块或脚本本身的结尾。

您使用GO 行的索引 - 1 标记前一个块的结束,并使用GO 行索引 + 1 作为下一个块的开始。如果GO 索引等于StringList.Count - 1,那么您已经到达脚本的结尾。您可以在处理块之前启动事务,并在引发异常时回滚该事务。

【讨论】:

希望 GO 自己在一条线上……但同一条线上只允许使用 cmets(参见 msdn.microsoft.com/en-us/library/ms188037.aspx)。您还必须在 /* 块注释 */ 中处理 GO @Gerry:两个优点。第一个可以通过查看GO; 的前三个字符来处理。第二个可以用 InComment 布尔标志处理。我从来没有说过你不必做一些工作,无论是设置脚本还是处理它的代码。 IMO,它仍然是最好的解决方案,因为我发现没有一个“开箱即用”可以正确地做事。【参考方案2】:

这其实是个好问题,没有简单的答案。

值得强调的是,这是 Microsoft 的问题,不是 SQL,也不是 Delphi。

这已经在 SO 上讨论过很多次,但没有“一刀切”的答案:

How to run a database script file from Delphi?

How to execute a SQL script using dbExpress?

Conflict between Delphi and SQL server

How to run a database script file from Delphi?

我的两个主要建议:

读取脚本文件,一次解析一行,并在每行只包含“go”的行之后运行“execute”

使用您的脚本和登录参数执行 SqlCmd.exe 的 ShellExecute()(或等效项)。

【讨论】:

以上是关于如何在 Delphi 中执行包含许多 GO 语句的大型 SQL 脚本? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

delphi程序在使用adoquery执行SQL语句的时候,如何判断SQL语句全部已经执行完成

GO学习笔记 - 用defer来实现try{}finally{}

Go 循环语句

delphi中如何使用SQL语句结果

从 Delphi 异步访问 MySQL 数据库

delphi中的SQL语句