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

标签 sql firebird interbase

首先抱歉我的英语。我有问题需要帮助。 我自己用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/

相关文章:

php - SQL JOIN 返回 3 个名称为 'id' 的字段

sql - 使用 SQL Server 删除零

mysql - 在一个查询行中创建多个数据库

sql - Firebird SQL 连接表

sql - 如何使用 JOIN 而不是 SELECT NOT IN?

java - 当我尝试将对象添加到 ArrayList 时,它添加了哈希码,不知道如何解决。初学者

PHP : connecting to a Firebird (Interbase) database with Zend

sql - 按多列分组和聚合

sql - 如何限制为Interbase 7.1返回的记录数?

php firebird/interbase 外部数据库连接