2013-12-19 43 views
2

我有一個sqlalchemy核心批量更新查詢,我需要以編程方式傳遞要更新的列的名稱。如何在SQLAlchemy Core中將列的名稱作爲參數傳遞?

函數看起來如下面每個變量註釋:

def update_columns(table_name, pids, column_to_update): 
    ''' 
    1. table_name: a string denoting the name of the table to be updated 
    2. pid: a list of primary ids 
    3. column_to_update: a string representing the name of the column that will be flagged. Sometimes the name can be is_processed or is_active and several more other columns. I thus need to pass the name as a parameter. 
    ''' 
    for pid in pids: 
     COL_DICT_UPDATE = {} 
     COL_DICT_UPDATE['b_id'] = pid 
     COL_DICT_UPDATE['b_column_to_update'] = True 
     COL_LIST_UPDATE.append(COL_DICT_UPDATE) 

    tbl = Table(table_name, meta, autoload=True, autoload_with=Engine) 
    trans = CONN.begin() 
    stmt = tbl.update().where(tbl.c.id == bindparam('b_id')).values(tbl.c.column_to_update==bindparam('b_column_to_update')) 
    trans.commit() 

table參數被接受並正常工作。

作爲參數傳遞時,column_to_update不起作用。它失敗並出現錯誤raise AttributeError(key) AttributeError: column_to_mark。如果我硬編碼列名稱,查詢運行。

如何通過column_to_update的名稱使SQLAlchemy識別它?

編輯:最終腳本

由於@Paulo,最終的腳本是這樣的:

def update_columns(table_name, pids, column_to_update): 
    for pid in pids: 
     COL_DICT_UPDATE = {} 
     COL_DICT_UPDATE['b_id'] = pid 
     COL_DICT_UPDATE['b_column_to_update'] = True 
     COL_LIST_UPDATE.append(COL_DICT_UPDATE) 

    tbl = Table(table_name, meta, autoload=True, autoload_with=Engine)   
    trans = CONN.begin() 
    stmt = tbl.update().where(
           tbl.c.id == bindparam('b_id') 
          ).values(**{column_to_update: bindparam('b_column_to_update')}) 
    CONN.execute(stmt, COL_LIST_UPDATE) 
    trans.commit() 

回答

2

我不知道如果我明白你想要什麼,你的代碼看起來很不同於我認爲的習慣sqlalchemy(我不批評,只是評論我們可能使用正交代碼樣式)。

如果您想通過文字列作爲一個參數使用:

from sqlalchemy.sql import literal_column 
... 
tbl.update().where(
    tbl.c.id == bindparam('b_id') 
).values(
    tbl.c.column_to_update == literal_column('b_column_to_update') 
) 

如果你想動態設置表達式的右側,使用方法:

tbl.update().where(
    tbl.c.id == bindparam('b_id') 
).values(
    getattr(tbl.c, 'column_to_update') == bindparam('b_column_to_update') 
) 

如果沒有這是不是你想要的,評論答案或改善你的問題,我會盡力幫助。

[更新]

values方法使用命名參數等.values(column_to_update=value)其中column_to_update是實際的列名,而不是一個變量保持的列名。例如:

stmt = users.update().\ 
     where(users.c.id==5).\ 
     values(id=-5) 

注意where使用比較運算符==values使用歸屬運營商=代替 - 前者使用列對象中一個布爾表達式,而後者使用列名作爲關鍵字參數綁定。

如果你需要它是動態的,使用**kwargs符號:.values(**{'column_to_update': value})

,不過也許你想使用的values參數而不是values方法。

+0

因爲批量更新需要此綁定參數,我該如何將'bindparam(b_column_to_mark)'傳遞給查詢? – lukik

+0

第二個選項更多地是我想要的,因爲我已經看到'getattr'獲取列名稱。然而,當我運行它時,出現錯誤'AttributeError:'BinaryExpression'對象和'Comparator'對象都沒有屬性'items'' – lukik

+0

'values'方法使用像''這樣的命名參數。值(column_to_update = value)'其中'column_to_update'是實際的列名稱,而不是包含列名稱的變量。如果你需要它是動態的,使用'** kwargs'符號:'.values(** {'column_to_update':value})' –

相關問題