1

我创建了一个生成发票编号的函数,但是当我这样做时:

select get_generated_kodesj()

它显示一个错误:

关系“transpending_h”不存在第
19 行:...END END END AS “KODETRANSNEW” FROM 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;

这里可能有什么问题?

4

1 回答 1

1

你评论说:

但我已经创建了这个表,在我声明这个函数之前,我运行这个查询(选择一些东西),它可以工作。

您创建了表,但显然不在 schemaadmin中,这是您的函数自定义中唯一的一个search_path(除了 temp schema 和 implicit pg_catalog)。查看:

SELECT * FROM pg_tables WHERE tablename = 'transpending_h';

模式限定函数体中的表,错误应该消失。喜欢:myschema.transpending_h

有关的:

旁白

  • 您使用数据类型进行操作char,这是一个误解:

    改为使用text

  • 如果可以避免的话,根本不要使用双引号标识符。只是引入了开销和混乱。

  • 你不需要 plpgsql 来完成这个简单的SELECT. 我建议使用普通的 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;

有关的:

但是整个方法在多用户环境中仍然受到竞争条件的影响。使用全局serialIDENTITY列(与dateor组合timestamp)而不是尝试创建自己的每月序列。看:

如果您需要每月的序列号,请考虑另一种方法来避免多用户环境中的竞争条件:

于 2018-04-20T12:13:08.743 回答