百科狗-知识改变命运!
--

PDO::lastInsertId() - PDO类

是丫丫呀12个月前 (11-21)阅读数 10#技术干货
文章标签序列

PDO::lastInsertId()

(PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.1.0)

返回最后插入行的ID或序列值

说明

PDO::lastInsertId([string $name= NULL]): string

返回最后插入行的ID,或者是一个序列对象最后的值,取决于底层的驱动。比如,PDO_PGSQL()要求为$name参数指定序列对象的名称。

Note:

PDO::lastInsertId() - PDO类

在不同的 PDO 驱动之间,此方法可能不会返回一个有意义或一致的结果,因为底层数据库可能不支持自增字段或序列的概念。

参数

$name

应该返回ID的那个序列对象的名称。

返回值

如果没有为参数$name指定序列名称,PDO::lastInsertId()则返回一个表示最后插入数据库那一行的行ID的字符串。

如果为参数$name指定了序列名称,PDO::lastInsertId()则返回一个表示从指定序列对象取回最后的值的字符串。

如果当前 PDO 驱动不支持此功能,则PDO::lastInsertId()触发一个IM001SQLSTATE 。

Remember, if you use a transaction you should use lastInsertId BEFORE you commit
otherwise it will return 0
To save time for some of you.
When using MySQL or MariaDB while inserting multiple rows in a single query (INSERT INTO table (a,b,c) VALUES (1,2,3), (2,3,4), ...) to a table with auto_increment column, PDO::lastInsertId does NOT return the autogenerated id of the last row. Instead, the FIRST generated id is returned. This may very well be explained by taking a look at MySQL and MariaDB's documentation.
Quotations from their respective documentations, 
MySQL:
"With no argument, LAST_INSERT_ID() returns a BIGINT UNSIGNED (64-bit) value representing the first automatically generated value successfully inserted for an AUTO_INCREMENT column as a result of the most recently executed INSERT statement."
MariaDB:
"LAST_INSERT_ID() (no arguments) returns the first automatically generated value successfully inserted for an AUTO_INCREMENT column as a result of the most recently executed INSERT statement."
This is clearly not what lastInsertId's own documentation states. Hopefully this will save someone from debugging the cause of id mismatch.
tl;dr (MySQL | Mariadb) + multi row insert + PDO::lastInsertId = first autogenerated id
Behaviour tested using MariaDB 10.2.6 32-bit, PHP 5.6.31 32-bit and mysqlnd 5.0.11 running on windows 7.
Beware of lastInsertId() when working with transactions in mysql. The following code returns 0 instead of the insert id.

When no exception is thrown, lastInsertId returns 0. However, if lastInsertId is called before calling commit, the right id is returned.
Sorry to contradict Jonathon Hibbard's comment (http://php.net/manual/en/pdo.lastinsertid.php#82838), but my experiencie with INSERT INTO ... ON DUPLICATE KEY UPDATE is totally different; maybe it's due to PHP version (I'm on Windows, 5.4.7; I realize his post is 6 years old) or to the database engine (MySQL in my case).
Nevertheless, if I do an INSERT INTO ... ON DUPLICATE KEY UPDATE (something like id=id or equivalent, where the updated value is equal to the original one), this is what I'm getting:
- If the key didn't exist, the value is inserted, and lastInsertId() returns the expected id for the new row.
- If the row exists AND a value is updated, with lastInsertId() I get the ID of the updated row.
- If the row exists but NO value is updated, lastInsertId() returns 0.
That contradicts his example, where he assures that
"INSERT INTO city (`city`) VALUES ('Paris') ON DUPLICATE KEY UPDATE `city` = 'Paris'"
returns 2 (??) on lastInsertId() and that he expected to return 1 "since no records were inserted" (??).
Hope this helps someone.
I think I get a nice solution in Postgres to get the ID using the RETURNING that comes with Postgress since version 8.2. In the example below, I add to my insert clause the "returning" along with the primary key of my table, then after the execute, I do a fetch getting an array with the value of the last inserted id. 
If you're accessing MSSQL/SQL Server 2008 R2 (or higher) from Linux via FreeTDS there's a slightly neater way of getting the last insert ID than the solution(s) outlined below.
The specific SQL involved is outlined here:
http://msdn.microsoft.com/en-us/library/ms177564.aspx
So for example, with a table containing the two columns (product_id, product_name) where product_id is a uniqueidentifier or something similar you could do the following.

Then $temp will contain an array like:
Array
(
  [product_id] => E1DA1CB0-676A-4CD9-A22C-90C9D4E81914
)
Just be warned that there are some issues relating to how uniqueidentifier columns are handled by PDO_DBLIB/FreeTDS depending on the TDS version you choose that have only been fixed as of PHP 5.3.7.
Information regarding this and the patch can be found here:
https://bugs.php.net/bug.php?id=54167
in case anyone was wondering
something like
$val = 5;
$sql = "REPLACE table (column) VALUES (:val)";
$stmt = $dbh->prepare($sql);
$stmt->bindParam(':val', $val, PDO::PARAM_INT);
$stmt->execute();
$lastId = $dbh->lastInsertId();
will return the last inserted id, whether the record was replaced or simply inserted
the REPLACE syntax, simply inserts, or deletes > inserts
so lastInsertId() still works
refer to http://mysql.com/doc/refman/5.0/en/replace.html
for REPLACE usage
It should be mentioned that this function DOES NOT retrieve the ID (Primary key) of the row but it's OID instead.
So if you use one of the latest PostgreSQL versions this function won't help you unless you add OID to the table specifically when you create it.
This function is now compatible with the newer MS SQL driver. http://msdn.microsoft.com/en-us/library/ff628155(v=sql.105)
About the connections created through classes
eg: db::SQL() >query();
then db::SQL() >lastInsertId();
it will create a new connection and will not return the last ID inserted. it is better to include a PDO connection file (or directly the logins) and work with it to get the last ID properly.
$db = new PDO(logins);
$db->query();
$db->lastInsertId();
Easiest solution I've found for MSSQL to obtain the last inserted ID is 
On version 7.0.9 I've implemented lastInsertId without having to name the sequence for PostgreSQL (I've also have done it for 5.6.can'trememberthenumber, but I can't find the PR).
Can someone update the documentation about it?
Here is the Pull Request: https://github.com/php/php-src/pull/2014
$dbh->commit(); 
print $dbh->lastInsertId(); 
The above will always return zero (0)
So it is important to call $dbh->lastInsertId(); before commiting transaction 
the above should be modified as 
print $dbh->lastInsertId(); 
$dbh->commit();
Simple example: 
Workaround for the fact that MSSQL does not provide lastInsertId(). This is locale-independent by design. 
In response to Yonatan Ben-Nes, it does appear that using the latest versions of PHP 5.x and PostgreSQL 8.x, the driver will return a "meaningful" ID (rather than an OID), provided you pass the name of the corresponding sequence.
So, if you created a table as follows:
CREATE TABLE "user" (
"id" SERIAL PRIMARY KEY NOT NULL,
"username" character varying(32)
);
PostgreSQL will (by default) create a sequence called 'user_id_seq'.
You can then do something like:
$strTable = "user":
$last_insert_id = $objPDO->lastInsertId("$strTable_id_seq);
This does appear to function as expected. What is a little unclear to me is whether this simply returns the current value of the sequence; if it does, this isn't a particularly reliable indicator as to the id of the record your code just inserted, especially if your site or application is especially high traffic.
It should be noted that, at least for MySQL using InnoDB tables, with transactions PDO will report the last insert id as 0 after the commit, the real ids are only reported before committing.
(As a side note, MySQL keeps the ID number incremented after a rollback).
As said by Dennis Du Kroger, in this situation the function will return 0. 
But you can retrieve the last inserted Id executing a query asking for the function LAST_INSERT_ID() (at least in MySQL)
Try this:
($o_db is the declared adapter)
$last_id = $o_db->fetchAll('SELECT LAST_INSERT_ID() as last_id');
    
$last_id = intval($last_id[0]['last_id']);
beware when mixing auto-incremented and explicit IDs!
Given a fresh table "tbl", executing 
insert into tbl values (0, 'kaeptn blaubaer'); --auto increment (-> 1)
insert into tbl values (16, 'pipi langstrumpf'); --explicit id (-> 16)
select LAST_INSERT_ID();
will return 1, which is not the value of the last insert. its the value from the last auto-increment insert!
(using mysql)
WARNING for PostgreSQL users! In response to the comment by ed at hicklinslade dot com, who wrote:
...
$last_insert_id = $objPDO->lastInsertId("$strTable_id_seq);
This does appear to function as expected. What is a little unclear to me is whether this simply returns the current value of the sequence; if it does, this isn't a particularly reliable indicator as to the id of the record your code just inserted, especially if your site or application is especially high traffic.
...
NEVER ever use lastInsertId() with PostgreSQL sequences, ESPECIALLY when your application's insert/update load is high. PostgreSQL sequences are non-transactional (a natural design feature to avoid exclusive locking which otherwise produces unacceptable performance). This means that any concurrent transaction incrementing the same sequence will render the value returned by lastInsertId() invalid with respect to the last insert by your transaction. Example:
Transaction 1 inserts with nextval('some_seq') yielding 100;
Concurrent transaction 2 inserts with nextval('some_seq') yielding 101;
Transaction 1 calls lastInsertId(), expecting 100, BUT GETS 101.
This PDO method is braindead for PostgreSQL, always use INSERT ... RETURNING instead. Regards.
This function is not available for MSSQL either.
@nour
You need to call lastInsertId before you commit
It should be noted here at this function will not display the correct ID if issuing ON DUPLICATE KEY UPDATE.
Example on a new Row:

鹏仔微信 15129739599 鹏仔QQ344225443 鹏仔前端 pjxi.com 共享博客 sharedbk.com

免责声明:我们致力于保护作者版权,注重分享,当前被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理!邮箱:344225443@qq.com)

图片声明:本站部分配图来自网络。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

内容声明:本文中引用的各种信息及资料(包括但不限于文字、数据、图表及超链接等)均来源于该信息及资料的相关主体(包括但不限于公司、媒体、协会等机构)的官方网站或公开发表的信息。部分内容参考包括:(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供参考使用,不准确地方联系删除处理!本站为非盈利性质站点,本着为中国教育事业出一份力,发布内容不收取任何费用也不接任何广告!)