我创建了一个生成发票号码的功能,但是当我这样做时:
select get_generated_kodesj()
显示错误:
关系“transpending_h”不存在 第19行:......终点结束为“KODETRANSNEW”来自transpendi ......
这是我的函数声明:
CREATE FUNCTION get_generated_kodesj()
RETURNS CHAR AS $$
DECLARE kodeSJ CHAR;
BEGIN
SELECT
CASE WHEN MAX(RIGHT("KODETRANS",4)) IS NULL THEN
CONCAT('SJ-',EXTRACT(YEAR FROM NOW()),LPAD(CAST(EXTRACT(MONTH from NOW()) AS CHAR), 2 ,'0'),'0001')
ELSE
CASE WHEN MAX(CAST(RIGHT("KODETRANS",4) AS INTEGER))+1<10 THEN
CONCAT('SJ-',EXTRACT(YEAR FROM NOW()),LPAD(CAST(EXTRACT(MONTH from NOW()) AS CHAR), 2 ,'0'),'000',
MAX(CAST(RIGHT("KODETRANS",4) AS INTEGER))+1)
ELSE
CASE WHEN MAX(CAST(RIGHT("KODETRANS",4) AS INTEGER))+1<100 AND MAX(CAST(RIGHT("KODETRANS",4) AS INTEGER))+1>=10 THEN
CONCAT('SJ-',EXTRACT(YEAR FROM NOW()),LPAD(CAST(EXTRACT(MONTH from NOW()) AS CHAR), 2 ,'0'),'00',
MAX(CAST(RIGHT("KODETRANS",4) AS INTEGER))+1)
ELSE
CASE WHEN MAX(CAST(RIGHT("KODETRANS",4) AS INTEGER))+1<1000 AND MAX(CAST(RIGHT("KODETRANS",4) AS INTEGER))+1>=100 THEN
CONCAT('SJ-',EXTRACT(YEAR FROM NOW()),LPAD(CAST(EXTRACT(MONTH from NOW()) AS CHAR), 2 ,'0'),'0',
MAX(CAST(RIGHT("KODETRANS",4) AS INTEGER))+1)
ELSE
CONCAT('SJ-',EXTRACT(YEAR FROM NOW()),LPAD(CAST(EXTRACT(MONTH from NOW()) AS CHAR), 2 ,'0'),
MAX(CAST(RIGHT("KODETRANS",4) AS INTEGER))+1)
END END END END AS "KODETRANSNEW" INTO kodeSJ
FROM transpending_h
WHERE SUBSTRING("KODETRANS" FROM 5 FOR 4)=CAST(EXTRACT(YEAR from NOW()) AS CHAR)
AND SUBSTRING("KODETRANS" FROM 9 FOR 2)=CAST(EXTRACT(MONTH from NOW()) AS CHAR);
RETURN kodeSJ;
END;
$$ LANGUAGE plpgsql
SECURITY DEFINER
-- Set a secure search_path: trusted schema(s), then 'pg_temp'.
SET search_path = admin, pg_temp;
这可能是什么问题?
答案 0 :(得分:1)
您评论道:
但我已经创建了这个表,在我声明这个函数之前,我运行这个查询(选择一些东西),它可以工作。
您创建了表,但显然不在模式admin
中,这是您的函数的自定义search_path
中唯一的一个(除了临时模式和隐式pg_catalog
) 。检查:
SELECT * FROM pg_tables WHERE tablename = 'transpending_h';
模式限定函数体中的表,错误应该消失。喜欢:myschema.transpending_h
。
相关:
您使用数据类型char
进行操作,这是一个误解:
改为使用text
。
如果可以避免,请不要使用双引号标识符。只是介绍了开销和混乱。
对于这个简单的SELECT
,您不需要plpgsql。我建议使用一个简单的SQL函数。
仔细看看,关于您的功能的 几乎所有 都可以得到改进。基本上,您正在递增每月序列号。可以简化为:
CREATE FUNCTION get_generated_kodesj()
RETURNS text AS
$func$
SELECT to_char(now(), '"SJ-"YYYYMM')
|| COALESCE(to_char(MAX(RIGHT("KODETRANS",4))::int + 1, 'FM0000'), '0001')
FROM transpending_h
WHERE "KODETRANS" LIKE to_char(now(), '"SJ-"YYYYMM"%"')
-- assuming your codes start with "SJ-"; else adapt
$func$ LANGUAGE sql
SECURITY DEFINER
SET search_path = admin, pg_temp;
相关:
但是整个方法仍然受到多用户环境中竞争条件的影响。使用全局serial
或IDENTITY
列(与date
或timestamp
结合使用),而不是尝试创建自己的每月序列。参见:
如果您需要每月序列号,请考虑采用不同的方法来避免多用户环境中的竞争条件: