在INSERT语句中使用类型转换和条件插入表

时间:2019-05-22 15:32:36

标签: sql postgresql insert psycopg2

基于this previous question

我正在尝试使用带有某些数据的psycopg2在Python中编写一个插入语句。该查询在Postgresql控制台中可以正常工作,但是当我从psycopg2尝试该查询时,出现错误。

这是我要插入的表

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

这是我要插入的数据

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

这是我的查询:

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_)

错误消息:

----> 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.

也许无法在psycopg2中执行此操作。任何帮助将不胜感激:))

2 个答案:

答案 0 :(得分:1)

您的参数替换不正确。例如,代替此:

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

您应该具有:

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

答案 1 :(得分:1)

该错误是由于CASE表达式(即您要插入的值)的结果是TEXT,而age列是INTEGER。

要直接解决该错误,只需将表达式强制转换为INTEGER

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

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

但是,除非当该字段不是整数而不是您专门排除的('', '#', '-', '--', '??')值之一之外,除非您实际上想要一个无效的强制转换异常,否则您可能希望将此特定语句重写为:

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

因此,在尝试对其进行强制转换之前,请检查它是否确实是一个数字,如果不是数字,则将其为NULL。但是无论哪种方式,您只需要强制转换结果即可。请注意,您可能需要对dob列执行相同的操作。