添加唯一约束但忽略现有 table 数据
Add a unique constraint but ignore existing table data
我希望使用以下查询将唯一约束添加到 table -
ALTER TABLE events ADD CONSTRAINT events_timestamp_request_session_key UNIQUE (event_timestamp, request_id, session_id);
查询有效,但是在一个数据库上现有数据不满足约束,因此查询失败-
ERROR: could not create unique index "events_timestamp_request_session_key"
DETAIL: Key (event_timestamp, request_id, session_id)=(2017-07-05 14:53:25.475246+00, a55df6-8533e322cd-aa9d57-87e2, 132443) is duplicated.
预计会有一些重复,但不幸的是我不能简单地删除或更改它们。
有什么方法可以根据需要添加约束,同时忽略 table 中的现有数据?
我认为没有内置方法可以执行此操作。但是,您可以使用表达式创建唯一索引。让我假设您在每个 table:
中都有一个序列唯一 ID
create unique index unq_events_timestamp_request_session_key
on (event_timestamp, request_id, session_id,
(case when event_id < 99999 then event_id else -1 end)
);
表达式本质上说:"if this key is already in the table, then ignore it for the unique constraint".
您可以对所有但当前的重复项实施唯一约束,方法是消除它们:
create unique index unq_events_timestamp_request_session_key
on (event_timestamp, request_id, session_id,
(case when event_id in (1, 2, 3, 5, 8) then event_id
else -1
end)
);
这需要对当前的副本进行研究。实际上,您也可以使用过滤子句:
create unique index unq_events_timestamp_request_session_key
on (event_timestamp, request_id, session_id)
where event_id > 999999 ;
create unique index unq_events_timestamp_request_session_key
on (event_timestamp, request_id, session_id)
where event_id not in (1, 2, 3, 5, 8) ;
您可以为此使用部分索引,这不是一个特别好的解决方案,但在您可以更正旧数据之前它会一直有效。
类似于:
CREATE UNIQUE INDEX events_timestamp_request_session_key
ON events (event_timestamp, request_id, session_id)
WHERE event_timestamp >= '2017-07-01'::timestamp;
时间是您清理数据的开始时间。
where 子句将索引限制为仅查看具有较新事件时间戳的记录。旧记录完全从索引中排除,因此不考虑进行唯一性检查。
文档:https://www.postgresql.org/docs/9.6/static/indexes-partial.html
我希望使用以下查询将唯一约束添加到 table -
ALTER TABLE events ADD CONSTRAINT events_timestamp_request_session_key UNIQUE (event_timestamp, request_id, session_id);
查询有效,但是在一个数据库上现有数据不满足约束,因此查询失败-
ERROR: could not create unique index "events_timestamp_request_session_key"
DETAIL: Key (event_timestamp, request_id, session_id)=(2017-07-05 14:53:25.475246+00, a55df6-8533e322cd-aa9d57-87e2, 132443) is duplicated.
预计会有一些重复,但不幸的是我不能简单地删除或更改它们。
有什么方法可以根据需要添加约束,同时忽略 table 中的现有数据?
我认为没有内置方法可以执行此操作。但是,您可以使用表达式创建唯一索引。让我假设您在每个 table:
中都有一个序列唯一 IDcreate unique index unq_events_timestamp_request_session_key
on (event_timestamp, request_id, session_id,
(case when event_id < 99999 then event_id else -1 end)
);
表达式本质上说:"if this key is already in the table, then ignore it for the unique constraint".
您可以对所有但当前的重复项实施唯一约束,方法是消除它们:
create unique index unq_events_timestamp_request_session_key
on (event_timestamp, request_id, session_id,
(case when event_id in (1, 2, 3, 5, 8) then event_id
else -1
end)
);
这需要对当前的副本进行研究。实际上,您也可以使用过滤子句:
create unique index unq_events_timestamp_request_session_key
on (event_timestamp, request_id, session_id)
where event_id > 999999 ;
create unique index unq_events_timestamp_request_session_key
on (event_timestamp, request_id, session_id)
where event_id not in (1, 2, 3, 5, 8) ;
您可以为此使用部分索引,这不是一个特别好的解决方案,但在您可以更正旧数据之前它会一直有效。
类似于:
CREATE UNIQUE INDEX events_timestamp_request_session_key
ON events (event_timestamp, request_id, session_id)
WHERE event_timestamp >= '2017-07-01'::timestamp;
时间是您清理数据的开始时间。
where 子句将索引限制为仅查看具有较新事件时间戳的记录。旧记录完全从索引中排除,因此不考虑进行唯一性检查。
文档:https://www.postgresql.org/docs/9.6/static/indexes-partial.html