繁体   English   中英

在Postgresql中的索引约束上初始可延迟

[英]DEFERRABLE INITIALLY DEFERRED on index contraint in postgresql

我可以使用以下查询添加DEFERRABLE INITIALIALDEFERED:

ALTER TABLE user DROP CONSTRAINT unq_user_address, add CONSTRAINT unq_user_address UNIQUE(user_address) deferrable INITIALLY DEFERRED;

现在,我还有另一列,我想添加DEFERRABLE INITIALIALLY DEFERRED。 约束是在索引上的,所以我这样做时会出错。

这是索引约束:

CREATE UNIQUE INDEX unq_account
  ON user 
  USING btree 
  (lower(account::text) COLLATE pg_catalog."default");

我修改为说

CREATE UNIQUE INDEX unq_account
      ON user 
      USING btree 
      (lower(account::text) COLLATE pg_catalog."default") deferrable INITIALLY DEFERRED;

也尝试过

CREATE UNIQUE INDEX unq_account
      ON user 
      USING btree 
      (lower(account::text) COLLATE pg_catalog."default") UNIQUE_CHECK_PARTIAL;

因此,不知道如何在索引上应用相同的内容。

我看到以下官方文档: https : //www.postgresql.org/docs/9.6/static/index-unique-checks.html

UNIQUE_CHECK_PARTIAL表示唯一约束是可延迟的。 PostgreSQL将使用此模式插入每一行的索引条目。 访问方法必须允许重复的条目进入索引,并通过从aminsert返回FALSE来报告任何潜在的重复。 对于返回FALSE的每一行,将安排一次延迟的重新检查。

和这里:

UNIQUE_CHECK_EXISTING表示这是对报告为潜在唯一性违规的行的重新检查。 尽管这是通过调用aminsert来实现的,但是在这种情况下,访问方法不得插入新的索引条目。 索引条目已经存在。 而是,访问方法必须检查以查看是否还有另一个活动索引条目。 如果是这样,并且目标行也仍然存在,请报告错误。

是我需要使用的东西吗?如果是,那么如何使用?

您不能将索引定义为可递延索引。 可延迟性是约束的属性,而不是索引。

CREATE TABLE test_table
(
    test_col integer not null
);

ALTER TABLE test_table
ADD constraint test_col_unique unique (test_col) deferrable initially deferred;

但是,不能将任意表达式用于唯一约束,只能使用直接列引用:

ALTER TABLE test_table
ADD CONSTRAINT test_col_abs_unique UNIQUE (abs(test_col));

将报告

ERROR:  syntax error at or near "("

因为解析器仅处理简单的列引用。

因此,您不能将这张支票延期。

您不能在CREATE INDEX ... SQL查询中使用UNIQUE_CHECK_PARTIALUNIQUE_CHECK_EXISTING 就像您在“ 访问方法接口”文档页面上所说的那样,

...向aminsert函数传递了一个checkUnique参数,该参数具有以下值之一:UNIQUE_CHECK_NO ...,UNIQUE_CHECK_YES ...,UNIQUE_CHECK_PARTIAL ...,UNIQUE_CHECK_EXISTING

因此,这些是要传递给aminsert函数的 checkUnique参数的值(我认为这是访问方法接口API或内部的一部分)

其余的由克雷格回答。

您可以alter table "user" add CONSTRAINT unq_user_address UNIQUE(account) deferrable INITIALLY DEFERRED; 失去lower(account)条件:

作为解决方法,您可以执行此丑陋的操作-添加列并触发:

b=# create table "user" (account text, account_uq text);
CREATE TABLE
b=# create function tf() returns trigger as $$ begin NEW.account_uq = lower(NEW.account); return NEW; end;$$ language plpgsql;
ERROR:  function "tf" already exists with same argument types
b=# CREATE TRIGGER tg BEFORE UPDATE OR INSERT ON "user" FOR EACH ROW EXECUTE PROCEDURE tf();
CREATE TRIGGER
b=# alter table "user" add CONSTRAINT another_uq UNIQUE(account_uq) deferrable INITIALLY DEFERRED;
ALTER TABLE
b=# insert into "user" (account) select 'b';
INSERT 0 1
b=# begin;
BEGIN
b=# insert into "user" (account) select 'B';
INSERT 0 1
b=# select * from "user";
 account | account_uq
---------+------------
 b       | b
 B       | b
(2 rows)

b=# end;
ERROR:  duplicate key value violates unique constraint "another_uq"
DETAIL:  Key (account_uq)=(b) already exists.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM