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
没有按预期工作的原因是正确的,因为我没有打电话给INSERT
或UPDATE
,而是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 列生成的值…
您还没有运行INSERT
或UPDATE
语句,而是运行了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
列;否则,你一开始就没有任何价值。
另外,请注意,这只是其中一种方式,与您的断言相反,lastrowid
和 LAST_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 远程连接 MySQL
python3-连接MySQL(mysql.connector与MySQLdb区别)