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

时间:2017-03-25 18:31:41

标签: c# ado.net firebird firebird-embedded

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. / p>

CREATE GENERATOR ...;
SET GENERATOR ...;

set term !! ;
CREATE TRIGGER ...
Visual Studio编译器无法识别

2 个答案:

答案 0 :(得分:2)

重要的是SET TERM 是Firebird语句语法的一部分,而是在ISQL等查询工具中设置语句终止符的客户端功能。此终结器必须知道语句何时完成并可以发送到服务器。默认情况下,这些工具在分号(;)上执行此操作,但这不适用于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 ;#
    
  3. 当您在表中插入值并希望生成密钥时,应在列列表中包含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)。它还显示了如何检索生成的密钥:

    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
        }
    }
    

答案 1 :(得分:0)

说明:

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<string> liststTableNames, 
                                           List<string> 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<string> 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
//------------------------------