我将firebird数据库配置为自动增加表的主键。
CREATE GENERATOR GEN_CHANNEL_PARAMETER_SET_ID;
SET GENERATOR GEN_CHANNEL_PARAMETER_SET_ID TO 0;
CREATE TRIGGER CHANNEL_PARAMETER_SETS_BI FOR CHANNEL_PARAMETER_SETS
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
if (NEW.CHANNEL_PARAMETER_SET_ID is NULL) then NEW.CHANNEL_PARAMETER_SET_ID = GEN_ID(GEN_CHANNEL_PARAMETER_SET_ID, 1);
END
现在,在我使用IBPP的C ++程序中,我遇到了以下问题:
将数据集插入此表的新行时,我知道我的C ++程序中的所有值都会释放新的主键,因为数据库会创建它。如何从数据库中检索此密钥?
也许其他人也插入了一个条目 - 就在我插入一个条目后的那一刻。因此,检索具有最高值的PK可能会产生错误。我怎么处理这个?
采用Amir Rahimi Farahani的回答我找到了以下问题的解决方案:
我使用发电机:
CREATE GENERATOR GEN_CHANNEL_PARAMETER_SET_ID;
SET GENERATOR GEN_CHANNEL_PARAMETER_SET_ID TO 0;
以及以下C ++ / IBPP / SQL代码:
// SQL statement
m_DbStatement->Execute(
"SELECT NEXT VALUE FOR gen_channel_parameter_set_id FROM rdb$database"
);
// Retrieve Data
IBPP::Row ibppRow;
int64_t channelParameterSetId;
m_DbStatement->Fetch(ibppRow);
ibppRow->Get (1, channelParameterSetId);
// SQL statement
m_DbStatement->Prepare(
"INSERT INTO channel_parameter_sets "
"(channel_parameter_set_id, ...) "
"VALUES (?, ...) "
);
// Set variables
m_DbStatement->Set (1, channelParameterSetId);
...
...
// Execute
m_DbStatement->Execute ();
m_DbTransaction->CommitRetain ();
答案 0 :(得分:4)
在插入新记录之前,可以生成并使用新的id:
SELECT NEXT VALUE FOR GEN_CHANNEL_PARAMETER_SET_ID FROM rdb$database
您现在知道新主键的值。
<强>更新强>
IBPP也支持RETURNING
:
// SQL statement
m_DbStatement->Prepare(
"INSERT INTO channel_parameter_sets "
"(...) VALUES (...) RETURNING channel_parameter_set_id"
);
// Execute
m_DbStatement->Execute ();
m_DbTransaction->CommitRetain ();
// Get the generated id
m_DbStatement->Get (1, channelParameterSetId);
...
答案 1 :(得分:3)
要检索生成的密钥(或任何其他列)的值,您可以使用INSERT ... RETURNING ...
。
例如:
INSERT INTO myTable (x, y, z) VALUES (1, 2, 3) RETURNING ID
许多驱动程序还提供额外的功能来支持RETURNING
,但我不了解IBPP。
请注意,从驱动程序的角度来看,使用RETURNING
会使插入行为像可执行存储过程一样;某些驱动程序可能要求您以特定方式执行它。