无法通过C#在firebird中运行多个插入记录查询

时间:2013-04-11 04:15:00

标签: c# database firebird

我在C#中生成多个插入记录查询并尝试在FireBird中执行。

当我在FlameRobin上运行它时效果很好。但是当我通过C#运行它时会抛出异常。

SET TERM ^ ; INSERT INTO COUNTRY1 SELECT '2', 'two ' FROM RDB$DATABASE UNION ALL SELECT '4', 'four' FROM RDB$DATABASE UNION ALL SELECT '5', 'five' FROM RDB$DATABASE; ^ SET TERM ; ^ 

C#代码中的异常是

  

{“动态SQL错误\ r \ nSQL错误代码= -104 \ r \ n未知 - 第1行,第5行\ n \ r \ nTERM”}

C#代码是

string sQuery = "SET TERM ^ ; INSERT INTO COUNTRY1 SELECT '2', 'two ' FROM RDB$DATABASE UNION ALL SELECT '4', 'four' FROM RDB$DATABASE UNION ALL SELECT '5', 'five' FROM RDB$DATABASE; ^ SET TERM ; ^ ";
SqlHelper.ExecuteNonQuery(SQLHelp.Connectionstring, CommandType.Text, sQuery);

我在这里做错了什么? 感谢

2 个答案:

答案 0 :(得分:2)

您所包含的set term语句不是Firebird SQL语言的一部分,而是首先在 isql 中引入的解释器配置指令,其中是Firebird的命令行客户端。

以这种方式查看你的脚本:

SET TERM ^ ; 

INSERT INTO COUNTRY1 
  SELECT '2', 'two ' FROM RDB$DATABASE 
  UNION ALL SELECT '4', 'four' FROM RDB$DATABASE 
  UNION ALL SELECT '5', 'five' FROM RDB$DATABASE; ^ 

SET TERM ; ^

引擎不知道也无法处理set term语句。

FlameRobin和其他客户端为set term语句添加了对兼容性的支持:允许运行为isql编写的SQL脚本,或者因为它们缺少完整的SQL解析器,并且仍然需要正确识别脚本在脚本结束时的位置包括分号。但是所有这些客户端,一旦语句在脚本中分隔,就不会将set term发送到引擎,只是忽略它。

您必须这样做:删除set term语句并发送您拥有的唯一其他语句,如下所示:

INSERT INTO COUNTRY1 
  SELECT '2', 'two ' FROM RDB$DATABASE 
  UNION ALL SELECT '4', 'four' FROM RDB$DATABASE 
  UNION ALL SELECT '5', 'five' FROM RDB$DATABASE

请注意,您还必须删除;

答案 1 :(得分:1)

您的查询不符合Firebird语法。驱动程序一次只能执行一个语句(请注意EXECUTE BLOCK被认为是单个语句)。 您不应该使用SET TERM,这是ISQL工具(以及其他一些查询工具,如FlameRobin)的工件,并且实际上不是Firebird SQL语言的一部分。

您也不应在查询中包含;。这些仅在1)PSQL(存储过程,触发器和内部EXECUTE BLOCK)和2)中再次在ISQL等工具中用于分隔(结束)语句。

因此,使用以下查询就足够了:

INSERT INTO COUNTRY1 SELECT '2', 'two ' FROM RDB$DATABASE UNION ALL SELECT '4', 'four' FROM RDB$DATABASE UNION ALL SELECT '5', 'five' FROM RDB$DATABASE

修改

正如我评论的那样,当与UNION结合使用时,解析器可能无法理解INSERT ... SELECT

使用子选择可能会起作用:

INSERT INTO COUNTRY1 
  SELECT column1, column2 FROM (
     SELECT '2' AS column1, 'two ' AS column2 FROM RDB$DATABASE 
     UNION ALL SELECT '4', 'four' FROM RDB$DATABASE 
     UNION ALL SELECT '5', 'five' FROM RDB$DATABASE
  )

编辑2

我刚刚使用下面的代码测试它并且它可以工作:插入预期的行:

static void Main(string[] args)
{
    var constrBuilder = new FbConnectionStringBuilder();
    constrBuilder.DataSource = "localhost";
    constrBuilder.Database = @"D:\data\db\testdatabase.fdb";
    constrBuilder.UserID = "sysdba";
    constrBuilder.Password = "masterkey";

    string constr = constrBuilder.ToString();

    using (var con = new FbConnection(constr))
    {
        con.Open();
        using (var trans = con.BeginTransaction())
        {
            var cmd = new FbCommand();
            cmd.CommandText = "INSERT INTO COUNTRY1 SELECT '2', 'two ' FROM RDB$DATABASE UNION ALL SELECT '4', 'four' FROM RDB$DATABASE UNION ALL SELECT '5', 'five' FROM RDB$DATABASE";
            cmd.Connection = con;
            cmd.Transaction = trans;

            cmd.ExecuteNonQuery();
            trans.Commit();
        }
    }
}