在 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
是多余的。
我正在尝试在 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
是多余的。