Использование WHERE в INSERT ... ON CONFLICT ... - PullRequest
0 голосов
/ 14 января 2019

Я пытаюсь использовать предложение where с insert on conflict в PostgreSQL, и оно не запускается. Вот мой SQL-запрос, написанный на python. Я использую 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, который на самом деле заполняет эти переменные:

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 не срабатывает.

1 Ответ

0 голосов
/ 14 января 2019

Сравнение 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 

является избыточным.

...