我让FK遇到了错误的限制,我必须改变它:
ALTER TABLE user_login_logout_fact DROP CONSTRAINT user_fk;
ALTER TABLE user_login_logout_fact
ADD CONSTRAINT user_fk FOREIGN KEY (user_id)
REFERENCES uuser (id) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
它没有问题,但我必须使用补丁文件来应用它,并检查它是否已经应用。所以我必须创建这样的函数:
CREATE FUNCTION tryUpgrade(patch varchar) RETURNS integer AS $$
DECLARE testRecord RECORD;
BEGIN
RAISE NOTICE 'checking %', patch;
SELECT INTO testRecord * FROM patchlog where basename = patch;
IF FOUND THEN
RAISE NOTICE 'patch % has already been applied', patch;
RETURN 0;
END IF;
//check if constraints are ok
IF ok THEN
RAISE NOTICE 'upgraded but not noted';
INSERT INTO patchlog VALUES (patch, now());
RETURN 0;
END IF;
SELECT INTO testRecord upgrade(); //this function will alter table
INSERT INTO patchlog VALUES (patch, now());
RAISE NOTICE 'upgraded';
RETURN 1;
END;
$$ LANGUAGE plpgsql;
所以,问题是 - 如何检查FK是否会使用ON DELETE CASCADE而不是旧的NO ACTION?
答案 0 :(得分:1)
如何检查FK是否使用ON DELETE CASCADE而不是旧的NO ACTION?
您可以查看系统目录表pg_constraint
中的confdeltype
。我引用手册:
外键删除操作代码:a =无操作,r = restrict,c = cascade,n =设置null,d =设置默认值
使用它像:
IF EXISTS (
SELECT 1
FROM pg_constraint
WHERE conname = 'user_fk'
AND conrelid = 'user_login_logout_fact'::regclass
AND confdeltype = 'c'
) THEN
-- all done
ELSE
-- run ALTER TABLE ...
END IF;
表名可以选择是模式限定的。详情:
How do I speed up counting rows in a PostgreSQL table?
当你自己回答时,可以通过查询符合SQL标准的information schema来实现同样的目标。
然而:
并非所有主要的RDBMS都实现它。例如,甲骨文没有。
信息模式是通过(有时非常复杂的) 视图 (而不是表格)来实现的,这使得查找很多比直接访问pg_catalog
中的表格要慢。实际数据库中的快速测试显示了手头示例的因子10。我似乎有1000倍以上。
使用信息模式的目的通常是使您的实现“可移植”。但这几乎从未开始。各种RDBMS在很多方面都远离SQL标准。
还有另一个好处:Postgres不会在主要版本的pg_catalog
中声明有关表格结构的任何内容。通过使用信息模式,可以在Postgres本身的主要版本上保持安全
但是,基本结构几乎没有变化。虽然可能,但这样的查询在将来的版本中会破坏,这是不太可能的。
答案 1 :(得分:1)
此外,第二个解决方案似乎更少特定于postgresql。
有关referential_constraints
表中的外键存储的信息:
SELECT * FROM information_schema.referential_constraints
WHERE CAST(constraint_name AS TEXT) LIKE 'user_fk'
AND delete_rule LIKE 'CASCADE'
AND update_rule LIKE 'CASCADE';