Если вы абсолютно уверены, что вам нужно динамически указывать имена столбцов, вам следует использовать библиотеку, которая может сделать это безопасно (и жалуется на неправильные вещи). 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 будет log сгенерированным 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)