恕我直言,这基本上是一个标准化问题。名为“id”的列不会唯一地寻址一行,因此它永远不可能是 PK。至少需要一个新的(代理)键(元素)。约束本身不能表示为“行内”的表达式,因此必须用 FK 来表示。
所以它分为两个表:
一个 PK=id,一个 FK REFERENCING two.sid
两个带有 PK= 代理键和 FK id REFERENCING one.id
原始有效载荷“值”也存在于此。
“一位变量”消失了,因为它可以用 EXISTS 来表示。 (实际上表一个指向持有令牌的行)
[我希望 Postgres 规则系统可用于使用上述两表模型来模拟 OP 的预期行为。但这将是一个丑陋的黑客...]
编辑/更新:
Postgres 支持部分/条件索引。 (不知道ms-sql)
DROP TABLE tmp.one;
CREATE TABLE tmp.one
( sid INTEGER NOT NULL PRIMARY KEY -- surrogate key
, id INTEGER NOT NULL
, status INTEGER NOT NULL DEFAULT '0'
/* ... payload */
);
INSERT INTO tmp.one(sid,id,status) VALUES
(1,1,0) , (2,1,1) , (3,1,0)
, (4,2,0) , (5,2,0) , (6,2,1)
, (7,3,0) , (8,3,0) , (9,3,1)
;
CREATE UNIQUE INDEX only_one_non_zero ON tmp.one (id)
WHERE status > 0 -- "partial index"
;
\echo this should succeed
BEGIN ;
UPDATE tmp.one SET status = 0 WHERE sid=2;
UPDATE tmp.one SET status = 1 WHERE sid=1;
COMMIT;
\echo this should fail
BEGIN ;
UPDATE tmp.one SET status = 1 WHERE sid=4;
UPDATE tmp.one SET status = 0 WHERE sid=9;
COMMIT;
SELECT * FROM tmp.one ORDER BY sid;