Insert into table with type casting and condition in INSERT statement

假如想象 提交于 2019-12-25 01:13:26

问题


Based on this previous question

I am trying to compose an insert statement in Python using psycopg2 with some data. The query works beautifully in postgresql console but when I try it from psycopg2 I get an error.

Here's the table i want to insert to

create_test_table = """CREATE TABLE persons(
   name           VARCHAR,
   age            INT,
   dob            DATE,
   sex            VARCHAR);"""

Here's the data I want to insert

d_ = {"name":"Gino", "age": "", "dob": "na", "sex": "M"}

And here's my query:

cur.execute("""INSERT INTO persons (age,dob,sex,name) 
               VALUES (CASE WHEN cast(%(age)s as text) IN ('', '#', '-', '--', '??') THEN NULL ELSE %(age)s END,
                       CASE WHEN cast(%(dob)s as text) IN ('', '#', '-', '--', '??') THEN NULL ELSE %(dob)s END,
                       CASE WHEN cast(%(sex)s as text) IN ('', '#', '-', '--', '??') THEN NULL ELSE %(sex)s END,
                       CASE WHEN cast(%(name)s as text) IN ('', '#', '-', '--', '??') THEN NULL ELSE %(name)s END)""", d_)

Error message:

----> 5  CASE WHEN cast(%(name)s as text) IN ('', '#', '-', '--', '??') THEN NULL ELSE %(name)s END)""", d_)

ProgrammingError: column "age" is of type integer but expression is of type text
LINE 2:                VALUES (CASE WHEN cast('' as text) IN ('', '#...
                               ^
HINT:  You will need to rewrite or cast the expression.

Maybe it is not possible to do this in psycopg2. Any help would be appreciated :))


回答1:


The error is due to the result of the CASE expression (i.e. the value you're trying to insert) being TEXT, whereas the age column is INTEGER.

To address the error directly, you could simply cast the expression to INTEGER:

CASE WHEN cast(%(age)s as text) IN ('', '#', '-', '--', '??') THEN NULL ELSE %(age)s END::INTEGER

Or

CAST(CASE WHEN cast(%(age)s as text) IN ('', '#', '-', '--', '??') THEN NULL ELSE %(age)s END AS INTEGER)

However, unless you actually want an invalid cast exception when that field is anything other than an integer, and not one of the ('', '#', '-', '--', '??') values you're specifically excluding, you might want to rewrite this particular statement as:

CASE WHEN age::TEXT ~ '^[\d]+$' THEN age ELSE NULL END::INTEGER

So check that's it actually a number before attempting to cast it, and if it's not a number then NULL it. But either way, you just need to cast the result. Note you may have to do the same for the dob column.




回答2:


Your parameter substitution is not correct. For example, instead of this:

%(CASE WHEN cast(age as text) IN ('', '#', '-', '--', '??') THEN NULL ELSE age END)s

You should have:

(CASE WHEN cast(%(age)s as text) IN ('', '#', '-', '--', '??') THEN NULL ELSE age END)


来源:https://stackoverflow.com/questions/56260366/insert-into-table-with-type-casting-and-condition-in-insert-statement

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