2013-12-19 6 views
2

У меня есть sqlalchemy core bulk update query, который мне нужно программно передать имя столбца, который должен быть обновлен.Как передать имя столбца в качестве параметра в 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, чтобы его распознать?

EDIT: Окончательный скрипт

Благодаря @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' использует именованные аргументы типа'.values ​​(column_to_update = value) 'где' column_to_update' - это фактическое имя столбца, а не переменная, содержащая имя столбца. Если вам нужно, чтобы он был динамическим, используйте нотацию '** kwargs':' .values ​​(** {'column_to_update': значение}) ' –

Смежные вопросы