<p>如果您非常确定需要动态指定列名,则应该使用能够安全地指定列名的库(并抱怨错误的地方)。SQLAlchemy在这方面非常擅长。</p>
<pre><code>>>> import sqlalchemy
>>> from sqlalchemy import *
>>> metadata = MetaData()
>>> dynamic_column = "cow"
>>> foo_table = Table('foo', metadata,
... Column(dynamic_column, Integer))
>>>
</code></pre>
<p><code>foo_table</code>现在<em>表示带有动态模式的表,但是您只能在实际数据库连接的上下文中使用它(以便sqlalchemy知道方言,以及如何处理生成的sql)。</p>
<pre><code>>>> metadata.bind = create_engine('sqlite:///:memory:', echo=True)
</code></pre>
<p>然后可以发出<code>CREATE TABLE ...</code>。使用<code>echo=True</code>,sqlalchemy将<em>log</em>生成的sql,但通常,sqlalchemy会特意让生成的sql不受您的控制(以免您考虑将其用于邪恶的目的)。</p>
<pre><code>>>> 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
>>>
</code></pre>
<p>是的,sqlalchemy将处理任何需要特殊处理的列名,比如列名是sql保留字时</p>
<pre><code>>>> 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
>>>
</code></pre>
<p>也能让你免于可能的恶行:</p>
<pre><code>>>> 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
>>>
</code></pre>
<p>(显然,有些奇怪的东西在sqlite中是完全合法的标识符)</p>