SQL:如何检查外键是否真的更改了
我使用了错误约束的FK,我必须更改它:SQL:如何检查外键是否真的更改了,sql,postgresql,plpgsql,Sql,Postgresql,Plpgsql,我使用了错误约束的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 DEFE
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是否将用于删除级联而不是旧的无操作
如何检查FK是否将用于删除级联而不是旧的无操作
可以在系统目录表中检查confdeltype。手册:
外键删除操作代码:a=不操作,r=限制,c=级联,n=设置为空,d=设置为默认值
在PL/pgSQL代码中,使用它的方式如下:
如果存在
从pg_约束中选择
其中conname='user\u fk'
和conrelid='user\u login\u logout\u fact':regclass
而confdeltype='c'
然后
-全部完成
其他的
-运行ALTERTABLE。。。
如果结束;
表名可以是模式限定的。见:
信息模式与系统目录
正如您自己回答的那样,通过查询遵循SQL标准的,也可以实现同样的目的
然而:
并非所有主要的RDBMS都实现了它。例如,甲骨文没有
信息模式有时使用非常复杂的视图而不是表来实现,这使得查找比直接访问中的表慢得多。在真实的实时数据库中进行的快速测试显示,手边示例的系数为10。我似乎有1000倍甚至更多
使用信息模式的目的通常是保持实现的可移植性。但这从一开始就很难奏效。各种RDBMS在很多方面都离SQL标准太远了
不过,还有另一个好处:Postgres不会声明任何关于PGU目录中跨主要版本的表结构的内容。通过使用信息模式,可以在Postgres的主要版本中安全地使用。
然而,基本结构几乎没有变化。虽然有可能,但像这样的查询不太可能在将来的版本中中断
见:
另外,第二种解决方案似乎不太适合postgresql 关于引用约束表中外键存储的信息:
我在回答中增加了一章讨论信息模式与PGU目录。
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';