INSERT INTO Firebird 如何使用主键的自动增量?
How do INSERT INTO Firebird, with autoincrement for the primary key?
如何 INSERT INTO Firebird,主键自增?
对于 table 个字段,我有:
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。这个终止符对于知道语句何时完成并可以发送到服务器是必需的。默认情况下,这些工具在分号 (;
) 上执行此操作,但这不适用于 PSQL(存储过程、触发器),因为 PSQL 代码也使用分号。为了解决这个问题,这些工具有 SET TERM
来切换这个终止符。
然而,使用 Firebird ADO.net 提供程序,您需要一次执行一条语句,因此语句终止符无关紧要。
为了能够生成主键,您可以使用以下解决方案:
Firebird 3 有一个身份类型列,所以你不需要创建一个序列并自己触发:
create table withgeneratedid(
id integer generated by default as identity primary key,
column2 varchar(100)
)
对于 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 ;#
当您将值插入 table 并希望生成一个键时,您应该不在列列表中包含 id 列。包括 id 列允许您覆盖键值,但这可能会导致将来的插入生成重复的键!。如果确实包含 id 列,则在 Firebird 3 示例中不会生成任何键,在 Firebird 2.5 示例中,如果该列的值为 null
,则会生成一个键,否则它将采用提供的值.
在 ADO.net 中,您通常需要单独执行语句(而不是使用 set term
)。或者,您可以使用 FbScript
来解析 DDL 脚本并执行解析语句。请注意 FbScript
确实支持(甚至需要)set term
.
要使用 Firebird ADO.net 提供程序执行此操作,您可以执行类似于下面示例的操作。我已经包含了三个用于创建 table、Firebird3
、Firebird2_5
和 FbScriptFB2_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
}
}
定义:
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
//------------------------------
如何 INSERT INTO Firebird,主键自增?
对于 table 个字段,我有:
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。这个终止符对于知道语句何时完成并可以发送到服务器是必需的。默认情况下,这些工具在分号 (;
) 上执行此操作,但这不适用于 PSQL(存储过程、触发器),因为 PSQL 代码也使用分号。为了解决这个问题,这些工具有 SET TERM
来切换这个终止符。
然而,使用 Firebird ADO.net 提供程序,您需要一次执行一条语句,因此语句终止符无关紧要。
为了能够生成主键,您可以使用以下解决方案:
Firebird 3 有一个身份类型列,所以你不需要创建一个序列并自己触发:
create table withgeneratedid( id integer generated by default as identity primary key, column2 varchar(100) )
对于 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 ;#
当您将值插入 table 并希望生成一个键时,您应该不在列列表中包含 id 列。包括 id 列允许您覆盖键值,但这可能会导致将来的插入生成重复的键!。如果确实包含 id 列,则在 Firebird 3 示例中不会生成任何键,在 Firebird 2.5 示例中,如果该列的值为 null
,则会生成一个键,否则它将采用提供的值.
在 ADO.net 中,您通常需要单独执行语句(而不是使用 set term
)。或者,您可以使用 FbScript
来解析 DDL 脚本并执行解析语句。请注意 FbScript
确实支持(甚至需要)set term
.
要使用 Firebird ADO.net 提供程序执行此操作,您可以执行类似于下面示例的操作。我已经包含了三个用于创建 table、Firebird3
、Firebird2_5
和 FbScriptFB2_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
}
}
定义:
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
//------------------------------