PLPGSQL 函数 return 的问题,涉及 uuid

Problem with PLPGSQL function return, uuid involved

我想分配序列中的序列号以及自动生成的 uuid。我的 table 看起来像

CREATE TABLE master_serialnumbers
(
    uuident     uuid            PRIMARY KEY DEFAULT uuid_generate_v1(),
    serno       integer         GENERATED ALWAYS AS IDENTITY UNIQUE,
    requester   varchar(20)     NOT NULL
);

我现在可以使用

生成序列号
INSERT INTO master_serialnumbers(requester) VALUES ('XY') 
RETURNING (uuident,serno,requester);

要自动执行此操作并生成包含多个序列号的块,我可以使用如下函数:

CREATE FUNCTION gen_serials_A(num_serials integer, req varchar(20)) 
RETURNS SETOF master_serialnumbers
AS $$
DECLARE
    new_id uuid;
    rr master_serialnumbers%ROWTYPE;        -- or simply RECORD
    tmpSQL TEXT;
BEGIN
    RAISE NOTICE 'generate % serial numbers', num_serials;
    
    CREATE TEMPORARY TABLE tmpIds (id uuid NOT NULL PRIMARY KEY);
    
    FOR i IN 1..num_serials LOOP
        RAISE NOTICE 'serno %', i;
        INSERT INTO master_serialnumbers(space, requester) VALUES (spc, req) 
            RETURNING (uuident) INTO new_id;
        INSERT INTO tmpIds(id) VALUES (new_id);
    END LOOP;

    FOR rr IN EXECUTE 'SELECT * FROM master_serialnumbers 
                       WHERE uuident IN (SELECT id FROM tmpIds)' LOOP
        RETURN NEXT rr;
    END LOOP;

    tmpSQL := 'DROP TABLE tmpIds';
    EXECUTE tmpSQL;

RETURN;
END
$$ LANGUAGE plpgsql;

这确实有效,但将值存储在临时 table 中并有两个循环似乎很麻烦。所以我试着像这样缩短它:

CREATE FUNCTION gen_serials(num_serials integer, req varchar(20)) 
RETURNS SETOF master_serialnumbers
AS $$
DECLARE
    rr master_serialnumbers%ROWTYPE;
BEGIN
    RAISE NOTICE 'generate % serial numbers', num_serials;
    
    FOR i IN 1..num_serials LOOP
        RAISE NOTICE 'serno %', i;
        INSERT INTO master_serialnumbers(requester) VALUES (req)
            RETURNING (uuident,serno,requester) INTO rr;
        RAISE NOTICE 'rr is %', rr;
        RETURN NEXT rr;
    END LOOP;

RETURN;
END
$$ LANGUAGE plpgsql;

– 但是 INSERT 抛出错误

invalid input syntax for type uuid: »(12345678-1234-1234-1234-123456789abc,1,A)«

将声明更改为 rr RECORD 现在会传递 INSERT:

rr is ("(12345678-1234-1234-1234-123456789abc,1,A)")
ERROR:  wrong record type supplied in RETURN NEXT
DETAIL:  Returned type does not match expected type uuid in column 1.

好像都已经转成字符串了

并且将 return 类型也更改为 SETOF RECORD 会产生另一个错误:

ERROR: function with set result called in a context that cannot process set results

(德语错误信息由我翻译回英语,抱歉)。

知道这里发生了什么(没有发生)吗?也许我通过使用带有程序循环的函数来做这件事太啰嗦了?

To automate this and generate a block of several serial numbers, I can use a function

不要搞得这么复杂。使用像

这样的东西
INSERT INTO master_serialnumbers(requester)
VALUES ('XY', 'YZ', 'ZA') 
RETURNING uuident, serno, requester;

INSERT INTO master_serialnumbers(requester)
SELECT UNNEST(ARRAY['XY', 'YZ', 'ZA']) -- useful for parameterised queries
RETURNING uuident, serno, requester;

INSERT INTO master_serialnumbers(requester)
SELECT 'XY'
FROM generate_series(1, 20) -- useful for arbitrary repetition of the same value
RETURNING uuident, serno, requester;

(一个set-returning function to create a series of numbers)