table/setof 类型的 PostgreSQL 数组
PostgreSQL array of type table/setof
我需要在 postgresql 中编写一个函数,该函数必须根据条件从 table 'pick' 整行,然后将它们插入数组,最后 return 该数组.
我实际上是在查询我需要的行,但是 table 中有一个特殊的列,我必须首先评估它是否可以检索它(插入到数组中),具体取决于正在查询的用户类型(客户或工作人员)。
例如:
特殊列名为“watchers”,有两个变体:'my_team' 和 'only_me',还有一个名为“user_id”的列。
如果该列显示 'my_team',该行可以毫无问题地插入到数组中,但如果显示 'only_me',我必须比较调用该函数的用户的 id 和用户注册在那一行,如果匹配我可以把它插入到数组中,否则我不能。
事情是,正如我到目前为止所读到的那样,它似乎不能用数组来完成,所以我想知道是否有另一种方法可以做到这一点,也许有一个额外的 table 什么的?
感谢您的帮助!
这是我的代码:
CREATE OR REPLACE FUNCTION public.calculates_permission_by_task(task_id integer)
RETURNS SETOF permission
LANGUAGE plpgsql
STABLE
AS $function$
DECLARE
num int := 5;
record permission;
ret_permissions permission [];
BEGIN
FOR record IN (select
p.id, p.slug
from task as t
join service_request_form as srf on t.service_request_form_id = srf.id
join service_group as sg on srf.service_group_id = sg.id
join worker_group as wg on wg.service_group_id = sg.id
join worker_group_member as wgm on wg.id = wgm.worker_group_id
join role as r on r.id = wgm.role_id
join permission_role as pr on r.id = pr.role_id
join permission as p on p.id = pr.permission_id
where t.id = task_id
and wgm.user_id = 'LFudaU6jzid4SKFlU8MgFAwezyP2'
and pr.value <> 'off'
and pr.value <> 'no')
LOOP
/* Here is where I pretend to do the comparison and insert data into the array */
ret_permission := array_append(ret_permissions, record.id);
END LOOP;
RETURN ret_permissions;
END
$function$
您可以在查询本身中实现逻辑。
假设您引用的 user_id
列对应于已在查询中的 wgm.user_id
,则查询的 where
子句将变为:
where
t.id = task_id
and pr.value not in ('off', 'no')
and (
?.watchers = 'my_team'
or (
?.watchers = 'only_me'
or wgm.user_id = 'LFudaU6jzid4SKFlU8MgFAwezyP2'
)
)
你不知道 table watches
属于哪个,所以我使用了 ?
,你需要将其替换为相关的 table 别名。
如果 watchers
只有两个可能的值,那么我们可以简化谓词:
where
t.id = task_id
and pr.value not in ('off', 'no')
and (?.watchers = 'my_team' or wgm.user_id = 'LFudaU6jzid4SKFlU8MgFAwezyP2')
- 你不需要数组
- 你不需要游标循环
- 你甚至不需要 plpgsql
- 普通 SQL 就足够了:
CREATE TABLE permission (
id integer
, slug text
);
INSERT INTO permission(id,slug) VALUES (1,'WTF' );
CREATE TABLE task (
id integer
, service_request_form_id integer
);
INSERT INTO task(id, service_request_form_id) VALUES (1,1 );
CREATE TABLE service_request_form (
id integer
, service_group_id integer
);
INSERT INTO service_request_form(id, service_group_id) VALUES (1,1 );
CREATE TABLE service_group (
id integer
);
INSERT INTO service_group(id) VALUES (1);
CREATE TABLE worker_group (
id integer
, service_group_id integer
);
INSERT INTO worker_group(id, service_group_id) VALUES (1,1 );
CREATE TABLE worker_group_member (
worker_group_id integer
, role_id integer
, user_id text
);
INSERT INTO worker_group_member(worker_group_id, role_id,user_id) VALUES (1,1,'LFudaU6jzid4SKFlU8MgFAwezyP2' );
CREATE TABLE zrole (
id integer
);
INSERT INTO zrole(id) VALUES (1 );
CREATE TABLE permission_role (
role_id integer
, permission_id integer
, value text
);
INSERT INTO permission_role(role_id,permission_id,value) VALUES (1,1,'Yes' );
CREATE OR REPLACE FUNCTION public.calculates_permission_by_task(task_id integer)
RETURNS SETOF permission
LANGUAGE sql STABLE SECURITY INVOKER ROWS 30 -- COST 1
AS $func$
SELECT p.id, p.slug
FROM permission as p
WHERE EXISTS (
SELECT *
FROM task as t
JOIN service_request_form as srf
on t.service_request_form_id = srf.id
JOIN service_group as sg
on srf.service_group_id = sg.id
JOIN worker_group as wg
on wg.service_group_id = sg.id
JOIN worker_group_member as wgm
on wg.id = wgm.worker_group_id
JOIN zrole as zr
on zr.id = wgm.role_id
JOIN permission_role as pr
on zr.id = pr.role_id
WHERE p.id = pr.permission_id
AND t.id = task_id
and wgm.user_id = 'LFudaU6jzid4SKFlU8MgFAwezyP2'
and pr.value NOT IN( 'off' , 'no' )
-- -------------------------
-- Add the needed logic
-- (From @GMB) here
-- -------------------------
);
$func$
;
-- Usage:
-- --------------
SELECT * -- p.id, p.slug
FROM public.calculates_permission_by_task(42);
我需要在 postgresql 中编写一个函数,该函数必须根据条件从 table 'pick' 整行,然后将它们插入数组,最后 return 该数组.
我实际上是在查询我需要的行,但是 table 中有一个特殊的列,我必须首先评估它是否可以检索它(插入到数组中),具体取决于正在查询的用户类型(客户或工作人员)。
例如:
特殊列名为“watchers”,有两个变体:'my_team' 和 'only_me',还有一个名为“user_id”的列。
如果该列显示 'my_team',该行可以毫无问题地插入到数组中,但如果显示 'only_me',我必须比较调用该函数的用户的 id 和用户注册在那一行,如果匹配我可以把它插入到数组中,否则我不能。
事情是,正如我到目前为止所读到的那样,它似乎不能用数组来完成,所以我想知道是否有另一种方法可以做到这一点,也许有一个额外的 table 什么的?
感谢您的帮助!
这是我的代码:
CREATE OR REPLACE FUNCTION public.calculates_permission_by_task(task_id integer)
RETURNS SETOF permission
LANGUAGE plpgsql
STABLE
AS $function$
DECLARE
num int := 5;
record permission;
ret_permissions permission [];
BEGIN
FOR record IN (select
p.id, p.slug
from task as t
join service_request_form as srf on t.service_request_form_id = srf.id
join service_group as sg on srf.service_group_id = sg.id
join worker_group as wg on wg.service_group_id = sg.id
join worker_group_member as wgm on wg.id = wgm.worker_group_id
join role as r on r.id = wgm.role_id
join permission_role as pr on r.id = pr.role_id
join permission as p on p.id = pr.permission_id
where t.id = task_id
and wgm.user_id = 'LFudaU6jzid4SKFlU8MgFAwezyP2'
and pr.value <> 'off'
and pr.value <> 'no')
LOOP
/* Here is where I pretend to do the comparison and insert data into the array */
ret_permission := array_append(ret_permissions, record.id);
END LOOP;
RETURN ret_permissions;
END
$function$
您可以在查询本身中实现逻辑。
假设您引用的 user_id
列对应于已在查询中的 wgm.user_id
,则查询的 where
子句将变为:
where
t.id = task_id
and pr.value not in ('off', 'no')
and (
?.watchers = 'my_team'
or (
?.watchers = 'only_me'
or wgm.user_id = 'LFudaU6jzid4SKFlU8MgFAwezyP2'
)
)
你不知道 table watches
属于哪个,所以我使用了 ?
,你需要将其替换为相关的 table 别名。
如果 watchers
只有两个可能的值,那么我们可以简化谓词:
where
t.id = task_id
and pr.value not in ('off', 'no')
and (?.watchers = 'my_team' or wgm.user_id = 'LFudaU6jzid4SKFlU8MgFAwezyP2')
- 你不需要数组
- 你不需要游标循环
- 你甚至不需要 plpgsql
- 普通 SQL 就足够了:
CREATE TABLE permission (
id integer
, slug text
);
INSERT INTO permission(id,slug) VALUES (1,'WTF' );
CREATE TABLE task (
id integer
, service_request_form_id integer
);
INSERT INTO task(id, service_request_form_id) VALUES (1,1 );
CREATE TABLE service_request_form (
id integer
, service_group_id integer
);
INSERT INTO service_request_form(id, service_group_id) VALUES (1,1 );
CREATE TABLE service_group (
id integer
);
INSERT INTO service_group(id) VALUES (1);
CREATE TABLE worker_group (
id integer
, service_group_id integer
);
INSERT INTO worker_group(id, service_group_id) VALUES (1,1 );
CREATE TABLE worker_group_member (
worker_group_id integer
, role_id integer
, user_id text
);
INSERT INTO worker_group_member(worker_group_id, role_id,user_id) VALUES (1,1,'LFudaU6jzid4SKFlU8MgFAwezyP2' );
CREATE TABLE zrole (
id integer
);
INSERT INTO zrole(id) VALUES (1 );
CREATE TABLE permission_role (
role_id integer
, permission_id integer
, value text
);
INSERT INTO permission_role(role_id,permission_id,value) VALUES (1,1,'Yes' );
CREATE OR REPLACE FUNCTION public.calculates_permission_by_task(task_id integer)
RETURNS SETOF permission
LANGUAGE sql STABLE SECURITY INVOKER ROWS 30 -- COST 1
AS $func$
SELECT p.id, p.slug
FROM permission as p
WHERE EXISTS (
SELECT *
FROM task as t
JOIN service_request_form as srf
on t.service_request_form_id = srf.id
JOIN service_group as sg
on srf.service_group_id = sg.id
JOIN worker_group as wg
on wg.service_group_id = sg.id
JOIN worker_group_member as wgm
on wg.id = wgm.worker_group_id
JOIN zrole as zr
on zr.id = wgm.role_id
JOIN permission_role as pr
on zr.id = pr.role_id
WHERE p.id = pr.permission_id
AND t.id = task_id
and wgm.user_id = 'LFudaU6jzid4SKFlU8MgFAwezyP2'
and pr.value NOT IN( 'off' , 'no' )
-- -------------------------
-- Add the needed logic
-- (From @GMB) here
-- -------------------------
);
$func$
;
-- Usage:
-- --------------
SELECT * -- p.id, p.slug
FROM public.calculates_permission_by_task(42);