在postgres中,当一个表/视图以一种破坏现有引用的方式更新(例如重命名)时,该引用也会被更新,或者初始更新请求将失败,并出现如下错误:
错误:无法删除表用户,因为其他对象依赖于它
哪个好极了!
但是,这些引用似乎并未在函数(或触发器)和表/视图之间强制执行。
所以这个过程:
(创建TabA)=> (创建TabB w / Ref to TabA)=> (将TabA重命名为TabC)=没有问题
但是
(创建TabA)=> (创建FuncA w / Ref to TabA)=> (将TabA重命名为TabC)=执行“FuncA”
时出现错误的悄悄破坏引用
因为FuncA
仍然指向TabA
。
Postgres不允许使用不存在的引用创建新函数,因此它显然能够验证函数中的引用。
所以,
编辑添加最小示例
-- Create users table
CREATE TABLE users
(
id integer NOT NULL,
name text COLLATE pg_catalog."default" NOT NULL
)
-- Create function that references "users"
create function myfunc(int)
returns text
language SQL
AS
$BODY$
select name
from users
where id = $1
limit 1
$BODY$
-- Test the function
select myfunc(1)
-- (SUCCESS: returns NULL)
-- Rename users table
alter table users rename to old_users
-- Test the function
select myfunc(1)
-- (ERROR: relation "users" does not exists SQL state 42P01)
答案 0 :(得分:2)
这里的根本问题是,当最初为PostgreSQL加载函数时,目前还没有真正的方法来总是知道它的依赖关系是什么。虽然这可能不会很难添加到SQL语言函数,即使在PL / PGSQL函数中使用动态SQL,这实际上也是不可能的。更进一步到C,PL / Perl,PL / Python等功能,你没有任何保证的希望。
所以功能是一个特例。值得注意的是,它们几乎总是规划不透明,实际上它们对PostgreSQL整体来说通常是不透明的。因此,您需要仔细考虑何时何地使用它们,如何测试等等。
幸运的是,有pg_TAP
和其他测试框架可以让你检查功能是否仍然有效。