Python mysql.connector cursor.lastrowid 总是返回 0

Posted

技术标签:

【中文标题】Python mysql.connector cursor.lastrowid 总是返回 0【英文标题】:Python mysql.connector cursor.lastrowid always returns 0 【发布时间】:2015-01-31 08:17:39 【问题描述】:

我正在为 Python 2.7 使用 mysql.connector 模块。我已将我的代码分解为最简单的脚本,但我仍然遇到这个问题。问题是,当我尝试获取最后一行 id(在 MySQL 中为 LAST_INSERT_ID)时,无论插入了多少行,我都会返回 0。有人有解决这个问题的办法吗?

我的代码如下:

import mysql.connector
default_config = 
    'user': 'root',
    'password': 'password',
    'host': '127.0.0.1',
    'database': 'test',
    'raise_on_warnings': True,
    'autocommit': True
    
connection = mysql.connector.connect(**default_config)
cursor = connection.cursor()
args = ('name', 'desc')
cursor.callproc('sp_tools_insert', args)
lastid = cursor.lastrowid
print lastid # This returns 0 every time, regardless of number of inserts

我的存储过程如下所示:

CREATE PROCEDURE `sp_tools_insert`
    (
        IN p_name VARCHAR(45), 
        IN p_description VARCHAR(255)
    )
BEGIN 
INSERT INTO TOOLS
    (
        tool_name, 
        description                   
    )
VALUES 
    ( 
        p_name, 
        p_description
    ); 
END

这就是我的TOOLS 表的定义方式:

DROP TABLE IF EXISTS `test`.`TOOLS` ;

CREATE TABLE IF NOT EXISTS `test`.`TOOLS` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `tool_name` VARCHAR(45) NOT NULL,
  `description` VARCHAR(255) NOT NULL,
  PRIMARY KEY (`id`))
ENGINE = InnoDB;

我已验证存储过程工作正常,.callproc() 调用按预期工作。唯一不起作用的是.lastrowid 电话。有什么建议吗?

【问题讨论】:

“内置 mysql 连接器”是指来自 MySQL 项目 (MySQL Connector/Python) 的那个?与其他两个流行的 MySQL 库相比,标准 Python 或大多数第三方 Python 都没有内置它。 另外,你能告诉我们TOOLS表的定义吗? 好的,我澄清了问题并添加了TOOLS表的定义。 这也是我的问题。但是每次 INSERT 或 UPDATE 后返回的 0L 的来源是因为我的表上的主 ID 不是自动递增的。这是一个主要且唯一的 ID,但不是连续的。所以这个——***.com/questions/2548493/…——更适合修复。 【参考方案1】:

@abarnert 说.lastrowid 没有按预期工作的原因是正确的,因为我没有打电话给INSERTUPDATE,而是CALL。因此,解决此问题的唯一方法是按如下方式更改我的存储过程:

CREATE PROCEDURE `sp_tools_insert`
    (
        IN p_name VARCHAR(45), 
        IN p_description VARCHAR(255)
    )
BEGIN 
INSERT INTO TOOLS
    (
        tool_name, 
        description                   
    )
VALUES 
    ( 
        p_name, 
        p_description
    )
SELECT LAST_INSERT_ID();
END

现在,当您调用该存储过程时,您应该期望它返回插入的行的 ID,就像您从任何调用 SELECT 语句的存储过程中获取变量一样.

在这个例子中:

args = ('name', 'desc')
cursor.callproc('sp_tools_insert', args)
for result in cursor.stored_results():
    print result.fetchall() # Or result.fetchone() for just the first result

我仍然不明白为什么.lastrowid 甚至存在,因为它从不与.callproc().execute() 语句一起使用。如果有人对此问题有任何见解,请告诉我!

【讨论】:

首先,这是我向您建议的两个解决方案之一:要么有一个返回 LAST_INSERT_ID 的存储函数,要么在存储过程中显式设置 LAST_INSERT_ID(通过调用-argument 版本而不是零参数版本)。 其次,您链接到的问题证明.lastrowid.execute 语句中永远不起作用,说明恰恰相反:“对于每个用户对象,return cursor.lastrowid 返回实际的 id……”。由于某种原因,它对他的 other 表不起作用,因为他没有回应要求澄清的 cmets,所以没有人可以诊断,但总的来说它确实有效,这就是为什么成千上万的应用程序使用一切正常。【参考方案2】:

lastrowid 属性:

…返回前一个 INSERT 或 UPDATE 语句为 AUTO_INCREMENT 列生成的值…

您还没有运行INSERTUPDATE 语句,而是运行了CALL 语句。

要获取详细信息,您必须点击指向 mysql_insert_id 调用的 mysql_insert_id 函数的 C API 文档的链接。特别是:

mysql_insert_id() 在生成AUTO_INCREMENT 值的存储过程的CALL 语句之后返回0,因为在这种情况下mysql_insert_id() 适用于CALL 而不是过程中的语句。在过程中,您可以在 SQL 级别使用LAST_INSERT_ID() 来获取AUTO_INCREMENT 值。

我在这里假设您的TOOLS 表确实有一个AUTO_INCREMENT 列;否则,你一开始就没有任何价值。

另外,请注意,这只是其中一种方式,与您的断言相反,lastrowidLAST_INSERT_ID() 不是同一件事。 LAST_INSERT_ID 的文档也值得一读。

【讨论】:

啊,好吧。我的印象是.lastrowid 调用了LAST_INSERT_ID 以获取最后插入的ID。我肯定检查了AUTO_INCREMENT 列(我更新了我的问题以反映TOOLS 表的定义)。这是超级好的信息。谢谢!但是,在调用存储过程的情况下,我如何得到这个lastrowid?我只需要在我的存储过程中调用SELECT LAST_INSERT_ID 吗? @Blairg23:IIRC,这还不够;这只是获取存储过程中的值。阅读帮助;它解释说你必须实际调用LAST_INSERT_ID(expr),并带有一个参数,才能获得一个值。所以我认为SELECT LAST_INSERT_ID(LAST_INSERT_ID()) 会起作用,尽管看起来很愚蠢。但是对于这种情况,通常的解决方案是使用存储的 函数 而不是存储过程,并以这种方式返回 LAST_INSERTED_ID 值。 从 MySQL 中,我可以调用 SELECT LAST_INSERT_ID() 并且它运行良好。我不确定他们想要expr 什么,但也许他们正在谈论特定的表格或其他东西。 我只是希望有一种方法可以在 MySQL 之外,从光标对象开始。 @Blairg23:您似乎只是在黑暗中刺痛,以避免阅读几页文档。当您使用表达式调用 LAST_INSERT_ID 时,它会将最后一个插入 ID 设置为该表达式的值。这也迫使mysql_insert_id 被更新。与插入具有AUTO_INCREMENT 列的行不同,只有在直接INSERT 语句(而不是存储过程调用)中完成时才会强制更新mysql_insert_id

以上是关于Python mysql.connector cursor.lastrowid 总是返回 0的主要内容,如果未能解决你的问题,请参考以下文章

python mysql connector

使用 Python mysql.connector 远程连接 MySQL

MySQL Connector/Python 开发者指南

python3-连接MySQL(mysql.connector与MySQLdb区别)

在 mysql-connector-python 中结束连接池

使用 python 库 mysql.connector 将 csv 插入 MySQL 数据库