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?
Solution 1:
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)
Solution 2:
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 ":"
.
Solution 3:
Try it without the parentheses around, :iddata
. That has been working for me.
sql_tmpl = """delete from Data where id_data in :iddata """