使用Firebird.NET 2.5执行SQL脚本时出现问题(错误代码= -104)

时间:2010-07-20 18:38:27

标签: sql firebird fbconnect interbase

首先抱歉我的英语。我有问题,需要帮助。 我有一个由c#自己制作的简单工具。此工具可连接到本地或远程firebird服务器(v.2.5)。我的工具可以在服务器上的某个地方创建指定的.fdb文件(数据库)。

我还有一个带有SQL语句的文件(创建表,触发器等)。我想在创建数据库后执行此文件。执行此文件将填充用户数据库的结构 - 而不是数据,只有结构。

然后我尝试执行我的SQL脚本 - firebird服务器返回

  

SQL错误代码= -104令牌未知行xxx列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文件。

2 个答案:

答案 0 :(得分:4)

正如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“绑定”到事务中。

我尝试的第一件事是(无效

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对象处于挂起的本地事务中时,Execute要求Command对象具有Transaction对象.Command的Transaction属性尚未初始化。”< / p>

这意味着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似乎没有效果。

如果您发现以这种方式分配本地交易的任何潜在问题,或者它是否有任何好处或者可以省略,我想要一些反馈。

答案 1 :(得分:1)

在一个批处理中启动两个create语句可能会出错。如果你将它分解为单独的查询,它会工作吗?它在您的SQL工具中有效吗?