sql - postgres 函数中未强制引用?

标签 sql database postgresql

在 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/

相关文章:

python - InternalError : current transaction is aborted, 命令被忽略,直到事务 block 结束

postgresql - 错误 : function jsonb_array_elements_text(jsonb[]) does not exist

sql - 如何在 Group By 中使用 Case Statement 列

php - 给定日期的 SQL 查询日期时间

sql - 选择使用通配符查找以两个字符结尾然后是数字

mongodb - 有没有办法用 MongoDB 替换 Many()?

MySQL:如何选择除前 10 条记录以外的所有内容

json - Swift,错误(参数标签 '(node:)' 与任何可用的重载不匹配),rest in Vapor,模型 Controller

mysql - 当值为 NULL 使用旧值时创建触发器。嵌套异常错误

Mysql库存系统,从其他表的行中加入一个字段的总和