Python DB-API:如何处理不同的参数?

Tam*_*más 13 python sql python-db-api

我正在实现一个Python本体类,它使用数据库后端来存储和查询本体.数据库模式是固定的(事先指定),但我不知道正在使用什么类型的数据库引擎.但是,我可以依赖数据库引擎的Python接口使用Python DB-API 2.0(PEP 249)的事实.一个直截了当的想法是让用户将符合PEP 249的Connection对象传递给我的本体的构造函数,然后使用各种硬编码的SQL查询来查询数据库:

class Ontology(object):
    def __init__(self, connection):
        self.connection = connection

    def get_term(self, term_id):
        cursor = self.connection.cursor()
        query = "SELECT * FROM term WHERE id = %s"
        cursor.execute(query, (term_id, ))
        [...]
Run Code Online (Sandbox Code Playgroud)

我的问题是允许不同的数据库后端支持查询中的不同参数标记,由paramstyle后端模块的属性定义.例如,如果paramstyle = 'qmark',接口支持问号样式(SELECT * FROM term WHERE id = ?); paramstyle = 'numeric'表示数字,位置样式(SELECT * FROM term WHERE id = :1); paramstyle = 'format'表示ANSI C格式的字符串样式(SELECT * FROM term WHERE id = %s).如果我想让我的类能够处理不同的数据库后端,似乎我必须为所有参数标记样式做准备.这似乎打败了我的通用DB API的整个目的,因为我不能使用相同的参数化查询与不同的数据库后端.

有没有办法绕过它,如果是这样,最好的办法是什么?DB API没有指定是否存在通用转义函数,我可以使用该函数清理查询中的值,因此手动执行转义不是一种选择.我不想通过使用更高级别的抽象(例如SQLAlchemy)为项目添加额外的依赖项.

Bru*_*uno 6

  • 这个Python配方可能会有所帮助.它引入了一个额外的抽象层来包装自己Param类中的参数.

  • PyDal项目也可能会接近你想达到什么目的" PyDal能够与符合DBAPI 2.0的任何模块使用相同的paramstyle和时间类型此外,paramstyles和时间类型是可配置的. "


Ste*_*ven 2

严格来说,问题不是由 DB API 允许这样做引起的,而是由不同的数据库使用不同的 SQL 语法引起的。DB API 模块将精确的查询字符串连同参数一起传递到数据库。“解析”参数标记是由数据库本身完成的,而不是由 DB API 模块完成的。

这意味着如果你想解决这个问题,你必须引入一些更高级别的抽象。如果您不想添加额外的依赖项,则必须自己添加。但是,您可以尝试根据后端模块的 paramstyle 将查询字符串中的参数标记动态替换为所需的参数标记,而不是手动转义和替换。然后将带有参数标记的字符串传递给数据库。例如,您可以在任何地方使用“%s”,如果数据库使用“数字”样式,则可以使用 python 字符串替换将“%s”替换为“:1”、“:2”等。 ..

  • “*DB API 模块将精确的查询字符串连同参数一起传递到数据库。*”我认为根本不是这种情况。例如,如果您查看 [PostgreSQL 的网络规范](http://www.postgresql.org/docs/8.4/static/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY),则在使用时,参数查询使用 ` $1`、`$2`、...作为占位符,它们不是任何 [Python paramstyles](http://www.python.org/dev/peps/pep-0249/#paramstyle)。显然,查询字符串在发送之前会以某种方式进行修改,尤其是在使用依赖于字典(带有名称)的参数样式时。 (3认同)