提问人:Jules78 提问时间:9/19/2023 最后编辑:Pavel StehuleJules78 更新时间:9/21/2023 访问量:40
pgsql 函数无法执行
pgsql function cannot execute
问:
我尝试执行此函数:
CREATE OR REPLACE FUNCTION public.increases_chrono(
chrono_seq_name text,
chrono_id_name text)
RETURNS TABLE(chrono_id bigint)
LANGUAGE 'plpgsql'
COST 100
VOLATILE PARALLEL UNSAFE
ROWS 1000
AS $$
DECLARE
retval bigint;
BEGIN
-- Check if sequence exist, if not create
IF NOT EXISTS (SELECT 0 FROM pg_class where relname = chrono_seq_name ) THEN
EXECUTE 'CREATE SEQUENCE "' || chrono_seq_name || '" INCREMENT 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1;';
END IF;
-- Check if chrono exist in parameters table, if not create
IF NOT EXISTS (SELECT 0 FROM parameters where id = chrono_id_name ) THEN
EXECUTE 'INSERT INTO parameters (id, param_value_int) VALUES ( ''' || chrono_id_name || ''', 1)';
END IF;
-- Get next value of sequence, update the value in parameters table before returning the value
SELECT nextval(chrono_seq_name) INTO retval;
UPDATE parameters set param_value_int = retval WHERE id = chrono_id_name;
RETURN QUERY SELECT retval;
END;
$$;
ALTER FUNCTION public.increases_chrono(text, text)
OWNER TO maarch;
但是当我像这样称呼他时:
SELECT increases_chrono('chrono_DAP_2023_seq' ,'chrono_DAP_2023')
我有错误:错误:关系“chrono_dap_2023_seq”不存在 上下文:SQL 语句“SELECT nextval(chrono_seq_name)” PL/pgSQL 函数 increase_chrono(text,text) SQL 语句第 14 行
SQL 状态:42P01 有人可以帮我
答:
0赞
Pavel Stehule
9/20/2023
#1
区分大小写存在问题。看起来像CREATE
CREATE SEQUENCE "chrono_DAP_2023_seq"
INCREMENT 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 1 CACHE 1;
标识符位于双引号内 - 因此区分大小写。
但是当你尝试使用它时,变量不会在双引号内传递,因此它不是区分大小写的标识符。使用功能修复它:chrono_seq_name
quote_ident
-- Get next value of sequence, update the value in parameters
---table before returning the value
SELECT nextval(quote_ident(chrono_seq_name)) INTO retval;
构建字符串 like 是错误的。永远不要这样做。它容易受到 SQL 注入的攻击。您应该再次使用函数,或带有占位符的函数:EXECUTE 'CREATE SEQUENCE "' || chrono_seq_name || '" INC ...
quote_ident
format
%I
EXECUTE format('CREATE SEQUENCE %I', chrono_seq_name);
还有另一个问题。没有任何理由,返回表是适得其反的。表函数的调用成本更高。这个函数应该只返回 bigint:
CREATE OR REPLACE FUNCTION public.increases_chrono(
chrono_seq_name text,
chrono_id_name text)
RETURNS bigint
LANGUAGE 'plpgsql'
COST 100
VOLATILE PARALLEL UNSAFE
ROWS 1000
AS $$
BEGIN
...
RETURN retval;
END;
$$;
评论
0赞
Jules78
9/21/2023
谢谢。。。现在的问题是指令IF NOT EXIST,以验证是否创建了序列
0赞
Pavel Stehule
9/21/2023
@Jules78 - 不,应该没有任何问题 - 列 relname 那里不包含双引号,并且 pg 中的字符串 compare 区分大小写。
评论