使用mssql 0.6迁移中的sqlalchemy日期类型

发布于 2024-09-05 08:39:24 字数 2758 浏览 4 评论 0原文

我在 linux ubuntu 10.04 上通过 pyodbc、FreeTDS odbc 驱动程序连接到 mssql 服务器。

Sqlalchemy 0.5 使用 DATETIME 作为 sqlalchemy.Date() 字段。

现在Sqlalchemy 0.6使用DATE,但是sql server 2000没有DATE类型。如何使 DATETIME 成为 sqlalchemy 0.6 mssql+pyodbc 方言上 sqlalchemy.Date() 的默认值?

我想尽可能保持干净。

这是重现问题的代码:

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' ()

I'm connection to mssql server through pyodbc, via FreeTDS odbc driver, on linux ubuntu 10.04.

Sqlalchemy 0.5 uses DATETIME for sqlalchemy.Date() fields.

Now Sqlalchemy 0.6 uses DATE, but sql server 2000 doesn't have a DATE type. How can I make DATETIME be the default for sqlalchemy.Date() on sqlalchemy 0.6 mssql+pyodbc dialect?

I'd like to keep it as clean as possible.

Here's code to reproduce the issue:

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()

And here is the traceback I'm getting:

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' ()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

嘿咻 2024-09-12 08:39:24

这种情况应该由 sqlalchemy 妥善处理。
请参阅 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(...)方法。

This situation is supposed to be properly handled by sqlalchemy.
See MS SQL - Date / Time Handling.

You can also this the extract of the implementation that handles this (see 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_)

My suggestion is to debug your code and check if this MSTypeCompiler is used and if you hit the visit_date(...) method.

下壹個目標 2024-09-12 08:39:24

我明白了 - 我的配置错误。

事实证明,您必须配置 freetds 才能使其使用 TDS 协议的 7.0 或 8.0 版本。默认情况下,它使用 4.2,这在查询 MS SQL Server 版本时会产生奇怪的结果,导致 SQLAlchemy 出现令人困惑的行为,正如我在问题中所述。

我在 freetds.conf 文件上正确设置了它,但该文件未被读取,因为只有当您使用文件中定义的 DSN 时才会解析它,并且我使用连接字符串作为在问题的例子中。

按照此处所述设置变量TDSVER解决了该问题。

I got it - my configuration was wrong.

Turns out that you have to configure freetds to make it use the version 7.0 or 8.0 of the TDS protocol. By default it uses 4.2, which yields weird results when querying for MS SQL Server version, leading SQLAlchemy to confusing behavior, as I described in my question.

I had it correctly set on the freetds.conf file, but this file was not being read, because it is only parsed when you use a DSN defined in the file, and I was using a connection string as in the example in the question.

Setting the variable TDSVER as described here solved the issue.

春庭雪 2024-09-12 08:39:24

你的迁移进展如何!!

我和使用 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)

How are you doing migrations!!?

I'm in the same boat with using mssqlsucks.
here's my solution.

config

SQLALCHEMY_DATABASE_URI = 'mssql+pyodbc://dashboarddata'
SQLALCHEMY_MIGRATE_REPO = os.path.join(basedir, 'db_repository')

my init.py (where's the underbars?)

I was having so many encoding problems, i ended up doing this, and it seems to work. I'd love to see what you finally ended up doing.

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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文