我使用PGSQL并尝试添加以下索引。
CREATE UNIQUE INDEX fk_client ON user_client (fk_client) WHERE fk_client NOT IN(SELECT fk_client FROM legal_entity);
但是......这是不可能的,因为允许在创建索引时运行子查询。
我收到以下错误:
ERROR: cannot use subquery in index predicate
有什么方法可以解决这个问题吗?
上述模型代表案件的情况。
索引没有,但是有什么方法可以解决这个问题吗?...
脚本生成表格:
-- user is a special word, then renamed to users
CREATE TABLE users (
id_user INT,
name VARCHAR(50) NOT NULL,
CONSTRAINT user_pkey PRIMARY KEY (id_user)
);
CREATE TABLE client (
id_client INT,
CONSTRAINT client_pkey PRIMARY KEY (id_client)
);
CREATE TABLE legal_entity (
fk_client INT,
federal_id VARCHAR(14) NOT NULL,
CONSTRAINT legal_entity_pkey PRIMARY KEY (fk_client),
CONSTRAINT legal_entity_fkey FOREIGN KEY (fk_client) REFERENCES client (id_client)
);
CREATE TABLE user_client (
fk_client INT,
fk_user INT,
CONSTRAINT user_client_pkey PRIMARY KEY (fk_client, fk_user),
CONSTRAINT user_client_fkey_1 FOREIGN KEY (fk_client) REFERENCES client (id_client),
CONSTRAINT user_client_fkey_2 FOREIGN KEY (fk_user) REFERENCES users (id_user)
);
答案 0 :(得分:3)
使用规则的缺点是规则只是在解析后重写查询,因此如果数据是通过触发器添加的,则不会触发。添加一个用你的逻辑调用函数的CHECK约束会更安全。如果我正确地遵循你的逻辑,它应该是这样的:
CREATE OR REPLACE FUNCTION check_user_client(fkc int)
RETURNS boolean AS
$$
DECLARE
i int;
BEGIN
SELECT count(*) INTO i FROM legal_entity WHERE fk_client = fkc;
IF (i > 0) THEN
RETURN true;
END IF;
SELECT count(*) INTO i FROM user_client WHERE fk_client = fkc;
IF (i = 0) THEN
RETURN true;
END IF;
RETURN false;
END
$$ LANGUAGE plpgsql;
ALTER TABLE user_client ADD CONSTRAINT unique_user CHECK (check_user_client(fk_client));
答案 1 :(得分:1)
我通过添加规则表解决了我的问题:
CREATE OR REPLACE RULE rule_test AS ON INSERT
TO user_client WHERE (
(SELECT fk_client FROM legal_entity WHERE fk_client = new.fk_client) IS NULL) AND (
(SELECT fk_client FROM user_client WHERE fk_client = new.fk_client) IS NOT NULL)
DO INSTEAD NOTHING;
答案 2 :(得分:-2)
DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path=tmp;
CREATE TABLE foo
( id INTEGER NOT NULL PRIMARY KEY
);
CREATE TABLE tbl_relation
( id INTEGER NOT NULL PRIMARY KEY
, foo_id INTEGER REFERENCES foo(id)
, fk_1 INTEGER
);
CREATE UNIQUE INDEX fk_1 ON tbl_relation (fk_1)
WHERE foo_id IS NULL;
更新:这是修改数据模型后的新情况。 问题是:legal_entity和客户似乎共享一个关键域(这是不正常的)给legal_entity自己的关键域似乎更合适。
DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path=tmp;
-- user is a special word, then renamed to users
CREATE TABLE users
( id INTEGER PRIMARY KEY
-- name is a special word
, zname VARCHAR(50) NOT NULL
);
CREATE TABLE client
(id INTEGER PRIMARY KEY
);
CREATE TABLE legal_entity
( id INTEGER PRIMARY KEY
, client_id INTEGER REFERENCES client(id)
, federal_id VARCHAR(14) NOT NULL
);
CREATE TABLE user_client
( client_id INTEGER REFERENCES client (id)
, user_id INTEGER REFERENCES users (id)
, legal_id INTEGER REFERENCES legal_entity(id)
, CONSTRAINT user_client_pkey PRIMARY KEY (client_id, user_id)
);
CREATE INDEX tres_stupide ON user_client (client_id) WHERE legal_id IS NULL;