변형 1
이있는 단일 열만 있으면되므로 모든 standard = true
다른 행에서 standard를 NULL로 설정하십시오. UNIQUE
NULL 값이 위반하지 않기 때문에 일반 제약 조건이 작동합니다.
CREATE TABLE taxrate (
taxrate int PRIMARY KEY
, standard bool DEFAULT true
, CONSTRAINT standard_true_or_null CHECK (standard) -- yes, that's the whole constraint
, CONSTRAINT standard_only_1_true UNIQUE (standard)
);
DEFAULT
입력 한 첫 번째 행이 기본값이되어야한다는 선택적 알림입니다. 아무것도 시행 하지 않습니다 . 로 둘 이상의 행을 standard = true
설정할 수 없지만 모든 행을 NULL로 설정할 수 있습니다. 단일 테이블에서 제한 조건 만으로이를 방지 할 수있는 확실한 방법은 없습니다 . CHECK
제약 조건은 다른 행을 고려하지 않습니다 (더티 트릭 없음).
관련 :
업데이트하려면 :
BEGIN;
UPDATE taxrate SET standard = NULL WHERE standard;
UPDATE taxrate SET standard = TRUE WHERE taxrate = 2;
COMMIT;
다음과 같은 명령을 허용하려면 (문의 끝에서만 제한 조건이 충족되는 경우) :
WITH kingdead AS (
UPDATE taxrate
SET standard = NULL
WHERE standard
)
UPDATE taxrate
SET standard = TRUE
WHERE taxrate = 1;
.. UNIQUE
제약 조건은이어야 DEFERRABLE
합니다. 보다:
여기 dbfiddle
변형 2
다음 과 같은 단일 행 이있는 두 번째 테이블 이 있습니다.
이것을 수퍼 유저로 생성하십시오 :
CREATE TABLE taxrate (
taxrate int PRIMARY KEY
);
CREATE TABLE taxrate_standard (
taxrate int PRIMARY KEY REFERENCES taxrate
);
CREATE UNIQUE INDEX taxrate_standard_singleton ON taxrate_standard ((true)); -- singleton
REVOKE DELETE ON TABLE taxrate_standard FROM public; -- can't delete
INSERT INTO taxrate (taxrate) VALUES (42);
INSERT INTO taxrate_standard (taxrate) VALUES (42);
이제 표준을 가리키는 단일 행이 항상 있습니다 (이 간단한 경우에도 표준 비율을 직접 나타냄). 수퍼 유저 만이이를 깨뜨릴 수 있습니다. 트리거로도 허용하지 않을 수 있습니다 BEFORE DELETE
.
여기 dbfiddle
관련 :
변형 1VIEW
과 동일하게 a 를 추가 할 수 있습니다 .
CREATE VIEW taxrate_combined AS
SELECT t.*, (ts.taxrate = t.taxrate) AS standard
FROM taxrate t
LEFT JOIN taxrate_standard ts USING (taxrate);
원하는 모든 것이 표준 요율 인 쿼리에서는 taxrate_standard.taxrate
직접 사용하십시오.
나중에 추가했습니다.
products.tax_rate_id
와 사이에 FK가 있습니다tax_rate.id
가난한 사람의 구현 변형 2 단지에 행 추가하는 것입니다 products
표준 세율을 가리키는 (또는 유사한 테이블); 더미 제품은 "표준 세율"이라고 부를 수 있습니다-설정에서 허용하는 경우.
FK 제약 조건은 참조 무결성을 강화합니다. 이를 완료하려면 tax_rate_id IS NOT NULL
행을 적용 하십시오 (일반적으로 열이 아닌 경우). 그리고 삭제를 허용하지 않습니다. 둘 다 방아쇠에 넣을 수 있습니다. 추가 테이블은 없지만 우아하지 않고 신뢰할 수 없습니다.