为什么ExecuteNonQuery捕获异常{“列验证错误”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的值,因为它与PRIMARY KEY一样。
答案 0 :(得分:1)
我没有添加fiKeyID的值,因为它与PRIMARY KEY一样。
因此,您尝试插入NULL主键。这是不允许的。
http://www.firebirdsql.org/manual/nullguide-keys.html
主键中绝不允许使用NULL。如果列已定义为NOT NULL,则列只能是(PK的一部分),无论是在列定义中还是在域定义中。
然后,您可能想要求服务器自动生成ID。这样做的方法很少。
例如,Firebird 3附带auto-inc列类型。 这是一种语法糖,而不是数据库开发人员之前明确使用过的工具。Firebird 2和之前的版本使用GENERATORS(又名SQL SEQUENCE)来实现它。
如果ID字段为NULL,则必须在表上进行BEFORE-INSERT(或BEFORE-INSERT-OR-UPDATE)触发器,该触发器将填充生成器的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列分配给该值,并将其与数据列一起插入,绕过触发器。< / p>
或者使用高级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命令 - 由您自行决定。
但是当我进行谷歌搜索(它是www.google.com)时,它会为许多不同的C#SQL库提供许多关于C# Firebird Insert Returniung
的链接,而且只有你可以告诉你使用哪一个。对于来自不同库的少数示例:
等等
答案 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_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
//------------------------------