簡體   English   中英

PostgreSQL 表/setof 類型數組

[英]PostgreSQL array of type table/setof

我需要在 postgresql 中編寫一個 function 代碼,它必須根據條件從表中“挑選”整行,然后將它們插入到數組中,最后返回該數組。

我實際上是在查詢我需要的行,但是表中有一個特殊的列,我必須首先評估它,看看我是否可以檢索它(插入到數組中),具體取決於正在執行查詢的用戶類型(客戶或工人)。

例如:

特殊列名為“watchers”,有兩個變體:“my_team”和“only_me”,還有一個名為“user_id”的列。

如果該列顯示“my_team”,則該行可以毫無問題地插入到數組中,但如果它顯示“only_me”,我必須比較調用 function 的用戶的 ID 和在該行中注冊的用戶,如果它們匹配我可以把它插入到數組中,否則我不能。

事情是,正如我到目前為止所讀到的那樣,它似乎不能用 arrays 來完成,所以我想知道是否有另一種方法可以做到這一點,也許有一張額外的桌子或什么的?

謝謝你的幫助!

這是我的代碼:

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'
        )
    )

你不告訴watches屬於哪個表,所以我用了? ,您需要將其替換為相關的表別名。

如果watchers只有兩個可能的值,那么我們可以簡化謂詞:

where 
    t.id = task_id
    and pr.value not in ('off', 'no')
    and (?.watchers = 'my_team' or wgm.user_id = 'LFudaU6jzid4SKFlU8MgFAwezyP2')
  • 你不需要數組
  • 你不需要 cursor 循環
  • 你甚至不需要 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);
                                                                                                                                                                         

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM