在 postgres 中,当表/ View 以破坏现有引用的方式更新(例如重命名)时,该引用也会被更新,否则初始更新请求将失败并出现如下错误:
ERROR: cannot drop table users because other objects depend on it
这太棒了!
但是,这些引用似乎并未在函数(或触发器)和表/ View 之间强制执行。
所以过程:
(Create TabA) => (Create TabB w/ Ref to TabA) => (Rename TabA to TabC) = No problems
但是
(Create TabA) => (Create FuncA w/ Ref to TabA) => (Rename TabA to TabC) = Quietly broken reference that errors on execution of "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)
最佳答案
这里的根本问题是,当前在最初加载 PostgreSQL 函数时,实际上没有办法始终知道其依赖项是什么。虽然将其添加到 SQL 语言函数中可能并不难,但即使在 PL/PGSQL 函数中使用动态 SQL,这实际上也是不可能的。如果再深入到 C、PL/Perl、PL/Python 等函数,您就没有任何保证。
所以函数是一个特例。值得注意的是,它们几乎总是对规划器不透明,事实上它们对于整个 PostgreSQL 来说通常是不透明的。因此,出于这个原因,您需要仔细考虑何时何地使用它们、如何测试等。
幸运的是,有像 pg_TAP
和其他测试框架之类的东西可以让您检查功能是否仍然有效。
关于sql - postgres 函数中未强制引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46379926/