INSERT INTO Firebird如何自动增加主键?

INSERT INTO Firebird如何自动增加主键?

对于我有的表格字段:

fstPriority VARCHAR(30), fstInfo VARCHAR(100), fstDateCreated VARCHAR(30), fstDateModified VARCHAR(30), fiKeyID INTEGER PRIMARY KEY 

INSERT INTO我有:

 FbConnection fbConn = new FbConnection(stOpenConn)) fbConn.Open(); ... FbTransaction fbTransaction = fbConn.BeginTransaction(); FbCommand fbCmd = new FbCommand("INSERT INTO " + stTableName + "(" + stFieldNames + ") VALUES ( @p0, @p1, @p2, @p3, @p4 ) RETURNING fiKeyID ", fbConn, fbTransaction); 

但我不确定fbCmd.Parameters.AddWithValue应该使用什么

 fbCmd.Parameters.AddWithValue("@p0", "1st value"); fbCmd.Parameters.AddWithValue("@p1", "2nd value"); fbCmd.Parameters.AddWithValue("@p2", "3rd value"); fbCmd.Parameters.AddWithValue("@p3", "4th value"); 

那又怎样? 对于fiKeyID,我要添加吗?

 fbCmd.Parameters.AddWithValue("@p4", ""); 

另外,我在http://www.firebirdfaq.org/faq29/上看到创建一个自动增量列,但我不确定如何在C#中执行此操作… Firebird ADO.NET … FirebirdClient.5.8.0 … Visual Studio 2013。

 CREATE GENERATOR ...; SET GENERATOR ...; set term !! ; CREATE TRIGGER ... 

Visual Studio编译器无法识别。

重要的是SET TERM 不是 Firebird语句语法的一部分,而是在ISQL等查询工具中设置语句终止符的客户端function。 此终结器必须知道语句何时完成并可以发送到服务器。 默认情况下,这些工具在分号( ; )上执行此操作,但这不适用于PSQL(存储过程,触发器),因为PSQL代码也使用分号。 为解决此问题,这些工具具有SET TERM来切换此终结器。

但是,使用Firebird ADO.net提供程序,您需要一次执行一个语句,因此语句终止符是无关紧要的。

为了能够生成主键,您可以使用以下解决方案:

  1. Firebird 3具有标识类型列,因此您无需创建序列并自行触发:

     create table withgeneratedid( id integer generated by default as identity primary key, column2 varchar(100) ) 
  2. 对于Firebird 2.5及更早版本,您需要创建一个序列并触发:

     create table withgeneratedid( id integer primary key, column2 varchar(100) ); create sequence seq_withgeneratedid; set term #; create trigger withgeneratedid_bi before insert on withgeneratedid as begin if (new.id is null) then new.id = next value for seq_withgeneratedid; end# set term ;# 

将值插入表并希望生成密钥时,不应在列列表中包含id列。 包括id列允许您覆盖键值,但这可能导致将来插入生成重复键! 如果确实包含id列,则Firebird 3示例中不会生成任何密钥,在Firebird 2.5示例中,如果列的值为null ,则将生成密钥,否则将采用提供的值。

在ADO.net中,您通常需要单独执行语句(而不是使用set term )。 或者,您可以使用FbScript来解析DDL脚本并执行解析语句。 请注意, FbScript确实支持(甚至需要) set term

要使用Firebird ADO.net提供程序执行此操作,您可以执行类似下面的示例。 我已经包含了三个用于创建表Firebird3Firebird2_5FbScriptFB2_5 (与Firebird2_5相同但使用FbScript )的FbScript 。 它还显示了如何检索生成的密钥:

 namespace FbGeneratedKeys { class Program { private static SolutionType solutionType = SolutionType.FbScriptFB2_5; static void Main(string[] args) { var connectionString = new FbConnectionStringBuilder { Database = @"D:\temp\generatedkey.fdb", ServerType = FbServerType.Default, UserID = "SYSDBA", Password = "masterkey", }.ToString(); FbConnection.CreateDatabase(connectionString, pageSize: 8192, overwrite : true); using (FbConnection connection = new FbConnection(connectionString)) using (FbCommand cmd = new FbCommand()) { connection.Open(); cmd.Connection = connection; switch (solutionType) { case SolutionType.Firebird3: Firebird3Example(cmd); break; case SolutionType.Firebird2_5: Firebird2_5Example(cmd); break; case SolutionType.FbScriptFB2_5: FbScriptFB2_5Example(cmd); break; } cmd.CommandText = @"insert into withgeneratedid(column2) values (@column2) returning id"; cmd.Parameters.AddWithValue("@column2", "some value"); cmd.Parameters.Add(new FbParameter() { Direction = System.Data.ParameterDirection.Output }); cmd.ExecuteNonQuery(); Console.WriteLine("Id:" + cmd.Parameters[1].Value); Console.ReadLine(); } } private static void Firebird3Example(FbCommand cmd) { // Firebird 3 identity column cmd.CommandText = @"create table withgeneratedid( id integer generated by default as identity primary key, column2 varchar(100) )"; cmd.ExecuteNonQuery(); } private static void Firebird2_5Example(FbCommand cmd) { // Firebird 2.5 and earlier normal primary key with trigger to generate key // Table cmd.CommandText = @"create table withgeneratedid( id integer primary key, column2 varchar(100) )"; cmd.ExecuteNonQuery(); // Sequence cmd.CommandText = "create sequence seq_withgeneratedid"; cmd.ExecuteNonQuery(); // Trigger cmd.CommandText = @"create trigger withgeneratedid_bi before insert on withgeneratedid as begin if (new.id is null) then new.id = next value for seq_withgeneratedid; end"; cmd.ExecuteNonQuery(); } private static void FbScriptFB2_5Example(FbCommand cmd) { string script = @" create table withgeneratedid( id integer primary key, column2 varchar(100) ); create sequence seq_withgeneratedid; set term #; create trigger withgeneratedid_bi before insert on withgeneratedid as begin if (new.id is null) then new.id = next value for seq_withgeneratedid; end# set term ;# "; FbScript fbScript = new FbScript(script); fbScript.Parse(); FbBatchExecution exec = new FbBatchExecution(cmd.Connection); exec.AppendSqlStatements(fbScript); exec.Execute(); } } enum SolutionType { Firebird3, Firebird2_5, FbScriptFB2_5 } } 

定义:

 public const string stMAIN_TABLE_NAME = " OrgTable "; public const string stDELETED_TABLE_NAME = " BackupTable "; public const string stFIELD_DEFINITIONS = " fstPriority VARCHAR(30)" + ", fstInfo VARCHAR(100)" + ", fstDateCreated VARCHAR(30)" + ", fstDateModified VARCHAR(30)" + ", fiKeyID INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY "; public const string stFIELD_NAMES = " fstPriority" + ", fstInfo" + ", fstDateCreated" + ", fstDateModified" + ", fiKeyID "; public const string stFIELD_NAMES_NO_KEY_ID = " fstPriority" + ", fstInfo" + ", fstDateCreated" + ", fstDateModified "; 

码:

 //------------------------------ static private bool boCreateDatabaseTables(string stPathFilename, string stUserID, string stPassword, List liststTableNames, List liststFieldDefinitions) { bool boErrorFlag = false; int iTablesCount = liststTableNames.Count(); string stOpenConn = new FbConnectionStringBuilder { Database = stPathFilename, UserID = stUserID, Password = stPassword, ServerType = FbServerType.Embedded, ClientLibrary = stCLIENT_LIBRARY }.ToString(); using (FbConnection fbConn = new FbConnection(stOpenConn)) { try { fbConn.Open(); FbTransaction fbTransaction = fbConn.BeginTransaction(); for (int ii = 0; ii < iTablesCount; ii++) { string stSql = "CREATE TABLE " + liststTableNames[ii] + "( " + liststFieldDefinitions[ii] + ")"; FbCommand fbCmd = new FbCommand(stSql, fbConn, fbTransaction); fbCmd.ExecuteNonQuery(); } fbTransaction.Commit(); } catch (Exception ex) { boErrorFlag = true; MessageBox.Show("catch ... GlobalsFirebird ... boCreateDatabaseTables ... " + ex.Message); } } return boErrorFlag; }//boCreateDatabaseTables //------------------------------ //------------------------------ static public bool boAddRow(string stPathFilename, string stUserID, string stPassword, string stTableName, string stFieldNamesNoKeyId, List liststFieldValuesNoKeyId) { bool boErrorFlag = false; string stOpenConn = new FbConnectionStringBuilder { Database = stPathFilename, UserID = stUserID, Password = stPassword, ServerType = FbServerType.Embedded, ClientLibrary = stCLIENT_LIBRARY }.ToString(); using(FbConnection fbConn = new FbConnection(stOpenConn)) { fbConn.Open(); try { string stValuesPlaceHolder = "@p0"; for (int iii = 1; iii < liststFieldValuesNoKeyId.Count; iii++) stValuesPlaceHolder += ", @p" + (iii).ToString(); FbTransaction fbTransaction = fbConn.BeginTransaction(); string stCmd = "INSERT INTO " + stTableName + "(" + stFieldNamesNoKeyId + ") VALUES ( " + stValuesPlaceHolder + " ) RETURNING fiKeyID "; FbCommand fbCmd = new FbCommand(stCmd, fbConn, fbTransaction); for (int iii = 0; iii < liststFieldValuesNoKeyId.Count; iii++) { string stPlaceHolder = "@p" + (iii).ToString(); string stValue = liststFieldValuesNoKeyId[iii]; fbCmd.Parameters.AddWithValue(stPlaceHolder, stValue); } fbCmd.Parameters.Add(new FbParameter() { Direction = System.Data.ParameterDirection.Output }); fbCmd.ExecuteNonQuery(); fbTransaction.Commit(); } catch (Exception ex) { boErrorFlag = true; MessageBox.Show("catch ... GlobalsFirebird ... boAddRow ... " + ex.Message); } } return boErrorFlag; }//boAddRow //------------------------------