Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I bind a list to a parameter in a custom query in SQLAlchemy?

I am using this SQL for performance reasons:

 sql_tmpl = """delete from Data where id_data in (:iddata) """  params = {                     'iddata':[1, 2,3 4],                     }   # 'session' is a session object from SQLAlchemy  self.session.execute(text(sql_tmpl), params) 

However, I got an exception:

NotSupportedError: (NotSupportedError) ('Python type list not supported.  param=1', 'HY097') 

Is there a workaround that can allow me to bind a list to the parameter of the 'in' clause?

like image 795
Anthony Kong Avatar asked Nov 02 '12 06:11

Anthony Kong


People also ask

What is all () in SQLAlchemy?

method sqlalchemy.orm.Query. all() Return the results represented by this Query as a list. This results in an execution of the underlying SQL statement. The Query object, when asked to return either a sequence or iterator that consists of full ORM-mapped entities, will deduplicate entries based on primary key.

What is subquery in SQLAlchemy?

The grouping is done with the group_by() query method, which takes the column to use for the grouping as an argument, same as the GROUP BY counterpart in SQL. The statement ends by calling subquery() , which tells SQLAlchemy that our intention for this query is to use it inside a bigger query instead of on its own.

How do I select data in SQLAlchemy?

To select data from a table via SQLAlchemy, you need to build a representation of that table within SQLAlchemy. If Jupyter Notebook's response speed is any indication, that representation isn't filled in (with data from your existing database) until the query is executed. You need Table to build a table.


2 Answers

A new approach to this problem that works for any database (not just relying on psycopg2's type adaptation) uses expanding bind parameters:

sql_tmpl = """delete from Data where id_data in :iddata""" params = { 'iddata': [1, 2, 3, 4], } # session is a session object from sqlalchemy t = text(sql_tmpl) t = t.bindparams(bindparam('iddata', expanding=True)) self.session.execute(t, params) 
like image 105
Jason Damiani Avatar answered Oct 05 '22 19:10

Jason Damiani


psycopg2 now supports type adaptation, which allows, among other things, the ability to pass a list into a single parameterized value in the query. This also works in SQLAlchemy, at the very least for raw-SQL-esque queries to a PostgreSQL database (I don't have access to other database types, so I don't know if sqlalchemy will respect this convention for other databases, but my inclinationcitation needed is that it will work).

some_ids = [1, 2, 3, 4] query = "SELECT * FROM my_table t WHERE t.id = ANY(:ids);" conn.execute(sqlalchemy.text(query), ids=some_ids) ## runs just fine 

I found that without the wrapper call to sqlalchemy.text, it gave a ProgrammingError: syntax error at or near ":".

like image 29
dwanderson Avatar answered Oct 05 '22 21:10

dwanderson