2012-02-22 154 views
3

我試圖使一個模型的自定義原始查詢和我得到這個錯誤:問題Django的原始查詢參數

DatabaseError: error de sintaxis en o cerca de «E'positions_statusrecord'» LINE 1: SELECT id FROM E'positions_statusrecord' WHERE "type"=E'Leav...

這裏是原始查詢我想要使用(這是一個管理方法):

def get_status_ids(self, model): 
    """ 
    This query returns the latest statuses ids for each entry 
    of "model" in StatusRecord. 
    """ 
    db_table = self.model._meta.db_table 
    model_type = model.get_status_type() 

    raw_query = (
     "SELECT id " 
     "FROM %s " 
     "WHERE \"type\"=%s AND " 
     "(identifier,date_time) IN " 
       "(" 
          "SELECT identifier, Max(date_time) " 
          "FROM %s " 
          "WHERE \"type\"=%s " 
          "GROUP BY identifier" 
       ")" 
    ) 

    params = (db_table, model_type, db_table, model_type,) 
    return self.raw(raw_query, params) 

我試圖用一個簡單的查詢(只是一個SELECT ... FROM ..),並有同樣的問題。似乎原始查詢不能使用參數完成FROM部分。

我是對的嗎?還是我犯了一個錯誤,我沒有找到它?

我使用的是PostgreSQL 8.4.10,django 1.3和python 2.6。

我搜索了有關原始查詢參數的信息,看看是否有一些禁止格式化選項,但我沒有找到任何幫助我的東西。

有誰知道是什麼原因導致了這個錯誤?

回答

2

It seems to be that raw queries couldn't have the "FROM" part completed with a parameter.

是的,ORM會引用字符串參數使其成爲... FROM 'some_table' ...

由於db_table參數是可信的(不是源自用戶輸入),你可以這樣做:

raw_query = (
    "SELECT id " 
    "FROM %s " 
    "WHERE \"type\"=%%s AND " 
    "(identifier,date_time) IN " 
      "(" 
         "SELECT identifier, Max(date_time) " 
         "FROM %s " 
         "WHERE \"type\"=%%s " 
         "GROUP BY identifier" 
      ")" 
) % (db_table, db_table) 
return self.raw(raw_query, (model_type, model_type)) 

由於Django Aggregation can be used in filters,也許你可以得到相同的結果,而不是訴諸原始SQL(看起來也是in lookup example)。

看看您是否可以用QuerySet.extra()替換raw(),並用EXISTS替換SQL IN

+0

感謝您的快速回答!我認爲總是建議將參數傳遞給「params」參數中的原始查詢。我是安全問題的新手,所以我一直試圖以這種方式使用它。但在這種情況下,這是值得信賴的投入。 關於「EXISTS」問題,我想我以前做過,但換個方式說,我有一些性能問題。如果我是對的,那個查詢會爲表中的每個條目創建一個子查詢,並且該表中有很多條目(超過2000個)。雖然我認爲我已經做到了,但我會再試一次。非常感謝你! – marianobianchi 2012-02-23 03:11:53

+0

@marianobianchi:2000條目相當小,你可能看不到'IN'和'EXISTS'之間的區別。 – 2012-02-23 13:08:22