在 INSERT 中使用 WHERE … ON CONFLICT …

Using WHERE in INSERT … ON CONFLICT …

我正在尝试在 PostgreSQL 中将 where 子句与 insert on conflict 一起使用,但它没有触发。这是我用 python 编写的 SQL 查询。我正在使用 psycopg2:

INSERT INTO city_guide_stat AS stat (city_guide_id, {cols})
VALUES {values}
ON CONFLICT (city_guide_id)
DO UPDATE SET ({update_cols}) = ({update_values})
WHERE stat.city_guide_id = excluded.city_guide_id 
AND md5(({dest_hash_cols})::TEXT)<>md5(({src_hash_cols})::TEXT)

这是我的 python 代码,它实际上填充了这些 python 变量:

sql_stmt = sql.SQL(UPSERT_CITY_GUIDE_STAT).format(
            # Table columns
            cols=sql.SQL(', ').join(
                map(sql.Identifier, COLUMNS_TO_INSERT_UPDATE)),
            # Values
            values=sql.SQL(', ').join(
                sql.SQL('({})').format(
                    sql.SQL(', ').join(sql.Placeholder() * (num_columns)),
                ) * num_batch
            ),
            # Update columns
            update_cols=sql.SQL(', ').join(
                map(sql.Identifier, COLUMNS_TO_INSERT_UPDATE)),
            update_values=sql.SQL(', ').join(map(lambda x: sql.SQL('excluded.{}').format(
                sql.Identifier(x)
            ), COLUMNS_TO_INSERT_UPDATE)),
            # hash_cols
            dest_hash_cols=sql.SQL(', ').join(map(lambda x: sql.SQL('stat.{}').format(
                sql.Identifier(x)
            ), COLUMNS_TO_INSERT_UPDATE)),
            src_hash_cols=sql.SQL(', ').join(map(lambda x: sql.SQL('excluded.{}').format(
                sql.Identifier(x)
            ), COLUMNS_TO_INSERT_UPDATE))
        )

我面临的问题是我的 where 子句没有触发。

比较行的文本表示的 md5 是不可靠的,因为输入文本可能与相同行的输出表示不同,例如对于数值:

md5('1.0') <> md5('1') while (1.0) = (1)

如果所有列类型都有相等运算符,则比较行:

INSERT INTO city_guide_stat AS stat (city_guide_id, {cols})
VALUES {values}
ON CONFLICT (city_guide_id)
DO UPDATE SET ({update_cols}) = ({update_values})
WHERE ({dest_hash_cols}) is distinct from ({src_hash_cols})

否则你根本无法做到这一点(或仅比较可比较)。

另请注意,

WHERE stat.city_guide_id = excluded.city_guide_id 

是多余的。