【问题标题】:PostgreSQL, check for duplicate before insertPostgreSQL,插入前检查重复
【发布时间】:2019-07-15 08:50:11
【问题描述】:

我正在运行 PostgreSQL 10,我的桌子上有几个 BEFORE INSERT OR UPDATEAFTER INSERT OR UPDATE tests

我想要另一个触发器BEFORE INSERT OR UPDATE 来检查潜在的重复行。

我做了这个:

CREATE OR REPLACE FUNCTION set_check_dublicate_on_test() RETURNS trigger AS $$
    BEGIN
        IF EXISTS (SELECT 1 FROM tests WHERE test_id = NEW.test_id) THEN
            RETURN NULL;
        ELSE
            RETURN NEW;
        END IF;

    END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS set_check_dublicate_on_test ON tests;
CREATE TRIGGER set_check_dublicate_on_test BEFORE INSERT OR UPDATE ON tests
    FOR EACH ROW EXECUTE PROCEDURE set_check_dublicate_on_test();

但我不确定它是否会与其他 triggers 冲突,或者它会完成目标,如果返回 NULL,触发器将被忽略?

【问题讨论】:

  • 使用 test_id 上的唯一索引检查重复值不是更容易吗?
  • test_id 上创建一个唯一索引,然后使用insert ... on conflict (test_id) do nothing - 不需要触发器。它甚至可以处理相同值的并发插入(触发器将能够检测到)
  • 我确实允许 test_id 成为 NULL,这应该允许 insert - 这仍然有效吗?
  • @Alfred 有效的评论,但显然它应该仍然有效:见stackoverflow.com/questions/23449207/…)

标签: sql postgresql


【解决方案1】:

首先——我相信如果你想在你的表中拥有一个唯一的字段——那么最简单的方法就是这样标记它:

https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-UNIQUE-CONSTRAINTS

如果尝试在此类字段上插入不应引发错误,则存在 ON CONFLICT 关键字:

https://www.postgresql.org/docs/current/sql-insert.html

特别是:ON CONFLICT DO NOTHING

【讨论】:

  • 我确实允许 test_id 成为 NULL,这应该允许 insert - 这仍然有效吗?
  • In general, a unique constraint is violated if there is more than one row in the table where the values of all of the columns included in the constraint are equal. However, two null values are never considered equal in this comparison. That means even in the presence of a unique constraint it is possible to store duplicate rows that contain a null value in at least one of the constrained columns. This behavior conforms to the SQL standard, but we have heard that other SQL databases might not follow this rule. So be careful when developing applications that are intended to be portable.
  • 如果 test_id 是唯一约束中的唯一列 - Postgresql 将允许 NULL 值。
  • 我会接受这个,因为这是第一个解决方案。谢谢大家。
  • @AlfredBalle 如果您的列中已经有重复数据并且您希望新条目现在是唯一的而不删除旧数据怎么办?我认为触发器将适用于那里
【解决方案2】:

让数据库管理唯一性!这可确保插入和更新的数据完整性。

这很简单:

alter table test add constraint unq_test_test_id unique (test_id);

如果您一次插入一行,那么这很好。插入(或更新)将失败。

如果你想插入多行并允许非重复插入进入,那么我们on conflict

insert into test ( . . . )
    select . ..
    from . . .
    on conflict on constraint unq_test_test_id do nothing;

【讨论】:

  • ON CONFLICT (test_id) DO UPDATE SET test_id = test_id 也可以像upsert 一样工作吗?因为我在我的应用程序中遇到了DO NOTHING 错误,因为它需要返回插入行的 id。
猜你喜欢
  • 1970-01-01
  • 2011-12-04
  • 2014-10-04
  • 2023-04-02
  • 2011-02-03
  • 1970-01-01
  • 2021-01-20
  • 2016-11-09
相关资源
最近更新 更多