对postgresql中的索引约束可以推断出最小的延迟

时间:2016-11-28 09:08:33

标签: java postgresql

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

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

现在我有另一列,我想添加DEFERRABLE INITIALLY 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表示这是a的延迟重新检查   报告为潜在唯一性违规的行。虽然   这是通过调用aminsert来实现的,访问方法一定不能   在这种情况下插入一个新的索引条目。索引条目已经存在   当下。相反,访问方法必须检查是否存在   另一个实时索引条目。如果是这样,并且目标行也是如此   直播,举报错误。

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

2 个答案:

答案 0 :(得分:1)

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

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 "("

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

所以你不能让这个检查延期。

答案 1 :(得分:1)

您无法在UNIQUE_CHECK_PARTIAL SQL查询中同时使用UNIQUE_CHECK_EXISTINGCREATE INDEX ...。如您所引用的Access Method Interface 文档页面所述,

  

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

所以那些 checkUnique 参数的值要传递给 aminsert函数(我假设它是Access方法接口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.