2014-01-31 26 views
3

我在執行對多個值進行檢查的原始SQL時遇到SQLAlchemy問題。SQLAlchemy WHERE IN單個值(原始SQL)

my_sess.execute(
     "SELECT * FROM table WHERE `key`='rating' AND uid IN :uids", 
     params=dict(uids=some_list) 
    ).fetchall() 

這個查詢有兩種情況,一種可以工作,一種不可以。如果some_list = [1],它會拋出一個SQL錯誤,我在)附近出現語法錯誤。但是如果some_list = [1, 2],查詢成功執行。

爲什麼會發生這種情況的任何原因?

回答

5

不,SQL參數只處理標量值。你必須在這裏生成SQL;如果您需要原始SQL,請使用:

statement = "SELECT * FROM table WHERE `key`='rating' AND uid IN ({})".format(
    ', '.join([':i{}'.format(i) for i in range(len(some_list))])) 

my_sess.execute(
     statement, 
     params={'i{}'.format(i): v for i, v in enumerate(some_list)}) 
    ).fetchall() 

例如生成足夠的參數以保存帶有字符串格式的some_list中的所有值,然後生成匹配參數以填充它們。

更妙的是使用一個literal_column() object做所有的發電爲您提供:

from sqlalchemy.sql import literal_column 

uid_in = literal_column('uid').in_(some_list) 
statement = "SELECT * FROM able WHERE `key`='rating' AND {}".format(uid_in) 

my_sess.execute(
     statement, 
     params={'uid_{}'.format(i): v for i, v in enumerate(some_list)}) 
    ).fetchall() 

但你或許可以只生成使用`sqlalchemy.sql.expression模塊則整個語句,因爲這將使支持多個數據庫方言更容易。

而且,uid_in對象已經擁有對綁定參數的正確值的引用;而不是像上面的str.format()動作那樣將它轉換爲字符串,SQLAlchemy將具有實際對象和相關參數,並且不再需要生成params字典或者

下面應該工作:

from sqlalchemy.sql import table, literal_column, select 

tbl = table('table') 
key_clause = literal_column('key') == 'rating' 
uid_clause = literal_column('uid').in_(some_list) 
my_sess.execute(select('*', key_clause & uid_clause, [tbl])) 

其中sqlalchemy.sql.select()採用列規範(這裏硬編碼爲*),where子句(由兩個分句產生與&生成一個SQL AND條款)和可選擇的列表;在這裏你的一個sqlalchemy.sql.table()價值。

快速演示:

>>> from sqlalchemy.sql import table, literal_column, select 
>>> some_list = ['foo', 'bar'] 
>>> tbl = table('table') 
>>> key_clause = literal_column('key') == 'rating' 
>>> uid_clause = literal_column('uid').in_(some_list) 
>>> print select('*', key_clause & uid_clause, [tbl]) 
SELECT * 
FROM "table" 
WHERE key = :key_1 AND uid IN (:uid_1, :uid_2) 

但所有這一切產生的實際對象樹包含實際值的綁定參數太多,所以my_sess.execute()可以直接訪問這些。

+0

儘管我明白你的答案的作用,並且打印'statement'變量產生了一個有效的SQL,我在調用'execute'方法時得到'AttributeError:'list'對象沒有屬性'keys'。 –

+0

@EduardLuca:啊,我從不使用'session.execute()',它確實只支持命名參數。將更新。 –

+0

@EduardLuca:但是,您真的應該考慮使用SQLAlchemy的核心功能來生成SQL。我敢打賭,它也可以處理「一代人」。 –