PHP MySQL PDO:获取上次插入的行而不是ID


PHP MySQL PDO: get last inserted ROW not ID

我目前有一个脚本,可以在使用表单添加新元素时自动插入新数据。

我使用

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

当然是逻辑。现在我只想知道如果表没有 ID 字段和没有自动增量字段,这是否会导致任何问题。

撇开事实不谈,如果这意味着使用了错误的数据库结构。我想确保这个例程在任何情况下都有效。好的数据库或坏的数据库结构。这应该没关系。

我的意思是我想返回包含数据的行,以便我可以搜索它。

例如

1

将新数据插入数据库

$query = $pdo->prepare("INSERT INTO `tablename` SET `data_name`='John', `data_familyname`='Doe', 'data_age`=45, `data_wife`='Sarah Doe'");
$query->execute();

阿拉伯数字

完全获取最后插入的行

///$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
)

但是自动增量字段似乎是必不可少的。

第二种解决方案,但仍带有自动增量字段。

(提议者:埃德温·兰布雷茨)

请注意,此解决方案不是故障安全的!!因为查询会选择最后插入的行...但在所有情况下!因此,如果另一个用户刚刚插入了新行...你将看到他的输入,而不是你的。如果更新发生在两者之间,则可能会发生这种情况。

$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
)

我不确定你的问题是什么,但是,为了不弄乱表中的东西,你必须实现这些东西:

  1. 表上有PK(主键)。它为您提供了一种唯一标识每一行的方法。它应该是一个字段或唯一标识每一行的字段组合。从理论上讲,PK的最佳候选者是存储在标识实体的表中的实体的固有属性。例如,对于Country表,PK的良好候选项是完整的国家/地区名称。在现实世界中,发明AUTO_INCREMENT场是因为:

    • 有些表只是没有可以用作PK的列或一组列; 例如,用于存储程序生成的日志条目的表 - 即使其中一些条目相同,也必须存储所有条目; 使用AUTO_INCREMENT字段为它们创建人工PK;
    • PK 的最佳候选列的类型为 string(上例中的国家/地区名称)或PK候选项是一组两列或更多列时,将其用作PK将对表的性能产生负面影响;人工PK(创建为AUTO_INCREMENT整数字段)生成较小的索引,从而提高使用它的查询的速度。
  2. INSERT上,您可以为PK生成一个值并将其放入查询中,也可以依靠数据库为您生成一个值(如果PKAUTO_INCREMENT字段)。

    • 如果为PK生成值,则需要确保表中尚不存在该值。您可以在INSERT之前检查它是否存在,也可以尝试INSERT并检查它是否成功。即使您之前检查过,INSERT仍然可能失败,因为脚本的另一个实例可以同时运行,为 PK 生成和INSERT相同的值。在这种情况下,您需要生成另一个值并尝试再次INSERT,此工作流将重复,直到成功。这对我来说似乎不是一个好的策略。
    • 您可以让数据库为您的PK生成唯一值(通过在INSERT查询中为PK提供NULL或根本不提供它),然后询问它生成的值。 MySQL为此提供了LAST_INSERT_ID()功能。文档摘录:

      生成的 ID 基于每个连接在服务器中维护。这意味着函数返回给给定客户端的值是为该客户端影响AUTO_INCREMENT列的最新语句生成的第一个AUTO_INCREMENT值。此值不受其他客户端的影响,即使它们生成自己的AUTO_INCREMENT值也是如此。此行为可确保每个客户端都可以检索自己的 ID,而无需担心其他客户端的活动,也不需要锁或事务。

      数据库负责所有事情:值是唯一的,它不会干扰尝试同时插入同一表中的脚本(甚至其他代码)的其他实例;INSERT成功,PK是唯一的,我得到标识我的行的值,而不是其他人的行。

如果附加列不是存储在表中的实体的固有属性,那么对于它产生的好处来说,这是一个很小的代价。

这只是一个指南,只有在有帮助时才应添加人工AUTO_INCREMENT列。在上面的国家/地区表中,不需要PKAUTO_INCREMENTED列:

  • 该表仅包含几百行;其中没有插入或删除(事实上有,但只是偶尔一次;您的应用程序可能在需要更改Country表之前就已停用);
  • PK有一个很好的候选者:是ISO-3166国家代码;它甚至有两种风格:2个字母和3个字母 - 选择你最喜欢的;它是一个CHAR[2](或CHAR[3]),因为桌子太小了,因为它PK不会以任何方式影响性能。

当然可以在不使用id的情况下获取最后插入的记录/行。

MySQL 语法:

SELECT column_name FROM table_name ORDER BY column_name DESC LIMIT 1

它将仅显示上次插入的记录。

来源: http://www.w3schools.com/sql/sql_func_last.asp