猿问

如何在Python中转义SQLite表/列名称的字符串?

在SQLite查询中使用变量值的标准方法是“问号样式”,如下所示:


import sqlite3

with sqlite3.connect(":memory:") as connection:

    connection.execute("CREATE TABLE foo(bar)")

    connection.execute("INSERT INTO foo(bar) VALUES (?)", ("cow",))


    print(list(connection.execute("SELECT * from foo")))

    # prints [(u'cow',)]

但是,这仅适用于将值替换为查询。当用于表名或列名时失败:


import sqlite3

with sqlite3.connect(":memory:") as connection:

    connection.execute("CREATE TABLE foo(?)", ("bar",))

    # raises sqlite3.OperationalError: near "?": syntax error

sqlite3模块和PEP 249均未提及转义名称或值的功能。大概是为了阻止用户使用字符串来组合他们的查询,但这使我无所适从。


什么功能或技术最适合在SQLite中为列或表使用变量名?我强烈希望能够在没有任何其他依赖项的情况下做到这一点,因为我将在自己的包装器中使用它。


我在寻找但找不到关于SQLite语法相关部分的清晰完整描述,以用于编写自己的函数。我想确保这对于SQLite允许的任何标识符都适用,因此试错解决方案对我来说还是不确定的。


SQLite 用来"引用标识符,但我不确定仅转义标识符就足够了。PHP sqlite_escape_string函数的文档表明,某些二进制数据可能也需要转义,但这可能是PHP库的一个怪癖。


慕码人2483693
浏览 1002回答 3
3回答

饮歌长啸

如果您确定需要动态指定列名,则应使用可以安全地执行此操作的库(并抱怨错误的地方)。SQLAlchemy非常擅长于此。>>> import sqlalchemy>>> from sqlalchemy import *>>> metadata = MetaData()>>> dynamic_column = "cow">>> foo_table = Table('foo', metadata,...     Column(dynamic_column, Integer))>>> foo_table现在用动态模式表示该表,但是您只能在实际数据库连接的上下文中使用它(以便sqlalchemy知道方言以及如何处理生成的sql)。>>> metadata.bind = create_engine('sqlite:///:memory:', echo=True)然后,您可以发出CREATE TABLE ...。使用时echo=True,sqlalchemy将记录生成的sql,但总的来说,sqlalchemy竭尽全力使生成的sql不受您的控制(除非您考虑将其用于邪恶目的)。>>> foo_table.create()2011-06-28 21:54:54,040 INFO sqlalchemy.engine.base.Engine.0x...2f4c CREATE TABLE foo (    cow INTEGER)2011-06-28 21:54:54,040 INFO sqlalchemy.engine.base.Engine.0x...2f4c ()2011-06-28 21:54:54,041 INFO sqlalchemy.engine.base.Engine.0x...2f4c COMMIT>>> 是的,sqlalchemy将处理需要特殊处理的所有列名,例如当列名是sql保留字时>>> dynamic_column = "order">>> metadata = MetaData()>>> foo_table = Table('foo', metadata,...     Column(dynamic_column, Integer))>>> metadata.bind = create_engine('sqlite:///:memory:', echo=True)>>> foo_table.create()2011-06-28 22:00:56,267 INFO sqlalchemy.engine.base.Engine.0x...aa8c CREATE TABLE foo (    "order" INTEGER)2011-06-28 22:00:56,267 INFO sqlalchemy.engine.base.Engine.0x...aa8c ()2011-06-28 22:00:56,268 INFO sqlalchemy.engine.base.Engine.0x...aa8c COMMIT>>> 并可以避免您遭受不良后果:>>> dynamic_column = "); drop table users; -- the evil bobby tables!">>> metadata = MetaData()>>> foo_table = Table('foo', metadata,...     Column(dynamic_column, Integer))>>> metadata.bind = create_engine('sqlite:///:memory:', echo=True)>>> foo_table.create()2011-06-28 22:04:22,051 INFO sqlalchemy.engine.base.Engine.0x...05ec CREATE TABLE foo (    "); drop table users; -- the evil bobby tables!" INTEGER)2011-06-28 22:04:22,051 INFO sqlalchemy.engine.base.Engine.0x...05ec ()2011-06-28 22:04:22,051 INFO sqlalchemy.engine.base.Engine.0x...05ec COMMIT>>> (显然,一些奇怪的东西在sqlite中完全是合法的标识符)
随时随地看视频慕课网APP

相关分类

Python
我要回答