为啥 PDO 的 Oracle 驱动程序不实现 lastInsertId()?

Posted

技术标签:

【中文标题】为啥 PDO 的 Oracle 驱动程序不实现 lastInsertId()?【英文标题】:Why doesn't PDO's Oracle driver implement lastInsertId()?为什么 PDO 的 Oracle 驱动程序不实现 lastInsertId()? 【发布时间】:2012-03-08 21:30:06 【问题描述】:

我在 PDO 中收到此错误:

错误:消息:PDO::lastInsertId() [pdo.lastinsertid]: SQLSTATE[IM001]:驱动程序不支持此功能:驱动程序支持 不支持 lastInsertId()

当试图从 oracle 数据库中获取最后插入的 id 时。我将序列字符串添加到最后一个插入 id 函数但仍然无法正常工作。对于带有 PDO 的 Oracle 上的这个错误,Google 没有多说。

【问题讨论】:

您是否尝试过通过查询来获取它? (假设 Oracle 有一个功能) 【参考方案1】:

Oracle 没有自动增量列,因此不像 mysql 那样支持 lastInsertId。您必须使用 Oracle 序列来实现等效的“手动”。

为每个需要它的表创建一个 oracle 序列,并在需要插入时使用 NEXTVAL 检索它,然后在插入表时使用该值。

$sh = $conn->prepare('SELECT uid_seq.NEXTVAL AS nextInsertID FROM DUAL');
$sh->execute();
$nextInsertId = $sh->fetchColumn(0);

$sh = $conn->prepare("INSERT INTO table (id, data) VALUES(?, 255)");
$sh->execute(array($nextInsertId));

【讨论】:

这种竞争条件安全吗? (我对甲骨文一无所知,只是好奇) @Pekka - 不,Oracle 服务器在没有竞争条件风险的情况下发出序列号,在每次请求 NEXTVAL 时递增和发出......就像 MySQL 的自动增量一样,除了在序列级别而不是比表级别。我认为否则有人会遇到问题,而如此基本的问题会破坏 Oracle 作为数据库。但是,没有什么可以阻止用户使用这种方法在 id 列中存储“任何旧值”。 我发现需要获取序列中的下一个值,然后发出插入有点难看。 Oracle 是否有类似 Postgres 的 curval / nextval / lastval 函数,可用内联? (出于好奇而询问。) INSERT INTO table (id, data) VALUES(uid_seq.NEXTVAL, 255);其次是 SELECT uid_seq.CURRVAL AS lastInsertID FROM DUAL;也将完全有效....但 LASTVAL 不存在【参考方案2】:

在 Oracle 中,您应该为需要自动递增列的表创建一个 oracle 序列。

如果你想插入,那么你可以同时插入,而不是查询nextIncrementId并插入如下:

$sh = $conn->prepare("INSERT INTO table (id, data) VALUES(SEQUENCE_NAME.NEXTVAL, ?)");
$sh->execute(array($valueToBeInsertedInDataColumn));

如果您只想知道最后一个插入 id,那么 不要使用 nextval,因为无论何时调用它,它都会将值增加到下一个。为此,您应该使用 CURRVAL。下面是一个例子:

$sh = $conn->prepare("SELECT SEQUENCE_NAME.CURRVAL AS lastInsertId FROM DUAL");
$lastInserId = $sh->execute();

调试:print_r($lastInserId);

【讨论】:

以上是关于为啥 PDO 的 Oracle 驱动程序不实现 lastInsertId()?的主要内容,如果未能解决你的问题,请参考以下文章

php中Oracle的程序与PDO

PDO::PARAM_FLOAT 不存在,为啥?

为啥 PDO 不允许具有相同名称的多个占位符?

为啥这种使用 PDO 计算 Mysql 行数的方法不起作用? [关闭]

PDO抽象层访问

PDO_OCI:找不到驱动程序