首先抱歉我的英语。我有问题需要帮助。 我自己用c#制作了一个简单的工具。该工具可以连接到本地或远程 firebird 服务器(v.2.5)。我的工具可以在服务器上的某个位置创建指定的 .fdb 文件(数据库)。
我还有一个包含 SQL 语句(创建表、触发器等)的文件。我想在创建数据库后执行这个文件。执行此文件将填充用户数据库的结构 - 不是数据,只有结构。
但是后来我尝试执行我的 SQL 脚本 - firebird 服务器返回
SQL error code = -104 Token unknown line xxx column xxx.
这是此 CREATE TABLE
SQL 语句中的行,例如:
CREATE TABLE tb1
(
col1 INTEGER NOT NULL,
col2 VARCHAR(36)
);
/* This next create statement causes an error */
CREATE TABLE tb2
(
col1 INTEGER NOT NULL,
col2 VARCHAR(36)
);
如果我在文件中只留下一个创建语句 - 一切都会好的...我不知道我是如何解释的(是否清楚)) - 换句话说 - 为什么我不能执行完整的查询在一个事务中许多 create 语句?我的主要方法是执行查询:
public static string Do(string conString, string query)
{
using (FbConnection conn = new FbConnection())
{
try
{
conn.ConnectionString = conString;
conn.Open();
FbTransaction trans = conn.BeginTransaction();
FbCommand cmd = new FbCommand(query, conn, trans);
cmd.ExecuteNonQuery();
trans.Commit();
}
catch (Exception ex)
{
System.Windows.MessageBox.Show(ex.ToString());
return "Transaction Fail";
}
}
return "Transaction Commited";
}
有一个查询是我的 SQL 文件。
最佳答案
正如 Victor 在他的最后评论中所述,您可以使用 FBScript 类进行批量执行。
我刚刚面临同样的任务。这个问题为我指明了正确的方向,但我必须做一些进一步的挖掘。
在这个例子中,语句的来源是一个外部脚本文件:
private void ExecuteScript(FbConnection myConnection, string scriptPath) {
if (!File.Exists(scriptPath))
throw new FileNotFoundException("Script not found", scriptPath);
FileInfo file = new FileInfo(scriptPath);
string script = file.OpenText().ReadToEnd();
// use FbScript to parse all statements
FbScript fbs = new FbScript(script);
fbs.Parse();
// execute all statements
FbBatchExecution fbe = new FbBatchExecution(myConnection, fbs);
fbe.Execute(true);
}
这会工作得很好,但你可能想知道为什么这整个事情没有被事务包围。实际上,不支持将 FbBatchExecution 直接“绑定(bind)”到事务。
我尝试的第一件事就是这个(行不通)
private void ExecuteScript(FbConnection myConnection, string scriptPath) {
using (FbTransaction myTransaction = myConnection.BeginTransaction()) {
if (!File.Exists(scriptPath))
throw new FileNotFoundException("Script not found", scriptPath);
FileInfo file = new FileInfo(scriptPath);
string script = file.OpenText().ReadToEnd();
// use FbScript to parse all statements
FbScript fbs = new FbScript(script);
fbs.Parse();
// execute all statements
FbBatchExecution fbe = new FbBatchExecution(myConnection, fbs);
fbe.Execute(true);
myTransaction.Commit();
}
}
这将导致异常:“当分配给命令的 Connection 对象处于挂起的本地事务中时,执行要求 Command 对象具有 Transaction 对象。Command 的 Transaction 属性尚未初始化。”
这仅意味着 FbBatchExecution 执行的命令未分配给代码块周围的本地事务。这里有帮助的是 FbBatchExecution 提供 CommandExecuting 事件我们可以拦截每个命令并像这样分配我们的本地事务:
private void ExecuteScript(FbConnection myConnection, string scriptPath) {
using (FbTransaction myTransaction = myConnection.BeginTransaction()) {
if (!File.Exists(scriptPath))
throw new FileNotFoundException("Script not found", scriptPath);
FileInfo file = new FileInfo(scriptPath);
string script = file.OpenText().ReadToEnd();
// use FbScript to parse all statements
FbScript fbs = new FbScript(script);
fbs.Parse();
// execute all statements
FbBatchExecution fbe = new FbBatchExecution(myConnection, fbs);
fbe.CommandExecuting += delegate(object sender, CommandExecutingEventArgs args) {
args.SqlCommand.Transaction = myTransaction;
};
fbe.Execute(true);
// myTransaction.Commit();
}
}
请注意,我已取消注释 myTransaction.Commit() 行。我对这种行为感到有点惊讶,但如果保留该行,事务将抛出一个异常,表明它已经被提交。 bool 参数 fbe.Execute(true) 名为“autoCommit”,但将其更改为 false 似乎没有效果。
如果您发现以这种方式分配本地事务有任何潜在问题,或者它有任何好处或可以省略,我希望得到一些反馈。
关于sql - 使用 Firebird.NET 2.5 执行 SQL 脚本时出现问题(错误代码 = -104),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3293197/