【问题标题】:Add IF ELSE statment添加 IF ELSE 语句
【发布时间】:2020-09-04 06:44:06
【问题描述】:

我在 PHP 中有类似的函数,

if (  $busyUsersIDS ) {
 SELECT statment 
ELSE {
SELECT statment
 }

到目前为止,我将其转换为 Oracle SQL 中的函数,现在的主要问题是添加 IF ELSE,这对我来说就像初学者一样很难,无论我尝试什么,我总是会出错

FUNCTION GET_MOMENT_PROJECT_USERS(p_busyUsersID IN INT)
   RETURN SYS_REFCURSOR IS 
    rc  SYS_REFCURSOR;
    /*getBusyUsersIDS*/
 BEGIN
  OPEN rc FOR
    CASE bussyUserID WHEN bussyUserID THEN
        SELECT u.*,
                ur.Roles 
        FROM 
                users u 
        INNER JOIN 
                user_roles ur 
        ON 
                u.User_roleID = ur.id 
        WHERE 
                u.UserID NOT IN (p_busyUsersID) 
        AND 
                u.Surname IS NOT NULL
        AND 
                u.Lastname IS NOT NULL 
        ORDER BY
                u.ProjectPlanSortIndex;

        ELSE  
                            
        SELECT  u.*, 
                ur.Roles 
        FROM 
                users u 
        INNER JOIN 
                user_roles ur 
        ON 
                u.User_roleID = ur.id 
        WHERE 
                u.Surname IS NOT NULL 
        AND 
                u.Lastname IS NOT NULL 
        ORDER BY 
                u.ProjectPlanSortIndex;
     END;
  RETURN rc;
END GET_BUSY_USERS_IDS;

到目前为止,我得到了两个错误

错误(524,9):PLS-00103:在预期以下之一时遇到符号“SELECT”:( - + case mod new not null continue avg count current exists max min prior sql stddev sum variance execute forall merge时间时间戳间隔日期管道

错误(528,3):PLS-00103:在预期以下之一时遇到符号“INNER”:, ;对于有相交减去顺序的组,在连接处开始联合

谁能告诉我我在哪里做错了,这里出了什么问题?

【问题讨论】:

  • 您在滥用open for 语法。我宁愿写case when busyuserid = someid then open rc for select ...; when busyuserid = otherid then open cursor for otherselect; else open rc for anotherselect; end case;之类的东西
  • 我不想总是在初学者中只打开一次 rc FOR。所以像这样OPEN rc FOR IF condition THEN {SELECT} ELSE {SELECT}
  • 整个设计看起来有缺陷。你有busyUsersIDS,这意味着你可以有多个,但是你只传递一个INT输入类型。您是否在某个表中有忙碌的用户,最好只加入该表而不是创建可以实现加入逻辑的函数。

标签: sql oracle plsql


【解决方案1】:

对于初学者如何应对这种语法问题,我建议你练习将其简化为尽可能最小的示例,以免被连接逻辑分散注意力。

例如,您可以快速测试一下,看看它行不通

declare
    rc sys_refcursor;
begin
    open rc for
        case
            when 1 = 1 then select * from dual  -- not valid
        end;
end;

失败了

ORA-06550: line 6, column 29:
PLS-00103: Encountered the symbol "SELECT" when expecting one of the following: ...

因为open rc for select 语法必须是单个语句,并且不能与条件逻辑分开。

注意没有create function、参数或连接等使事情复杂化。理顺语法后,您可以将所有这些重新添加。 case 语句语法为 here。 (请注意,case 有几种不同的类型。)它必须是任一

declare
    rc sys_refcursor;
begin
    case
        when 1 = 1 then
            open rc for select * from dual;
    end case;
end;

或使用if的等价物:

declare
    rc sys_refcursor;
begin
    if 1 = 1 then
        open rc for select * from dual;
    end if;
end;

【讨论】:

    【解决方案2】:

    这不是有效的语法。您可以这样做(正如 Florin Ghita 在评论中建议的那样):

    FUNCTION GET_MOMENT_PROJECT_USERS(p_busyUsersID IN INT)
       RETURN SYS_REFCURSOR IS 
        rc  SYS_REFCURSOR;
        /*getBusyUsersIDS*/
     BEGIN
      CASE bussyUserID WHEN bussyUserID THEN
        OPEN rc FOR
            SELECT u.*,
                    ur.Roles 
            FROM 
                    users u 
            INNER JOIN 
                    user_roles ur 
            ON 
                    u.User_roleID = ur.id 
            WHERE 
                    u.UserID NOT IN (p_busyUsersID) 
            AND 
                    u.Surname IS NOT NULL
            AND 
                    u.Lastname IS NOT NULL 
            ORDER BY
                    u.ProjectPlanSortIndex;
    
      ELSE  
         OPEN rc FOR
            SELECT  u.*, 
                    ur.Roles 
            FROM 
                    users u 
            INNER JOIN 
                    user_roles ur 
            ON 
                    u.User_roleID = ur.id 
            WHERE 
                    u.Surname IS NOT NULL 
            AND 
                    u.Lastname IS NOT NULL 
            ORDER BY 
                    u.ProjectPlanSortIndex;
      END CASE;
      RETURN rc;
    END GET_BUSY_USERS_IDS;
    

    或者您可以将条件移动到单个查询的 WHERE 子句中,例如:

    FUNCTION GET_MOMENT_PROJECT_USERS(p_busyUsersID IN INT)
       RETURN SYS_REFCURSOR IS 
        rc  SYS_REFCURSOR;
        /*getBusyUsersIDS*/
     BEGIN
      CASE bussyUserID WHEN bussyUserID THEN
        OPEN rc FOR
            SELECT u.*,
                    ur.Roles 
            FROM 
                    users u 
            INNER JOIN 
                    user_roles ur 
            ON 
                    u.User_roleID = ur.id 
            WHERE 
                    (bussyUserID != bussyUserID
                     OR u.UserID NOT IN (p_busyUsersID))
            AND 
                    u.Surname IS NOT NULL
            AND 
                    u.Lastname IS NOT NULL 
            ORDER BY
                    u.ProjectPlanSortIndex;
    
      END CASE;
      RETURN rc;
    END GET_BUSY_USERS_IDS;
    

    但是,如果条件 bussyUserID != bussyUserID 的任一侧都可以为 null,那么如果不对处理 null 进行一些更改,这将无法正常工作。

    (注意:当您将bussyUserID 与自身进行比较时,您的情况没有意义!)

    【讨论】:

    • 感谢您的回答。但是,我刚刚意识到这种代码的和平,我发现busyUserID 不能与它自己比较。但是我需要找到一些更好的解决方案
    猜你喜欢
    • 1970-01-01
    • 2020-02-21
    • 2019-04-09
    • 1970-01-01
    • 1970-01-01
    • 2017-02-05
    • 2015-07-06
    • 2012-08-05
    相关资源
    最近更新 更多