为什么 ExecuteNonQuery 捕获异常 {"validation error for column \"ORGTABLE\".\"FIKEYID\", value \"* null *\""}
Why the ExecuteNonQuery catch exception {"validation error for column \"ORGTABLE\".\"FIKEYID\", value \"* null *\""}
为什么 ExecuteNonQuery 捕获异常 {"validation error for column \"ORGTABLE\".\"FIKEYID\",值 \"* null *\""}
string stValuesPlaceHolder = "@p0";
for (int iii = 1; iii < liststFieldValuesNoKeyId.Count; iii++)
stValuesPlaceHolder += ", @p" + (iii).ToString();
FbTransaction fbTransaction = fbConn.BeginTransaction();
FbCommand fbCmd = new FbCommand("INSERT INTO " + stTableName + "(" + stFieldNamesNoKeyId + ") VALUES ( " + stValuesPlaceHolder + " )", 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.ExecuteNonQuery();
fbTransaction.Commit();
stTableName 是 OrgTable。
字段名称是:
fstPriority, fstInfo, fstDateCreated, fstDateModified, fiKeyID.
字段定义为:
fstPriority VARCHAR(30), fstInfo VARCHAR(100), fstDateCreated VARCHAR(30), fstDateModified VARCHAR(30), fiKeyID INTEGER PRIMARY KEY
这段代码中:
stFieldNamesNoKeyId = "fstPriority, fstInfo, fstDateCreated, fstDateModified".
stValuesPlaceHolder = "@p0, @p1, @p2, @p3"
四个
fbCmd.Parameters.AddWithValue:
stPlaceHolder = "@p0" ... stValue = "1st value";
stPlaceHolder = "@p1" ... stValue = "2nd value";
stPlaceHolder = "@p2" ... stValue = "3rd value";
stPlaceHolder = "@p3" ... stValue = "4th value";
我没有为 fiKeyID 添加值,因为它是主键。
I did not add a value for fiKeyID as it as the PRIMARY KEY.
因此您尝试插入一个 NULL 主键。这是不允许的。
http://www.firebirdsql.org/manual/nullguide-keys.html
NULLs are never allowed in primary keys. A column can only be (part of) a PK if it has been defined as NOT NULL, either in the column definition or in a domain definition.
然后,您可能需要请求服务器自动生成 ID。有几种方法可以做到这一点。
例如,Firebird 3 带有 auto-inc 列类型。 这是数据库开发人员以前明确使用的工具的语法糖。
Firebird 2 和之前的版本使用 GENERATORS(又名 SQL SEQUENCE)来实现它。
您必须在 table 上创建一个 BEFORE-INSERT(或 BEFORE-INSERT-OR-UPDATE)触发器,如果 ID 字段为 NULL,它将填充来自生成器的 ID 字段。 http://www.firebirdfaq.org/faq29/
CREATE GENERATOR gen_t1_id;
SET GENERATOR gen_t1_id TO 0;
set term !! ;
CREATE TRIGGER T1_BI FOR T1
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
if (NEW.ID is NULL) then NEW.ID = GEN_ID(GEN_T1_ID, 1);
END!!
set term ; !!
归结为您的 SQL 访问库。
因为通常在您插入该行之后 - 您必须知道它的 ID。
如果你不关心新生行的那个ID,你可以跳过剩下的。
但是如果您既想插入该行又想知道它的 ID,那么它归结为另一种选择。
低技术含量的 SQL- 只有图书馆会迫使您进行双程旅行:
SELECT GEN_ID(GEN_T1_ID, 1) FROM RDB$DATABASE
或 SELECT NEXT VALUE FOR GEN_T1_ID FROM RDB$DATABASE
会为您保留一个免费令牌,然后您会明确地将您的 ID PK 列分配给该值并将其与数据列一起插入,绕过触发器。
或者使用高级 SQL 库,您可以要求 Firebird 自动计算值并将其报告给您:INSERT INTO tablename(data1,data2,dataq3) VALUES (1,2,3) RETURNING id
。参见 https://en.wikipedia.org/wiki/Insert_(SQL)#Retrieving_the_key
是否需要学习插入的 ID,以及您的 SQL 库是否支持 INSERT-RETURNING 命令 - 由您决定。
然而,当我进行 Google 搜索(它是 www.google.com )时,它带有许多关于 C# Firebird Insert Returniung
的链接,用于许多不同的 C# SQL 库,同样只有你可以告诉你使用哪一个。来自不同库的几个例子:
- http://www.ibprovider.com/eng/documentation/firebird_21_adonet.html
- http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=720869&msg=8075816
- Retrieve last id from Firebird db table
- Firebird insert...returning asp.net
- https://social.msdn.microsoft.com/Forums/en-US/e7099cfb-7809-460a-aae9-79a2bd703454/how-i-can-return-the-id-after-insert-a-record-into-a-database-firebird-25-with-linq?forum=adodotnetentityframework
等等
定义:
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_NO_KEY_ID = " fstPriority" +
", fstInfo" +
", fstDateCreated" +
", fstDateModified ";
public const string stFIELD_NAMES_KEY_ID = " fiKeyID ";
public const string stFIELD_NAMES = stFIELD_NAMES_NO_KEY_ID + ", " + stFIELD_NAMES_KEY_ID;
代码:
//------------------------------
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,
string stFieldNamesKeyId,
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 " + stFieldNamesKeyId;
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
//------------------------------
为什么 ExecuteNonQuery 捕获异常 {"validation error for column \"ORGTABLE\".\"FIKEYID\",值 \"* null *\""}
string stValuesPlaceHolder = "@p0";
for (int iii = 1; iii < liststFieldValuesNoKeyId.Count; iii++)
stValuesPlaceHolder += ", @p" + (iii).ToString();
FbTransaction fbTransaction = fbConn.BeginTransaction();
FbCommand fbCmd = new FbCommand("INSERT INTO " + stTableName + "(" + stFieldNamesNoKeyId + ") VALUES ( " + stValuesPlaceHolder + " )", 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.ExecuteNonQuery();
fbTransaction.Commit();
stTableName 是 OrgTable。
字段名称是:
fstPriority, fstInfo, fstDateCreated, fstDateModified, fiKeyID.
字段定义为:
fstPriority VARCHAR(30), fstInfo VARCHAR(100), fstDateCreated VARCHAR(30), fstDateModified VARCHAR(30), fiKeyID INTEGER PRIMARY KEY
这段代码中:
stFieldNamesNoKeyId = "fstPriority, fstInfo, fstDateCreated, fstDateModified".
stValuesPlaceHolder = "@p0, @p1, @p2, @p3"
四个 fbCmd.Parameters.AddWithValue:
stPlaceHolder = "@p0" ... stValue = "1st value";
stPlaceHolder = "@p1" ... stValue = "2nd value";
stPlaceHolder = "@p2" ... stValue = "3rd value";
stPlaceHolder = "@p3" ... stValue = "4th value";
我没有为 fiKeyID 添加值,因为它是主键。
I did not add a value for fiKeyID as it as the PRIMARY KEY.
因此您尝试插入一个 NULL 主键。这是不允许的。
http://www.firebirdsql.org/manual/nullguide-keys.html
NULLs are never allowed in primary keys. A column can only be (part of) a PK if it has been defined as NOT NULL, either in the column definition or in a domain definition.
然后,您可能需要请求服务器自动生成 ID。有几种方法可以做到这一点。
例如,Firebird 3 带有 auto-inc 列类型。 这是数据库开发人员以前明确使用的工具的语法糖。
Firebird 2 和之前的版本使用 GENERATORS(又名 SQL SEQUENCE)来实现它。
您必须在 table 上创建一个 BEFORE-INSERT(或 BEFORE-INSERT-OR-UPDATE)触发器,如果 ID 字段为 NULL,它将填充来自生成器的 ID 字段。 http://www.firebirdfaq.org/faq29/
CREATE GENERATOR gen_t1_id;
SET GENERATOR gen_t1_id TO 0;
set term !! ;
CREATE TRIGGER T1_BI FOR T1
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
if (NEW.ID is NULL) then NEW.ID = GEN_ID(GEN_T1_ID, 1);
END!!
set term ; !!
归结为您的 SQL 访问库。 因为通常在您插入该行之后 - 您必须知道它的 ID。
如果你不关心新生行的那个ID,你可以跳过剩下的。
但是如果您既想插入该行又想知道它的 ID,那么它归结为另一种选择。
低技术含量的 SQL- 只有图书馆会迫使您进行双程旅行:
SELECT GEN_ID(GEN_T1_ID, 1) FROM RDB$DATABASE
或SELECT NEXT VALUE FOR GEN_T1_ID FROM RDB$DATABASE
会为您保留一个免费令牌,然后您会明确地将您的 ID PK 列分配给该值并将其与数据列一起插入,绕过触发器。或者使用高级 SQL 库,您可以要求 Firebird 自动计算值并将其报告给您:
INSERT INTO tablename(data1,data2,dataq3) VALUES (1,2,3) RETURNING id
。参见 https://en.wikipedia.org/wiki/Insert_(SQL)#Retrieving_the_key
是否需要学习插入的 ID,以及您的 SQL 库是否支持 INSERT-RETURNING 命令 - 由您决定。
然而,当我进行 Google 搜索(它是 www.google.com )时,它带有许多关于 C# Firebird Insert Returniung
的链接,用于许多不同的 C# SQL 库,同样只有你可以告诉你使用哪一个。来自不同库的几个例子:
- http://www.ibprovider.com/eng/documentation/firebird_21_adonet.html
- http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=720869&msg=8075816
- Retrieve last id from Firebird db table
- Firebird insert...returning asp.net
- https://social.msdn.microsoft.com/Forums/en-US/e7099cfb-7809-460a-aae9-79a2bd703454/how-i-can-return-the-id-after-insert-a-record-into-a-database-firebird-25-with-linq?forum=adodotnetentityframework
等等
定义:
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_NO_KEY_ID = " fstPriority" +
", fstInfo" +
", fstDateCreated" +
", fstDateModified ";
public const string stFIELD_NAMES_KEY_ID = " fiKeyID ";
public const string stFIELD_NAMES = stFIELD_NAMES_NO_KEY_ID + ", " + stFIELD_NAMES_KEY_ID;
代码:
//------------------------------
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,
string stFieldNamesKeyId,
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 " + stFieldNamesKeyId;
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
//------------------------------