SQLAlchemy error: “argument formats can't be mixed” when inputting variables

我是研究僧i 提交于 2019-12-30 09:58:25

问题


I have a Python script that runs a pgSQL file through SQLAlchemy's connection.execute function. Here's the block of code in Python:

results = pg_conn.execute(sql_cmd, beg_date = datetime.date(2015,4,1), end_date = datetime.date(2015,4,30))

And here's one of the areas where the variable gets inputted in my SQL:

WHERE
    (   dv.date >= %(beg_date)s AND
        dv.date <= %(end_date)s)

When I run this, I get a cryptic python error:

sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) argument formats can't be mixed

…followed by a huge dump of the offending SQL query. I've run this exact code with the same variable convention before. Why isn't it working this time?


回答1:


I encountered a similar issue as Nikhil. I have a query with LIKE clauses which worked until I modified it to include a bind variable, at which point I received the following error:

DatabaseError: Execution failed on sql '...': argument formats can't be mixed

The solution is not to give up on the LIKE clause. That would be pretty crazy if psycopg2 simply didn't permit LIKE clauses. Rather, we can escape the literal % with %%. For example, the following query:

SELECT *
FROM people
WHERE start_date > %(beg_date)s
AND name LIKE 'John%';

would need to be modified to:

SELECT *
FROM people
WHERE start_date > %(beg_date)s
AND name LIKE 'John%%';

More details in the pscopg2 docs: http://initd.org/psycopg/docs/usage.html#passing-parameters-to-sql-queries




回答2:


As it turned out, I had used a SQL LIKE operator in the new SQL query, and the % operand was messing with Python's escaping capability. For instance:

    dv.device LIKE 'iPhone%' or
    dv.device LIKE '%Phone'

Another answer offered a way to un-escape and re-escape, which I felt would add unnecessary complexity to otherwise simple code. Instead, I used pgSQL's ability to handle regex to modify the SQL query itself. This changed the above portion of the query to:

        dv.device ~ E'iPhone.*' or
        dv.device ~ E'.*Phone$'

So for others: you may need to change your LIKE operators to regex '~' to get it to work. Just remember that it'll be WAY slower for large queries. (More info here.)



来源:https://stackoverflow.com/questions/30357004/sqlalchemy-error-argument-formats-cant-be-mixed-when-inputting-variables

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!