Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use RETURNING for query.update() with sqlalchemy

Tags:

sqlalchemy

I want to specify the return values for a specific update in sqlalchemy.

The documentation of the underlying update statement (sqlalchemy.sql.expression.update) says it accepts a "returning" argument and the docs for the query object state that query.update() accepts a dictionary "update_args" which will be passed as the arguments to the query statement.

Therefore my code looks like this:

session.query(
  ItemClass
).update(
  {ItemClass.value: value_a},
  synchronize_session='fetch',
  update_args={
    'returning': (ItemClass.id,)
  }
)

However, this does not seem to work. It just returns the regular integer.

My question is now: Am I doing something wrong or is this simply not possible with a query object and I need to manually construct statements or write raw sql?

like image 564
user3688217 Avatar asked Aug 23 '17 14:08

user3688217


People also ask

How do I update data in SQLAlchemy?

Update table elements in SQLAlchemy. Get the books to table from the Metadata object initialized while connecting to the database. Pass the update query to the execute() function and get all the results using fetchall() function. Use a for loop to iterate through the results.

What is returned by SQLAlchemy query?

It returns an instance based on the given primary key identifier providing direct access to the identity map of the owning Session. It creates a SQL JOIN against this Query object's criterion and apply generatively, returning the newly resulting Query. It returns exactly one result or raise an exception.

What is _sa_instance_state in SQLAlchemy?

_sa_instance_state is a non-database-persisted value used by SQLAlchemy internally (it refers to the InstanceState for the instance. While not directly relevant to this section, if we want to get at it, we should use the inspect() function to access it).

What is SQLAlchemy refresh?

refresh() to immediately get an up-to-date version of the object, even if the session already queried the object earlier.


2 Answers

The full solution that worked for me was to use the SQLAlchemy table object directly.

You can get that table object and the columns from your model easily by doing

table = Model.__table__
columns = table.columns

Then with this table object, I can replicate what you did in the question:

from your_settings import db

update_statement = table.update().returning(table.id)\
    .where(columns.column_name=value_one)\
    .values(column_name='New column name')
result = db.session.execute(update_statement)

tuple_of_results = result.fetchall()

db.session.commit()

The tuple_of_results variable would contain a tuple of the results. Note that you would have to run db.session.commit() in order to persist the changes to the database as you it is currently running within a transaction.

You could perform an update based on the current value of a column by doing something like:

update_statement = table.update().returning(table.id)\
    .where(columns.column_name=value_one)\
    .values(like_count=table_columns.like_count+1)

This would increment our numeric like_count column by one.

Hope this was helpful.

like image 57
Chidiebere Avatar answered Sep 20 '22 11:09

Chidiebere


Here's a snippet from the SQLAlchemy documentation:

# UPDATE..RETURNING
result = table.update().returning(table.c.col1, table.c.col2).\
    where(table.c.name=='foo').values(name='bar')
print result.fetchall()
like image 44
djkern Avatar answered Sep 20 '22 11:09

djkern