数据库
首页 > 数据库> > python – MySQLdb.cursor.execute无法运行多个查询

python – MySQLdb.cursor.execute无法运行多个查询

作者:互联网

我们尝试将包含多个插入语句的SQL文件作为单个查询运行,但是当任何语句包含错误时,似乎回滚失败.

MySQLd配置:

sql_mode = STRICT_ALL_TABLES
default-storage-engine = innodb

Python代码:

from contextlib import closing
import MySQLdb
database_connection = MySQLdb.connect(host="127.0.0.1", user="root")
with closing(database_connection.cursor()) as cursor:
    database_connection.begin()
    cursor.execute('DROP DATABASE IF EXISTS db_name')
    cursor.execute('CREATE DATABASE db_name')
    cursor.execute('USE db_name')
    cursor.execute('CREATE TABLE table_name(first_field INTEGER)')
with closing(database_connection.cursor()) as cursor:
    try:
        database_connection.begin()
        cursor.execute('USE db_name')
        cursor.execute('INSERT INTO table_name VALUES (1)')
        cursor.execute('INSERT INTO table_name VALUES ("non-integer value")')
        database_connection.commit()
    except Exception as error:
        print("Exception thrown: {0}".format(error))
        database_connection.rollback()
        print("Rolled back")
with closing(database_connection.cursor()) as cursor:
    try:
        database_connection.begin()
        cursor.execute('USE db_name')
        cursor.execute('INSERT INTO table_name VALUES (1); INSERT INTO table_name VALUES ("non-integer value")')
        database_connection.commit()
    except:
        print("Exception thrown: {0}".format(error))
        database_connection.rollback()
        print("Rolled back")

预期结果:“抛出异常”和“回滚”两次打印.

MySQL-python 1.2.4的实际结果:

Exception thrown: (1366, "Incorrect integer value: 'non-integer value' for column 'first_field' at row 1")
Rolled back
Exception thrown: (1366, "Incorrect integer value: 'non-integer value' for column 'first_field' at row 1")
Traceback (most recent call last):
  File "test.py", line 30, in <module>
    print("Rolled back")
  File ".../python-2.7/lib/python2.7/contextlib.py", line 154, in __exit__
    self.thing.close()
  File ".../virtualenv-python-2.7/lib/python2.7/site-packages/MySQLdb/cursors.py", line 100, in close
    while self.nextset(): pass
  File ".../virtualenv-python-2.7/lib/python2.7/site-packages/MySQLdb/cursors.py", line 132, in nextset
    nr = db.next_result()
_mysql_exceptions.OperationalError: (1366, "Incorrect integer value: 'non-integer value' for column 'first_field' at row 1")

是什么赋予了?我们是否真的必须解析SQL以拆分语句(包含所有需要的转义和引用处理)以在多次执行中运行它们?

解决方法:

像所有Python DB-API 2.0 implementations一样,cursor.execute()方法只设计了一个语句,因为它保证了之后光标的状态.

请改用cursor.executemany() method.请注意,as per the DB-API 2.0 specification

Use of this method for an operation which produces one or more result sets constitutes undefined behavior, and the implementation is permitted (but not required) to raise an exception when it detects that a result set has been created by an invocation of the operation.

将它用于多个INSERT语句应该没问题:

cursor.executemany('INSERT INTO table_name VALUES (%s)',
    [(1,), ("non-integer value",)]
)

如果你需要从脚本中执行一系列不同的语句,那么在大多数情况下你可以将语句分开;并将每个语句分别提供给cursor.execute().

标签:python,mysql,mysql-python
来源: https://codeday.me/bug/20190929/1831387.html