使用mssql进行0.6迁移时的sqlalchemy日期类型
我正在通过pyodbc连接到mssql服务器,使用FreeTDS的odbc驱动,在Linux Ubuntu 10.04上。
Sqlalchemy 0.5版本使用DATETIME
来表示sqlalchemy.Date()
字段。
现在Sqlalchemy 0.6版本使用DATE
,但是sql server 2000没有DATE
这种类型。我该如何让DATETIME
成为Sqlalchemy 0.6版本中sqlalchemy.Date()
的默认类型,特别是在mssql+pyodbc
的情况下呢?
我希望保持代码尽可能简洁。
下面是重现这个问题的代码:
import sqlalchemy
from sqlalchemy import Table, Column, MetaData, Date, Integer, create_engine
engine = create_engine(
'mssql+pyodbc://sa:sa@myserver/mydb?driver=FreeTDS')
m = MetaData(bind=engine)
tb = sqlalchemy.Table('test_date', m,
Column('id', Integer, primary_key=True),
Column('dt', Date())
)
tb.create()
这是我遇到的错误信息:
Traceback (most recent call last):
File "/tmp/teste.py", line 15, in <module>
tb.create()
File "/home/nosklo/.local/lib/python2.6/site-packages/sqlalchemy/schema.py", line 428, in create
bind.create(self, checkfirst=checkfirst)
File "/home/nosklo/.local/lib/python2.6/site-packages/sqlalchemy/engine/base.py", line 1647, in create
connection=connection, **kwargs)
File "/home/nosklo/.local/lib/python2.6/site-packages/sqlalchemy/engine/base.py", line 1682, in _run_visitor
**kwargs).traverse_single(element)
File "/home/nosklo/.local/lib/python2.6/site-packages/sqlalchemy/sql/visitors.py", line 77, in traverse_single
return meth(obj, **kw)
File "/home/nosklo/.local/lib/python2.6/site-packages/sqlalchemy/engine/ddl.py", line 58, in visit_table
self.connection.execute(schema.CreateTable(table))
File "/home/nosklo/.local/lib/python2.6/site-packages/sqlalchemy/engine/base.py", line 1157, in execute
params)
File "/home/nosklo/.local/lib/python2.6/site-packages/sqlalchemy/engine/base.py", line 1210, in _execute_ddl
return self.__execute_context(context)
File "/home/nosklo/.local/lib/python2.6/site-packages/sqlalchemy/engine/base.py", line 1268, in __execute_context
context.parameters[0], context=context)
File "/home/nosklo/.local/lib/python2.6/site-packages/sqlalchemy/engine/base.py", line 1367, in _cursor_execute
context)
File "/home/nosklo/.local/lib/python2.6/site-packages/sqlalchemy/engine/base.py", line 1360, in _cursor_execute
context)
File "/home/nosklo/.local/lib/python2.6/site-packages/sqlalchemy/engine/default.py", line 277, in do_execute
cursor.execute(statement, parameters)
sqlalchemy.exc.ProgrammingError: (ProgrammingError)
('42000', '[42000] [FreeTDS][SQL Server]Column or parameter #2:
Cannot find data type DATE. (2715)
(SQLExecDirectW)')
'\nCREATE TABLE test_date (\n\tid INTEGER NOT NULL IDENTITY(1,1),
\n\tdt DATE NULL, \n\tPRIMARY KEY (id)\n)\n\n' ()
3 个回答
你们是怎么做迁移的!!?
我也在用mssqlsucks,跟你们一样。
这是我的解决方案。
配置
SQLALCHEMY_DATABASE_URI = 'mssql+pyodbc://dashboarddata'
SQLALCHEMY_MIGRATE_REPO = os.path.join(basedir, 'db_repository')
我的 init.py(下划线在哪里呢?)
我遇到了很多编码问题,最后我做了这个,结果似乎有效。我很想知道你们最后是怎么解决的。
class HackedSQLAlchemy(SQLAlchemy):
def apply_driver_hacks(self, app, info, options):
print "Applying driver hacks"
super(HackedSQLAlchemy, self).apply_driver_hacks(app, info, options)
options["supports_unicode_binds"] = False
# import pdb
# pdb.set_trace()
@app.template_filter('reverse')
def reverse_filter(s):
if s > datetime.date.today():
return 0
else:
return 1
db = HackedSQLAlchemy(app)
这个情况应该由sqlalchemy来妥善处理。你可以查看这个链接了解更多关于MS SQL的日期和时间处理的信息:MS SQL - 日期/时间处理。
你也可以查看处理这个问题的实现部分(见这个链接:mssql\base.py):
def visit_date(self, type_):
if self.dialect.server_version_info < MS_2008_VERSION:
return self.visit_DATETIME(type_)
else:
return self.visit_DATE(type_)
我的建议是调试你的代码,检查一下是否使用了这个 MSTypeCompiler
,并且看看你是否调用了 visit_date(...)
这个方法。
我明白了——我的配置是错的。
原来你需要把freetds配置成使用TDS协议的7.0或8.0版本。默认情况下,它使用的是4.2版本,这样在查询MS SQL Server版本时会出现奇怪的结果,导致SQLAlchemy表现得很混乱,就像我在问题中描述的那样。
我在freetds.conf
文件中设置是正确的,但这个文件没有被读取,因为它只有在使用文件中定义的DSN时才会被解析,而我使用的是连接字符串,就像问题中的例子那样。
按照这里的说明设置TDSVER
变量解决了这个问题。