【问题标题】:Sqlalchemy query parameters are not inserted未插入 Sqlalchemy 查询参数
【发布时间】:2014-05-16 18:35:25
【问题描述】:

我使用 SQLAlchemy 声明式来处理 MySQL。

from sqlalchemy import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relation, sessionmaker
import datetime

engine = create_engine('mysql+mysqldb://root:mypass@localhost/somedb')

Base = declarative_base()
Base.metadata.bind = engine
DBSession = sessionmaker(bind=engine)
session = DBSession()

class Item(Base):
    __tablename__ = 'item'
    id = Column(Integer, primary_key=True)
    dt = Column(DateTime)
    title = Column(UnicodeText)

Base.metadata.create_all(engine)

i = Item()
i.dt = datetime.datetime.now()
i.title = "hello world"
session.add(i)
session.commit()

此代码在session.commit() 上引发异常:

sqlalchemy.exc.ProgrammingError: (ProgrammingError) (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '%s, %s)' at line 1") b'INSERT INTO item (dt, title) VALUES (%s, %s)' (datetime.datetime(2014, 5, 16, 20, 58, 7, 729245), 'hello world')

异常的完整堆栈跟踪在帖子的末尾。

我发现参数没有正确插入到查询字符串中。有一行query = query.format( *db.literal(args) ) in the file MySQLdb/cursors.py, on the line 163query 变量是一个字符串。 string.format 函数接受替换字段,例如 {}{1}{23},而不是 %s。但是查询变量中的替换字段是%s

因此,参数没有被插入到查询中。

我可以通过更改sqlalchemy/sql/compiler.py 文件,变量BIND_TEMPLATES 来解决这个问题。我已将'format': "%%s" 更改为'format': "{}"

但我清楚地知道人们成功使用 sqlalchemy 没有这个错误。问题的真正原因是什么?也许我安装了一些不兼容的版本?

我在 Windows 7 x64 上使用 Python 3.4, mysql连接器:MySQL_python-1.2.3-py3.4-win-amd64.egg

异常的完整堆栈跟踪:

Traceback (most recent call last):
  File "C:\Program Files (x86)\JetBrains\PyCharm Community Edition 3.1.3\helpers\pydev\pydevd.py", line 1539, in <module>
    debugger.run(setup['file'], None, None)
  File "C:\Program Files (x86)\JetBrains\PyCharm Community Edition 3.1.3\helpers\pydev\pydevd.py", line 1150, in run
    pydev_imports.execfile(file, globals, locals) #execute the script
  File "C:\Program Files (x86)\JetBrains\PyCharm Community Edition 3.1.3\helpers\pydev\_pydev_execfile.py", line 37, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc) #execute the script
  File "C:/Work/midmay/midmay.parser/scripts/test.py", line 30, in <module>
    session.commit()
  File "C:\Python34\lib\site-packages\sqlalchemy\orm\session.py", line 765, in commit
    self.transaction.commit()
  File "C:\Python34\lib\site-packages\sqlalchemy\orm\session.py", line 370, in commit
    self._prepare_impl()
  File "C:\Python34\lib\site-packages\sqlalchemy\orm\session.py", line 350, in _prepare_impl
    self.session.flush()
  File "C:\Python34\lib\site-packages\sqlalchemy\orm\session.py", line 1903, in flush
    self._flush(objects)
  File "C:\Python34\lib\site-packages\sqlalchemy\orm\session.py", line 2021, in _flush
    transaction.rollback(_capture_exception=True)
  File "C:\Python34\lib\site-packages\sqlalchemy\util\langhelpers.py", line 57, in __exit__
    compat.reraise(exc_type, exc_value, exc_tb)
  File "C:\Python34\lib\site-packages\sqlalchemy\util\compat.py", line 168, in reraise
    raise value
  File "C:\Python34\lib\site-packages\sqlalchemy\orm\session.py", line 1985, in _flush
    flush_context.execute()
  File "C:\Python34\lib\site-packages\sqlalchemy\orm\unitofwork.py", line 370, in execute
    rec.execute(self)
  File "C:\Python34\lib\site-packages\sqlalchemy\orm\unitofwork.py", line 523, in execute
    uow
  File "C:\Python34\lib\site-packages\sqlalchemy\orm\persistence.py", line 64, in save_obj
    mapper, table, insert)
  File "C:\Python34\lib\site-packages\sqlalchemy\orm\persistence.py", line 594, in _emit_insert_statements
    execute(statement, params)
  File "C:\Python34\lib\site-packages\sqlalchemy\engine\base.py", line 720, in execute
    return meth(self, multiparams, params)
  File "C:\Python34\lib\site-packages\sqlalchemy\sql\elements.py", line 317, in _execute_on_connection
    return connection._execute_clauseelement(self, multiparams, params)
  File "C:\Python34\lib\site-packages\sqlalchemy\engine\base.py", line 817, in _execute_clauseelement
    compiled_sql, distilled_params
  File "C:\Python34\lib\site-packages\sqlalchemy\engine\base.py", line 947, in _execute_context
    context)
  File "C:\Python34\lib\site-packages\sqlalchemy\engine\base.py", line 1108, in _handle_dbapi_exception
    exc_info
  File "C:\Python34\lib\site-packages\sqlalchemy\util\compat.py", line 174, in raise_from_cause
    reraise(type(exception), exception, tb=exc_tb, cause=exc_value)
  File "C:\Python34\lib\site-packages\sqlalchemy\util\compat.py", line 167, in reraise
    raise value.with_traceback(tb)
  File "C:\Python34\lib\site-packages\sqlalchemy\engine\base.py", line 940, in _execute_context
    context)
  File "C:\Python34\lib\site-packages\sqlalchemy\engine\default.py", line 435, in do_execute
    cursor.execute(statement, parameters)
  File "C:\Python34\lib\site-packages\mysql_python-1.2.3-py3.4-win-amd64.egg\MySQLdb\cursors.py", line 184, in execute
    self.errorhandler(self, exc, value)
  File "C:\Python34\lib\site-packages\mysql_python-1.2.3-py3.4-win-amd64.egg\MySQLdb\connections.py", line 37, in defaulterrorhandler
    raise errorvalue
  File "C:\Python34\lib\site-packages\mysql_python-1.2.3-py3.4-win-amd64.egg\MySQLdb\cursors.py", line 171, in execute
    r = self._query(query)
  File "C:\Python34\lib\site-packages\mysql_python-1.2.3-py3.4-win-amd64.egg\MySQLdb\cursors.py", line 330, in _query
    rowcount = self._do_query(q)
  File "C:\Python34\lib\site-packages\mysql_python-1.2.3-py3.4-win-amd64.egg\MySQLdb\cursors.py", line 294, in _do_query
    db.query(q)
sqlalchemy.exc.ProgrammingError: (ProgrammingError) (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '%s, %s)' at line 1") b'INSERT INTO item (dt, title) VALUES (%s, %s)' (datetime.datetime(2014, 5, 16, 20, 58, 7, 729245), 'hello world')

【问题讨论】:

    标签: python mysql sqlalchemy


    【解决方案1】:

    尝试添加__table_args__ = {}。这对我有用:

    from sqlalchemy import *
    from sqlalchemy.ext.declarative import declarative_base, DeferredReflection
    from sqlalchemy.orm import relation, relationship
    
    DeclarativeBase = declarative_base(cls=DeferredReflection)
    
    class MyItem(DeclarativeBase):
        __tablename__ = 'myitem'
        __table_args__ = {}
    

    更新:我已经使用 Python 2.7(x64,在 Linux 上)按原样运行您的代码(当然除了更改引擎的 mysql url 字符串)并且它运行没有任何问题(它创建了表并插入了“hello world”进去)。依赖:

    MySQL-python==1.2.5
    SQLAlchemy==0.9.2
    

    仔细阅读您的帖子,我发现您使用的是 Python 3.4。 http://docs.sqlalchemy.org/en/rel_0_9/changelog/migration_09.html 状态:

    “现在,所有 SQLAlchemy 模块和单元测试都可以与 2.6 以后的任何 Python 解释器(包括 3.1 和 3.2 解释器)同样良好地解释。”

    这并没有明确提及 3.3 和 3.4。您可能在 SA 中遇到了一个错误,或者它还没有针对 3.4 进行更新。我建议安装 2.7(它们应该能够在单个系统上共存),将 virtualenv 用于 2.7,安装 deps 并重新运行您的代码。

    问题的另一个可能来源是 3.4 的 MySQL 驱动程序。我很难过这样说,但是 Python 3.* 下对 MySQL 的支持严重不足:我工作场所的团队发现驱动程序不仅泄漏,而且在高负载下无法处理许多连接。在修复驱动程序之前,您可能会更好地使用 2.7。那,或者只是将 Postgres 更改为 db。

    【讨论】:

    • __table_args__ = {} 不能解决问题。添加列名也不行。
    【解决方案2】:

    我找到了解决办法。也许它不是最好的,也不适合所有人。但在这里。 解决方案是安装 Mysql Connector 而不是 MySQLDb 并将连接字符串从 mysql+mysqldb://root:mypass@localhost/somedb 更改为 mysql+connector://root:mypass@localhost/somedb

    如果你是 Windows 用户(和我一样),并且你有这个问题:"Cannot open include file: 'config-win.h': No such file or directory" while installing mysql-python,那么你可以将 Python 版本从 3.4 降级到 3.3,并从这里下载用于 python 3.3 的预编译 Mysql 连接器:@ 987654322@

    它对我有用。谢谢。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-26
      • 1970-01-01
      相关资源
      最近更新 更多