无法从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。
核心修复步骤
- 拆分事务:把
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
相关产品推荐
相关产品推荐

