为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕码人2483693 2019-11-30 10:35:17
在SQLite查询中使用变量值的标准方法是“问号样式”,如下所示:import sqlite3with 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 sqlite3with sqlite3.connect(":memory:") as connection:    connection.execute("CREATE TABLE foo(?)", ("bar",))    # raises sqlite3.OperationalError: near "?": syntax errorsqlite3模块和PEP 249均未提及转义名称或值的功能。大概是为了阻止用户使用字符串来组合他们的查询,但这使我无所适从。什么功能或技术最适合在SQLite中为列或表使用变量名?我强烈希望能够在没有任何其他依赖项的情况下做到这一点,因为我将在自己的包装器中使用它。我在寻找但找不到关于SQLite语法相关部分的清晰完整描述,以用于编写自己的函数。我想确保这对于SQLite允许的任何标识符都适用,因此试错解决方案对我来说还是不确定的。SQLite 用来"引用标识符,但我不确定仅转义标识符就足够了。PHP sqlite_escape_string函数的文档表明,某些二进制数据可能也需要转义,但这可能是PHP库的一个怪癖。
查看完整描述

3 回答

?
饮歌长啸

TA贡献1951条经验 获得超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中完全是合法的标识符)


查看完整回答
反对 回复 2019-11-30
  • 3 回答
  • 0 关注
  • 1001 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信