簡體   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