2013-03-18 62 views
2

串請看下錶:SQLAlchemy的日期作爲原始SQL

class Employee(Base): 
    __tablename__ = "t_employee" 

    id = Column(Integer(20), Sequence('%s_id_seq' % __tablename__), primary_key=True) 
    first_name = Column(String(30)) 
    last_name = Column(String(30)) 
    email = Column(String(50)) 
    start_date = Column(Date, default=datetime.now) 
    end_date = Column(Date) 

如何選擇使用字符串而非日期在SQLAlchemy的一個原始的SQL?在MySQL,但不是在甲骨文以下工作:

session.query(Employee).\ 
    filter("end_date IS NULL OR end_date>='%s'" % datetime.now()).all() 

最好的情況是,如果我可以使用字符串或日期(互換),只要與日期或日期時間列處理(我已經試過TypeDecorator無濟於事)

請注意,這個問題是指 SQL(我知道這是可以使用謂詞來完成)...

回答

7

不要使用字符串格式化不插入值到SQL。在datetime對象的情況下,默認字符串格式恰好適用於MySQL,但這只是偶然和運氣。

在這種情況下,不要使用原始SQL,並有SQLAlchemy的翻譯DateTime對象的東西后端數據庫瞭解你:

from sqlalchemy import or_ 

session.query(Employee).filter(
    or_(Employee.end_date == None, Employee.end_date >= datetime.now()) 
).all() 

即使使用原始的SQL語句時,我不得不SQLAlchemy的生成SQL並使用綁定參數:

from sqlalchemy.sql.expression import bindparam, column 
from sqlalchemy.types import DateTime 
from sqlalchemy import or_ 

dtnow = bindparam('dtnow', datetime.now(), DateTime) 
end_date = column('enddate', DateTime) 

session.query(Employee).\ 
    filter(or_(end_date == None, end_date >= dtnow)).all() 

該過濾器表達變成正確轉義爲SQL數據庫後端,後端的任何可能。當沒有後端被設置時,表達式變爲:

>>> str(or_(end_date == None, end_date >= dtnow)) 
'enddate IS NULL OR enddate >= :dtnow' 

和執行時datetime.now()值將被傳遞在作爲SQL參數到後端數據庫光標。

不得已是到text() type使用:

from sqlalchemy.sql.expression import bindparam, text 

dtnow = bindparam('dtnow', datetime.now(), DateTime) 
session.query(Employee).\ 
    filter(text('end_date is NULL or end_date >= :dtnow', bindparams=[dtnow])).all() 

我會以其他方式避免混合原料SQL和SQLAlchemy的ORM乾脆。直接使用原始的SQL只與數據庫連接:

conn = session.connection() 
conn.execute(text('SELECT * FROM t_employee WHERE end_date IS NULL OR end_date>=:dtnow'), 
    dtnow=datetime.now()) 
+0

正如我所說的,我知道這可以用謂詞來完成,而且我也知道,這是最好的方式,但我的問題是關於原始SQL – Ofir 2013-03-19 14:09:06

+0

@Ofir:不要混合原始SQL和聲明性語句。如果您需要使用原始SQL,請使用連接'.execute()'方法並使用SQL參數。 – 2013-03-19 14:11:54

+0

你能舉個例子嗎? 10X。 – Ofir 2013-03-20 15:22:34