Pos*_*thu 5 postgresql plpgsql functions array composite-types
我Books在 Postgres 中创建了一个类型,它有 2 个numeric字段和 2 个varchar字段。我想将Books一个函数的数组发送到INSERT匹配表中的那些值。
这是我的类型:
CREATE TYPE Books AS (
V_Book_ID NUMERIC,
V_Row_Num NUMERIC,
V_Book_OWNER TEXT,
V_Book_OWNER_ID TEXT
);
Run Code Online (Sandbox Code Playgroud)
这是我的功能:
CREATE OR REPLACE FUNCTION Update_Table(row_book Books[]) RETURNS TEXT AS $$
DECLARE
Status TEXT;
I_Max integer := array_length(row_book, 1);
BEGIN
FOR I in 1..I_Max
LOOP
INSERT INTO books_table(Book_ID,
Row_Num,
Book_OWNER,
Book_OWNER_ID)
values
(row_book[I].V_Book_ID,
row_book[I].V_Row_Num,
row_book[I].V_Book_OWNER,
row_book[I].V_Book_OWNER_ID);
END LOOP;
STATUS:='Saved';
exception when others then
STATUS:='failure';
RETURN STATUS;
END;
$$ language plpgsql;
Run Code Online (Sandbox Code Playgroud)
如何向函数发送数据,或者如何使用数据调用函数?
前段时间我在 SO 上回答了一个类似的问题,提出与unnest()@a_horse一样的解决方案:
如果books_table与复合类型具有相同的行类型books,则根本不需要创建附加类型,只需使用表的行类型:
CREATE TABLE books_table (
book_id numeric
, row_num numeric
, book_owner text
, book_owner_id text
);
Run Code Online (Sandbox Code Playgroud)
如果您出于某种未声明的原因需要plpgsql 函数:
CREATE TABLE books_table (
book_id numeric
, row_num numeric
, book_owner text
, book_owner_id text
);
Run Code Online (Sandbox Code Playgroud)
使用行值列表调用示例:
SELECT update_table_variadic('(2,100,Arthur,1)', '(2,50,Zaphod,1)');
Run Code Online (Sandbox Code Playgroud)
如果不使用VARIADIC,函数调用将需要一个数组参数。
要么是数组字面量(可选择显式转换):
SELECT update_table('{"(1,100,Arthur,1)","(1,50,Zaphod,1)"}'::books_table[]);
Run Code Online (Sandbox Code Playgroud)
看:
或者您可以使用像@a_horse 演示这样的数组构造函数。数组文字通常更容易提供。
要点:
使用更简单FOREACH的循环遍历数组。看:
除非您知道自己在做什么,否则在 Postgres 中避免使用 CaMeL 大小写名称。
(可选)使用VARIADIC参数来简化函数调用的语法。然后您可以提供行值列表。请注意函数参数的最大数量(默认为 100),如果您使用VARIADIC:
如果不需要捕获异常,也不需要返回字符串 'Saved' / 'Failure',请简化:
CREATE OR REPLACE FUNCTION update_table_set(VARIADIC _books_arr books_table[])
RETURNS void
LANGUAGE sql AS
$func$
INSERT INTO books_table
SELECT * FROM unnest(_books_arr) b;
$func$;
Run Code Online (Sandbox Code Playgroud)
小智 2
要创建类型的数组,请使用显式数组构造函数:
array[(1,100,'Arthur',1), (1,50,'Zaphod',1)]::books[]
Run Code Online (Sandbox Code Playgroud)
因此,要调用您的函数,您需要使用:
select update_table(array[(1,100,'Arthur',1), (1,50,'Zaphod',1)]::books[])
Run Code Online (Sandbox Code Playgroud)
但是您的函数有一个错误:在循环之后缺少 return 语句,因为仅在发生异常时才执行异常块中的语句。
所以你需要这样的东西:
begin
....
STATUS:='Saved';
return status; ---<<< this is missing
exception when others then
STATUS:='failure';
RETURN STATUS; --<<< this is only execute if an exception occurs
END;
Run Code Online (Sandbox Code Playgroud)
或者你需要另一个begin .. end;块:
begin
begin
for ...
end loop;
STATUS:='Saved';
exception when others then
STATUS:='failure';
end;
RETURN STATUS;
END;
Run Code Online (Sandbox Code Playgroud)
不相关,但是:您不需要循环来迭代数组。您可以使用单个语句更有效地做到这一点:
INSERT INTO books_table
(Book_ID, Row_Num, Book_OWNER, Book_OWNER_ID)
select *
from unnest(row_book);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
16884 次 |
| 最近记录: |