You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法从init.db访问pgcrypto扩展,gen_salt函数不存在报错求助

问题:pgcrypto扩展的gen_salt函数找不到,触发器执行报错

我创建了一个用pgcrypto扩展处理员工密码加密的触发器函数,代码如下:

CREATE EXTENSION IF NOT EXISTS pgcrypto SCHEMA public;

CREATE FUNCTION public.on_add_employee_account() RETURNS trigger AS
$add_employee_account$
BEGIN
    IF EXISTS(SELECT FROM public.employees WHERE emp_login = NEW.emp_login) THEN
        RAISE EXCEPTION 'User with such login already exists';
    end if;

    NEW.emp_pass = crypt(format('%s', NEW.emp_pass), gen_salt('md5'));
    RETURN NEW;
end ;

$add_employee_account$ LANGUAGE plpgsql;

CREATE TRIGGER add_employee_account
    BEFORE INSERT OR UPDATE
    ON public.employees
    FOR EACH ROW
EXECUTE PROCEDURE public.on_add_employee_account();

但通过init.db插入初始数据时,触发了报错:

ERROR:  function gen_salt(unknown) does not exist at character 50
No function matches the given name and argument types. You might need to add explicit type casts.
NEW.emp_pass = crypt(format('%s', NEW.emp_pass), gen_salt('md5'))

插入语句:

INSERT INTO public.employees
VALUES (1, 'Mike', 'Brown', '@mike', 'qwerty1234', '+77777777777', 'mikebr@gmail.com', 'MNDP');

我怀疑是所有操作在单事务中执行,pgcrypto扩展还没创建完成就触发了触发器?


解决办法

你的猜测完全正确:PostgreSQL在同一个事务中执行CREATE EXTENSION后,不会立即加载扩展提供的函数,直到事务提交。所以触发器执行时找不到gen_salt。

核心修复步骤

  1. 拆分事务:把CREATE EXTENSION pgcrypto单独放在一个独立事务中执行,提交后再运行触发器创建和数据插入的脚本。
    • 如果是用init.db,可以把扩展创建的代码单独放在一个文件里,先执行它,再执行其他部分。

额外优化建议

  • 替换重复登录检查逻辑:用唯一约束替代触发器里的查询,性能更优:
    ALTER TABLE public.employees ADD CONSTRAINT unique_emp_login UNIQUE (emp_login);
    
  • 简化密码加密代码:format('%s', NEW.emp_pass)是多余的,直接传入原字段即可:
    NEW.emp_pass = crypt(NEW.emp_pass, gen_salt('md5'));
    

内容的提问来源于stack exchange,提问作者prokhor kot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 23:55:06