PHP MySQL PDO:获取最后插入的 ROW 而不是 ID
PHP MySQL PDO: get last inserted ROW not ID
我目前有一个脚本可以在使用表单添加新元素时自动插入新数据。
我用
public string PDO::lastInsertId ([ string $name = NULL ] )
当然是逻辑。现在我只是想知道如果 table 没有 ID 字段也没有自动递增字段,这是否会导致任何问题。
抛开事实,如果这意味着使用了错误的数据库结构。
我想确保这个例程在任何情况下都能正常工作。好的数据库或坏的数据库结构。应该没关系。
我的意思是我想取回包含数据的行,以便我可以搜索它。
例如
1
将新数据插入数据库
$query = $pdo->prepare("INSERT INTO `tablename` SET `data_name`='John', `data_familyname`='Doe', 'data_age`=45, `data_wife`='Sarah Doe'");
$query->execute();
2
完全获取最后插入的行
///$LastID = $pdo->lastInsertId();
$query = $pdo->prepare("SELECT `data_name`,`data_familyname`,`data_age`,`data_wife` FROM `tablename` WHERE LAST IDFIELD = ".$pdo->lastInsertId());
$query->execute();
$row = $query->fetch();
行包含
array(
'data_name' => 'John',
'data_familyname' => 'Doe',
'data_age' => '45',
'data_wife' => 'Sarah Doe'
);
3
然后用刚插入的数据更新最后插入的行
$query = $pdo->prepare("UPDATE `tablename` SET `data_name`='Chris' WHERE `data_name`=? AND `data_familyname`=? AND 'data_age`=? AND `data_wife`=?");
$query->execute(array_values($row));
最后的查询基本是:
UPDATE `tablename` SET `data_name`='Chris'
WHERE `data_name`='John' AND `data_familyname`='Doe' AND 'data_age`='45' AND `data_wife`='Sarah Doe'
当然有重复数据存在的可能。你只想修改最后一行。这就是我的意思,除了数据库是否有任何好的结构之外。
但是为了防止重复数据,可以添加:
行包含
array(
'data_id' => 20,
'data_name' => 'John',
'data_familyname' => 'Doe',
'data_age' => '45',
'data_wife' => 'Sarah Doe'
);
重点是
第 2 步
没用,因为我只用了几分钟就完成了。但是我想知道是否有任何类似的功能或例程与我刚才提到的相同。
希望清楚我想要什么
我最终的解决方案是:
$sth = $pdo_connection->prepare("INSERT INTO `pdo_test` SET
`pdo_name` = 'John Doe',
`pdo_description` = 'John Doe who served in Vietnam and every other war game as a default name',
`pdo_text` = 'Some text BLABLA'
");
$sth ->execute();
$stmt = $pdo_connection->query("SELECT LAST_INSERT_ID()");
$result = $stmt->fetch(PDO::FETCH_ASSOC);
$lastID = $result['LAST_INSERT_ID()'];
$stmt = $pdo_connection->prepare("SHOW COLUMNS FROM `pdo_test` WHERE EXTRA LIKE '%AUTO_INCREMENT%'");
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$AutoIncrementField = $row['Field'];
$stmt = $pdo_connection->prepare('SELECT * FROM `pdo_test` WHERE `'.$AutoIncrementField.'` = ?');
$stmt->execute(array($lastID));
$result = $stmt->fetch(PDO::FETCH_ASSOC);
echo print_r($result);
结果:
Array
(
[pdo_id] => 64
[pdo_name] => John Doe
[pdo_counter] => 0
[pdo_description] => John Doe who served in Vietnam and every other war game as a default name
[pdo_text] => Some text BLABLA
)
但是 AutoIncrement 字段似乎是必不可少的。
第二种解决方案,但仍带有自动增量字段。
(提议者:Edwin Lambregts)
请注意,此解决方案并非万无一失!!!因为查询选择了最后插入的行......但是在所有情况下!因此,如果另一个用户刚刚插入了一个新行......你将看到他的输入而不是你的。如果更新发生在两者之间,则可能会发生这种情况。
$sth = $pdo_connection->prepare("INSERT INTO `pdo_test` SET
`pdo_name` = 'John Doe',
`pdo_description` = 'John Doe who served in Vietnam and every other war game as a default name',
`pdo_text` = 'Some text BLABLA'
");
$sth ->execute();
$stmt = $pdo_connection->prepare("SHOW COLUMNS FROM `pdo_test` WHERE EXTRA LIKE '%AUTO_INCREMENT%'");
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$AutoIncrementField = $row['Field'];
$stmt = $pdo_connection->prepare('SELECT * FROM `pdo_test` ORDER BY `'.$AutoIncrementField.'` DESC LIMIT 0,1');
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
结果是:
Array
(
[pdo_id] => 67
[pdo_name] => John Doe
[pdo_counter] => 0
[pdo_description] => John Doe who served in Vietnam and every other war game as a default name
[pdo_text] => Some text BLABLA
)
获取最后插入的 record/row 当然可以不使用 id。
MySQL 语法:
SELECT column_name FROM table_name
ORDER BY column_name DESC
LIMIT 1
它只会显示最后插入的记录。
我不确定你的问题是什么,但是,为了不把你的 table 中的事情搞砸,你必须实施这些事情:
在table上有一个PK
(主键)。它为您提供了一种唯一标识每一行的方法。它应该是唯一标识每一行的字段或字段组合。理论上,PK
的最佳候选者是存储在 table 中标识实体的实体的内在 属性。例如,对于 Country
table,PK
的一个很好的候选者是完整的国家/地区名称。在现实世界中,发明了 AUTO_INCREMENT
个字段,因为:
- 一些table只是没有一个列或一组列可以用作
PK
;例如,用于存储程序生成的日志条目的 table - 所有条目都必须存储,即使其中一些条目相同;使用 AUTO_INCREMENT
字段为他们创建了人工 PK
;
- 当
PK
的最佳候选列的类型为string
(上例中的国家名称)或当PK
的候选列为两个或多个的集合时列,将其用作 PK
会对 table 产生负面性能影响;人工 PK
(创建为 AUTO_INCREMENT
整数字段)会生成较小的索引,从而提高使用它的查询的速度。
在 INSERT
上,您可以为 PK
生成一个值并将其放入查询中,或者依靠数据库为您生成一个值(如果 PK
是一个 AUTO_INCREMENT
字段)。
- 如果您为
PK
生成一个值,您需要确保它不存在于 table 中。您可以检查它是否在 INSERT
之前不存在,或者您可以尝试 INSERT
并检查它是否成功。即使您之前检查过,INSERT
仍然会失败,因为脚本的另一个实例可以同时 运行,为 PK
生成和 INSERT
相同的值。在这种情况下,您需要生成另一个值并再次尝试 INSERT
并且此工作流会重复直到成功。这对我来说似乎不是一个好策略。
您可以让数据库为您的 PK
生成唯一值(通过为 INSERT
查询中的 PK
提供 NULL
或根本不提供)然后询问它产生的价值。 MySQL
为此提供了 LAST_INSERT_ID()
函数。文档摘录:
The ID that was generated is maintained in the server on a per-connection basis. This means that the value returned by the function to a given client is the first AUTO_INCREMENT
value generated for most recent statement affecting an AUTO_INCREMENT
column by that client. This value cannot be affected by other clients, even if they generate AUTO_INCREMENT
values of their own. This behavior ensures that each client can retrieve its own ID without concern for the activity of other clients, and without the need for locks or transactions.
数据库处理一切:值是唯一的,它不会干扰试图同时插入相同 table 的脚本的其他实例(甚至其他代码) ; INSERT
成功,PK
是唯一的,我取回标识我的行而不是其他人的行的值。
有一个额外的列不是存储在 table 中的实体的固有 属性 是为其产生的好处付出的小代价。
这只是一个指南,应该添加一个人为的 AUTO_INCREMENT
列 只有当它有帮助时 。在上面国家 table 的示例中,不需要 PK
的 AUTO_INCREMENTED
列:
- table 仅包含数百行;其中没有插入或删除(实际上有,但只是偶尔发生一次;有可能您的应用程序在需要更改
Country
table 之前就已停用);
-
PK
有一个很好的候选者:是 ISO-3166
国家代码;它甚至有两种口味:2 个字母和 3 个字母 - 选择你最喜欢的;它是 CHAR[2]
(或 CHAR[3]
),因为 table 非常小,所以 PK
不会以任何方式影响性能。
我目前有一个脚本可以在使用表单添加新元素时自动插入新数据。
我用
public string PDO::lastInsertId ([ string $name = NULL ] )
当然是逻辑。现在我只是想知道如果 table 没有 ID 字段也没有自动递增字段,这是否会导致任何问题。
抛开事实,如果这意味着使用了错误的数据库结构。 我想确保这个例程在任何情况下都能正常工作。好的数据库或坏的数据库结构。应该没关系。
我的意思是我想取回包含数据的行,以便我可以搜索它。
例如
1
将新数据插入数据库
$query = $pdo->prepare("INSERT INTO `tablename` SET `data_name`='John', `data_familyname`='Doe', 'data_age`=45, `data_wife`='Sarah Doe'");
$query->execute();
2
完全获取最后插入的行
///$LastID = $pdo->lastInsertId();
$query = $pdo->prepare("SELECT `data_name`,`data_familyname`,`data_age`,`data_wife` FROM `tablename` WHERE LAST IDFIELD = ".$pdo->lastInsertId());
$query->execute();
$row = $query->fetch();
行包含
array(
'data_name' => 'John',
'data_familyname' => 'Doe',
'data_age' => '45',
'data_wife' => 'Sarah Doe'
);
3
然后用刚插入的数据更新最后插入的行
$query = $pdo->prepare("UPDATE `tablename` SET `data_name`='Chris' WHERE `data_name`=? AND `data_familyname`=? AND 'data_age`=? AND `data_wife`=?");
$query->execute(array_values($row));
最后的查询基本是:
UPDATE `tablename` SET `data_name`='Chris'
WHERE `data_name`='John' AND `data_familyname`='Doe' AND 'data_age`='45' AND `data_wife`='Sarah Doe'
当然有重复数据存在的可能。你只想修改最后一行。这就是我的意思,除了数据库是否有任何好的结构之外。
但是为了防止重复数据,可以添加:
行包含
array(
'data_id' => 20,
'data_name' => 'John',
'data_familyname' => 'Doe',
'data_age' => '45',
'data_wife' => 'Sarah Doe'
);
重点是
第 2 步
没用,因为我只用了几分钟就完成了。但是我想知道是否有任何类似的功能或例程与我刚才提到的相同。
希望清楚我想要什么
我最终的解决方案是:
$sth = $pdo_connection->prepare("INSERT INTO `pdo_test` SET
`pdo_name` = 'John Doe',
`pdo_description` = 'John Doe who served in Vietnam and every other war game as a default name',
`pdo_text` = 'Some text BLABLA'
");
$sth ->execute();
$stmt = $pdo_connection->query("SELECT LAST_INSERT_ID()");
$result = $stmt->fetch(PDO::FETCH_ASSOC);
$lastID = $result['LAST_INSERT_ID()'];
$stmt = $pdo_connection->prepare("SHOW COLUMNS FROM `pdo_test` WHERE EXTRA LIKE '%AUTO_INCREMENT%'");
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$AutoIncrementField = $row['Field'];
$stmt = $pdo_connection->prepare('SELECT * FROM `pdo_test` WHERE `'.$AutoIncrementField.'` = ?');
$stmt->execute(array($lastID));
$result = $stmt->fetch(PDO::FETCH_ASSOC);
echo print_r($result);
结果:
Array
(
[pdo_id] => 64
[pdo_name] => John Doe
[pdo_counter] => 0
[pdo_description] => John Doe who served in Vietnam and every other war game as a default name
[pdo_text] => Some text BLABLA
)
但是 AutoIncrement 字段似乎是必不可少的。
第二种解决方案,但仍带有自动增量字段。
(提议者:Edwin Lambregts)
请注意,此解决方案并非万无一失!!!因为查询选择了最后插入的行......但是在所有情况下!因此,如果另一个用户刚刚插入了一个新行......你将看到他的输入而不是你的。如果更新发生在两者之间,则可能会发生这种情况。
$sth = $pdo_connection->prepare("INSERT INTO `pdo_test` SET
`pdo_name` = 'John Doe',
`pdo_description` = 'John Doe who served in Vietnam and every other war game as a default name',
`pdo_text` = 'Some text BLABLA'
");
$sth ->execute();
$stmt = $pdo_connection->prepare("SHOW COLUMNS FROM `pdo_test` WHERE EXTRA LIKE '%AUTO_INCREMENT%'");
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$AutoIncrementField = $row['Field'];
$stmt = $pdo_connection->prepare('SELECT * FROM `pdo_test` ORDER BY `'.$AutoIncrementField.'` DESC LIMIT 0,1');
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
结果是:
Array
(
[pdo_id] => 67
[pdo_name] => John Doe
[pdo_counter] => 0
[pdo_description] => John Doe who served in Vietnam and every other war game as a default name
[pdo_text] => Some text BLABLA
)
获取最后插入的 record/row 当然可以不使用 id。
MySQL 语法:
SELECT column_name FROM table_name
ORDER BY column_name DESC
LIMIT 1
它只会显示最后插入的记录。
我不确定你的问题是什么,但是,为了不把你的 table 中的事情搞砸,你必须实施这些事情:
在table上有一个
PK
(主键)。它为您提供了一种唯一标识每一行的方法。它应该是唯一标识每一行的字段或字段组合。理论上,PK
的最佳候选者是存储在 table 中标识实体的实体的内在 属性。例如,对于Country
table,PK
的一个很好的候选者是完整的国家/地区名称。在现实世界中,发明了AUTO_INCREMENT
个字段,因为:- 一些table只是没有一个列或一组列可以用作
PK
;例如,用于存储程序生成的日志条目的 table - 所有条目都必须存储,即使其中一些条目相同;使用AUTO_INCREMENT
字段为他们创建了人工PK
; - 当
PK
的最佳候选列的类型为string
(上例中的国家名称)或当PK
的候选列为两个或多个的集合时列,将其用作PK
会对 table 产生负面性能影响;人工PK
(创建为AUTO_INCREMENT
整数字段)会生成较小的索引,从而提高使用它的查询的速度。
- 一些table只是没有一个列或一组列可以用作
在
INSERT
上,您可以为PK
生成一个值并将其放入查询中,或者依靠数据库为您生成一个值(如果PK
是一个AUTO_INCREMENT
字段)。- 如果您为
PK
生成一个值,您需要确保它不存在于 table 中。您可以检查它是否在INSERT
之前不存在,或者您可以尝试INSERT
并检查它是否成功。即使您之前检查过,INSERT
仍然会失败,因为脚本的另一个实例可以同时 运行,为PK
生成和INSERT
相同的值。在这种情况下,您需要生成另一个值并再次尝试INSERT
并且此工作流会重复直到成功。这对我来说似乎不是一个好策略。 您可以让数据库为您的
PK
生成唯一值(通过为INSERT
查询中的PK
提供NULL
或根本不提供)然后询问它产生的价值。MySQL
为此提供了LAST_INSERT_ID()
函数。文档摘录:The ID that was generated is maintained in the server on a per-connection basis. This means that the value returned by the function to a given client is the first
AUTO_INCREMENT
value generated for most recent statement affecting anAUTO_INCREMENT
column by that client. This value cannot be affected by other clients, even if they generateAUTO_INCREMENT
values of their own. This behavior ensures that each client can retrieve its own ID without concern for the activity of other clients, and without the need for locks or transactions.数据库处理一切:值是唯一的,它不会干扰试图同时插入相同 table 的脚本的其他实例(甚至其他代码) ;
INSERT
成功,PK
是唯一的,我取回标识我的行而不是其他人的行的值。
- 如果您为
有一个额外的列不是存储在 table 中的实体的固有 属性 是为其产生的好处付出的小代价。
这只是一个指南,应该添加一个人为的 AUTO_INCREMENT
列 只有当它有帮助时 。在上面国家 table 的示例中,不需要 PK
的 AUTO_INCREMENTED
列:
- table 仅包含数百行;其中没有插入或删除(实际上有,但只是偶尔发生一次;有可能您的应用程序在需要更改
Country
table 之前就已停用); -
PK
有一个很好的候选者:是ISO-3166
国家代码;它甚至有两种口味:2 个字母和 3 个字母 - 选择你最喜欢的;它是CHAR[2]
(或CHAR[3]
),因为 table 非常小,所以PK
不会以任何方式影响性能。