我正在使用 PostgreSQL pgsql 函数内部的代码。 我有一个合并语句,其中包含多个仅在运行时才知道的元素,并作为参数提供给函数,这需要我将合并语句构建为我执行的动态 SQL 语句。 这些动态元素包括合并的目标表和源数据,我将其作为复合记录数组。
如何将复合记录数组传递到执行语句中,以便合并正常工作? 我知道如何在动态语句中使用数据值、列名和表名,但我还没有破解如何传入表或值数组。
我似乎不知道如何使用 unnest 来做到这一点。 本地临时表似乎在执行事务中没有作用域。 在合并中直接引用的常规表会在函数的并行执行中产生争用和问题。
CREATE TEMPORARY TABLE bulk_data_table OF dbo."compositerecordtype";
INSERT INTO bulk_data_table (cola, colb, colc) SELECT BM.cola, BM.colb, BM.colc FROM UNNEST("user_bulk_data"::compositerecordtype) AS BM;
dynamic_sqlStatement :=
'MERGE INTO ' || "TableName" || ' AS TRG
USING (SELECT cola, colb, colc FROM ' || bulk_data_table || ' AS SRC
ON (TRG.id = SRC.id)
WHEN NOT MATCHED THEN
INSERT (cola, colb, colc) VALUES (SRC.cola, SRC.colb, SRC.colc)
WHEN MATCHED THEN
UPDATE SET colb = SRC.colb, colc = SRC.colc;';
EXECUTE dynamic_sqlStatement
"TableName"
传递到函数中。相反,使用该表名称来转换传入数组。pg_type
中查找目标表。所有常规类型都列出了一个数组版本。这意味着根据传入数组的 pg_typeof()
,您可以查找其基本元素类型,这将是目标表。anyarray()
,这样你就不需要为不同的目标定义多个版本。%1$I
通过 format()
将目标表传递到查询中。$1
通过 execute..using
传递传入的有效负载。create or replace function merge_payload_into_table(
payload anyarray)returns void as $f$
declare base_type text:=(select typelem::regtype
from pg_type
where oid=pg_typeof(payload)::regtype);
begin execute format(
$dsql$
MERGE INTO %1$I AS TRG
USING (SELECT id, cola, colb, colc FROM unnest($1::%1$I[]) ) AS SRC
ON (TRG.id = SRC.id)
WHEN NOT MATCHED THEN
INSERT (cola, colb, colc) VALUES (SRC.cola, SRC.colb, SRC.colc)
WHEN MATCHED THEN
UPDATE SET colb = SRC.colb, colc = SRC.colc;
$dsql$, base_type) USING payload;
end $f$ language plpgsql;
information_schema.columns
中查找列并动态构建 merge
中的列列表,只留下您要匹配的 id
是静态的。如果您想完全动态化,您可以在 pg_index
中查找主键列或唯一列组合,并让
merge..on
条件动态构建。pg_type.typnamespace
。一个简单的测试:
create schema dbo;
create table dbo."compositerecordtype"(
id int generated by default as identity primary key
,cola int
,colb int
,colc int);
set search_path to dbo,public;
insert into "compositerecordtype"(cola,colb,colc)
values(1,2,3)
returning*;
id | 可乐 | 科尔布 | 科尔克 |
---|---|---|---|
1 | 1 | 2 | 3 |
select merge_payload_into_table(array[ row(1,101,102,103)
,row(2,201,202,203)
,row(3,301,302,303)]::compositerecordtype[] );
select*from compositerecordtype;
id | 可乐 | 科尔布 | 科尔克 |
---|---|---|---|
1 | 1 | 102 | 103 |
2 | 201 | 202 | 203 |
3 | 301 | 302 | 303 |