Firebird/IBPP: 如何获取数据库自增生成的ID?
Firebird/IBPP: How to retrieve ID generated by a database autoincrement?
我将我的 firebird 数据库配置为自动增加 table 的主键。
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++ 程序中,我遇到了以下问题:
将数据集插入此 table 的新行时,我知道我的 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 ();
要检索生成的键(或任何其他列)的值,您可以使用 INSERT ... RETURNING ...
。
例如:
INSERT INTO myTable (x, y, z) VALUES (1, 2, 3) RETURNING ID
还有很多驱动程序提供额外的功能来支持RETURNING
,但我不知道IBPP。
请注意,从驱动程序的角度来看,使用 RETURNING
将使插入行为像一个可执行的存储过程;某些驱动程序可能会要求您以特定方式执行它。
可以在插入新记录前生成并使用新的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);
...
我将我的 firebird 数据库配置为自动增加 table 的主键。
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++ 程序中,我遇到了以下问题:
将数据集插入此 table 的新行时,我知道我的 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 ();
要检索生成的键(或任何其他列)的值,您可以使用 INSERT ... RETURNING ...
。
例如:
INSERT INTO myTable (x, y, z) VALUES (1, 2, 3) RETURNING ID
还有很多驱动程序提供额外的功能来支持RETURNING
,但我不知道IBPP。
请注意,从驱动程序的角度来看,使用 RETURNING
将使插入行为像一个可执行的存储过程;某些驱动程序可能会要求您以特定方式执行它。
可以在插入新记录前生成并使用新的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);
...