Как исправить синтаксическую ошибку при преобразовании процедуры в функцию?

#postgresql

#postgresql

Вопрос:

Я работаю над преобразованием хранимой процедуры SQL Server в хранимую функцию в PostgreSQL. Я преобразовал хранимую процедуру в функцию. После преобразования я запускаю этот скрипт в pgadmin, но он выдает синтаксическую ошибку, близкую к условию if.

Сохраненная функция:

     CREATE OR REPLACE FUNCTION getuserdepartmentlist(p_nUserID  bigInt,p_sRole varchar(100),p_nInstID  bigInt = 0) RETURNS TEXT
        AS $BODY$   
            ----get dept list for non admin users
            DECLARE v_DeptID bigint;
                v_DeptIDList text;
                v_isAdmin int;
                v_isPM int;
                v_isDelgate int;
        BEGIN
         v_DeptIDList :=''; 
         v_isAdmin :=POSITION('Admin' IN p_sRole);
         v_isPM :=POSITION('PM' IN p_sRole);
         v_isDelgate :=POSITION('Delegate' IN p_sRole);

            --Cursor Declaration for Admin/pm
            DECLARE DeptCursor1 CURSOR FOR 
                        SELECT  department.ndept_id 
                                FROM   department
                                WHERE  ninst_id = p_nInstID; 

            --Cursor Declaration for non Admin/pm
            DECLARE DeptCursor2 CURSOR FOR 
                        SELECT  department.ndept_id 
                                FROM    users INNER JOIN
                                    permission ON users.nuser_id = permission.nuser_id INNER JOIN
                                    userrolemapping ON users.nuser_id = userrolemapping.nuser_id INNER JOIN
                                    department ON permission.ndept_inst = department.ninst_id
                                    AND  department.ninst_id = p_nInstID
                                WHERE     
                                    users.nuser_id = p_nUserID and
                                    spermission_type <> 'N' AND
                                    permission.sperm_level = 'D' AND 
                                    users.bis_active = 1 AND 
                                    userrolemapping.nrole_id NOT IN 
                                                (SELECT nrole_id  
                                                    FROM  roles
                                                    WHERE  srole_desc in ('Admin','PM'))                                
                    Union
                        SELECT  department.ndept_id 
                                FROM  users 
INNER JOIN permission ON users.nuser_id = permission.nuser_id 
INNER JOIN userrolemapping ON users.nuser_id = userrolemapping.nuser_id 
INNER JOIN department ON permission.ndept_inst = department.ninst_id
                                AND  department.ninst_id = p_nInstID 
                                WHERE     
                                    users.nuser_id = p_nUserID and
                                    spermission_type  <> 'N' AND
                                    permission.sperm_level = 'I' AND 
                                    users.bis_active = 1 AND 
                                    userrolemapping.nrole_id NOT IN 
                                                (SELECT nrole_id  
                                                    FROM  roles
                                                    WHERE  srole_desc in ('Admin','PM'));

            IF (v_isAdmin > 0) OR (v_isPM > 0) OR (v_isDelgate >0)
                THEN
                    --Cursor for Admin amp; PM
                    OPEN DeptCursor1;
                    FETCH NEXT FROM; DeptCursor1
                    INTO v_DeptID

                    WHILE FOUND
                        LOOP
                            v_DeptIDList := v_DeptIDList || '' || cast(v_DeptID as varchar(1)) || ','; 

                                -- Get the next vendor.
                        FETCH NEXT FROM; DeptCursor1 
                        INTO v_DeptID 
                        END LOOP; 
                    CLOSE DeptCursor1;
            ELSE    
                    --Cursor for Non Admin
                    OPEN DeptCursor2;

                    FETCH NEXT FROM; DeptCursor2 
                    INTO v_DeptID

                    WHILE FOUND
                        LOOP
                            v_DeptIDList := v_DeptIDList || '' || cast(v_DeptID as varchar(1)) || ','; 

                                -- Get the next vendor.
                        FETCH NEXT FROM; DeptCursor2 
                        INTO v_DeptID 
                        END LOOP; 
                    CLOSE DeptCursor2;

            END IF;         
                    RETURN(v_DeptIDList);
        END;
        $$LANGUAGE plpgsql;
  

Ошибка:

Он показывает синтаксическую ошибку рядом с условием if.Я добавил код ошибки ниже:

 ERROR:  syntax error at or near "IF"
LINE 61:  IF (v_isAdmin > 0) OR (v_isPM > 0) OR (v_isDelgate >0)
          ^
  

Комментарии:

1. Я исправил свою ошибку. Необходимо объявить курсор вне тела функции.

Ответ №1:

Этот код работает нормально, без ошибок.Объявление курсора неверно в приведенном выше коде.

 CREATE OR REPLACE FUNCTION getuserdepartmentlist(p_nUserID  bigInt,p_sRole varchar(100),p_nInstID  bigInt = 0)
      RETURNS TEXT
AS
$BODY$  
    ----get dept list for non admin users
    DECLARE v_DeptID bigint;
        v_DeptIDList text;
        v_isAdmin int;
        v_isPM int;
        v_isDelgate int;
        --Cursor Declaration for Admin/pm
    DECLARE DeptCursor1 CURSOR FOR 
                SELECT  department.ndept_id 
                        FROM   department
                        WHERE  ninst_id = p_nInstID; 


    --Cursor Declaration for non Admin/pm
    DECLARE DeptCursor2 CURSOR FOR 
                SELECT  department.ndept_id 
                        FROM    users INNER JOIN
                            permission ON users.nuser_id = permission.nuser_id INNER JOIN
                            userrolemapping ON users.nuser_id = userrolemapping.nuser_id INNER JOIN
                            department ON permission.ndept_inst = department.ninst_id
                            AND  department.ninst_id = p_nInstID
                        WHERE     
                            users.nuser_id = p_nUserID and
                            spermission_type <> 'N' AND
                            permission.sperm_level = 'D' AND 
                            users.bis_active = 1 AND 
                            userrolemapping.nrole_id NOT IN 
                                        (SELECT nrole_id  
                                            FROM  roles
                                            WHERE  srole_desc in ('Admin','PM'))                                
            Union
                SELECT     department.ndept_id 
                        FROM    users INNER JOIN
                                    permission ON users.nuser_id = permission.nuser_id INNER JOIN
                            userrolemapping ON users.nuser_id = userrolemapping.nuser_id INNER JOIN
                            department ON permission.ndept_inst = department.ninst_id
                            AND  department.ninst_id = p_nInstID 
                        WHERE     
                            users.nuser_id = p_nUserID and
                            spermission_type  <> 'N' AND
                            permission.sperm_level = 'I' AND 
                            users.bis_active = 1 AND 
                            userrolemapping.nrole_id NOT IN 
                                        (SELECT nrole_id  
                                            FROM  roles
                                            WHERE  srole_desc in ('Admin','PM'));



BEGIN

 v_DeptIDList :=''; 
 v_isAdmin :=POSITION('Admin' IN p_sRole);
 v_isPM :=POSITION('PM' IN p_sRole);
 v_isDelgate :=POSITION('Delegate' IN p_sRole);


    IF (v_isAdmin > 0) OR (v_isPM > 0) OR (v_isDelgate >0)
        THEN
            --Cursor for Admin amp; PM
            OPEN DeptCursor1;

            FETCH NEXT FROM DeptCursor1
            INTO v_DeptID;

            WHILE FOUND
                LOOP
                    v_DeptIDList := v_DeptIDList || '' || cast(v_DeptID as varchar(1)) || ','; 

                        -- Get the next vendor.
                FETCH NEXT FROM DeptCursor1 
                INTO v_DeptID; 
                END LOOP; 
            CLOSE DeptCursor1;
    ELSE    
            --Cursor for Non Admin
            OPEN DeptCursor2;

            FETCH NEXT FROM DeptCursor2 
            INTO v_DeptID;

            WHILE FOUND
                LOOP
                    v_DeptIDList := v_DeptIDList || '' || cast(v_DeptID as varchar(1)) || ','; 

                        -- Get the next vendor.
                FETCH NEXT FROM DeptCursor2 
                INTO v_DeptID; 
                END LOOP; 
            CLOSE DeptCursor2;

    END IF;                             
            --End cursor declaration 


            if len(v_DeptIDList)> 0 then 
                v_DeptIDList := SUBSTRING(v_DeptIDList,1,len(v_DeptIDList)-1);
            else
                v_DeptIDList :='0';
            end if;

            RETURN(v_DeptIDList);
END;
$BODY$
LANGUAGE plpgsql;
  

Комментарии:

1. Вы можете упростить (и сделать это намного эффективнее), удалив бесполезные циклы и курсоры. Что-то вроде этого dpaste.com/0289YSM