输出参数值显示为'无效标识符'

时间:2016-11-08 10:08:49

标签: oracle plsql

我正在尝试从临时创建的表中检索值。但返回值会引发错误'无效标识符

create or replace procedure edu_stream (input in varchar2,vals out varchar2)
    as
    inp varchar2(30);
    valu varchar2(30);
    begin
    inp:=input;
    if inp='secondary education' then

         Execute immediate'WITH secedu as (
    (SELECT "ICSE" as name FROM dual ) UNION
    (SELECT "CBSE" as name FROM dual ) UNION
    (SELECT "STATE BOARD" as name FROM dual)
    )        
    SELECT name into valu from(SELECT name
        FROM  secedu ORDER BY DBMS_RANDOM.RANDOM)where rownum<2';

        vals:=valu;

    else 
    if inp='intermediate education' then

      Execute immediate'WITH intedu as (
    (SELECT "MPC" as name FROM dual ) UNION
    (SELECT "BIPC" as name FROM dual ) UNION
    (SELECT "MBIPC" as name FROM dual) UNION
    (SELECT "CEC" as name FROM dual)
    )        
    SELECT name into valu from(SELECT name
        FROM intedu ORDER BY DBMS_RANDOM.RANDOM)where rownum<2'; 

        vals:=valu;

        else 
    if inp='Graduation' then

      Execute immediate'WITH gedu as (
    (SELECT "ECE" as name FROM dual ) UNION
    (SELECT "CSE" as name FROM dual ) UNION
    (SELECT "CE" as name FROM dual) UNION
    (SELECT "EEE" as name FROM dual)UNION
    (SELECT "ME" as name FROM dual)UNION
    (SELECT "AE" as name FROM dual)UNION
    (SELECT "BIOTECH" as name FROM dual)UNION
    (SELECT "EIE" as name FROM dual)
    )       
    SELECT name into valu from(SELECT name
        FROM gedu ORDER BY DBMS_RANDOM.RANDOM)where rownum<2'; 

        vals:=valu;


        else 
    if inp='post-graduation' then

      Execute immediate'WITH pgedu as (
    (SELECT "MCA" as name FROM dual ) UNION
    (SELECT "MTECH" as name FROM dual ) UNION
    (SELECT "MSC" as name FROM dual) UNION
    (SELECT "MBA" as name FROM dual)
    )        
    SELECT name into valu from(SELECT name
        FROM pgedu ORDER BY DBMS_RANDOM.RANDOM)where rownum<2'; 

        vals:=valu;

       else 
    if inp='phd'then

     Execute immediate' WITH phdedu as (
    (SELECT "Doctorate of philosophy" as name FROM dual ) UNION
    (SELECT "doctorate of medicine" as name FROM dual ) UNION
    (SELECT "doctorate of science" as name FROM dual) UNION
    (SELECT "Doctorate of computer sciences" as name FROM dual)
    )        
    SELECT name into valu from(SELECT name
        FROM phdgedu ORDER BY DBMS_RANDOM.RANDOM)where rownum<2'; 

        vals:=valu;
    end if;
    end if;
    end if;
    end if;
    end if;
    end;

执行:

declare 
value1 varchar2(30);
cv varchar2(30);
begin
cv:='secondary education';
edu_stream(cv,value1);
dbms_output.put_line('val is'||value1);
end;

错误报告:

  

在命令的第2行开始出错:declare value1 varchar2(30);简历   VARCHAR2(30);开始cv:=&#39;中学教育&#39 ;; edu_stream(CV,值1);   dbms_output.put_line(&#39; val是&#39; || value1);结束;错误报告:ORA-00904:   &#34; ICSE&#34;:无效标识符ORA-06512:at&#34; DATAFOCUS_GROUP.EDU_STREAM&#34;,   第9行ORA-06512:第6行   00904. 00000 - &#34;%s:无效标识符&#34;   *原因:
  *操作:

如果我使用&#39; ICSE&#39;而不是&#34; ICSE&#34;

错误显示 -

  

PLS-00103:遇到符号&#34; ICSE&#34;当期待其中一个   以下:
  ERROR 103 *&amp; = - +; &LT; /&gt;在in是mod余数而不是rem   返回
  返回&lt;&gt;或!=或〜=&gt; =&lt; =&lt;&gt;和或   喜欢like2 like4 likec之间使用|| multiset散装
  成员submultiset

3 个答案:

答案 0 :(得分:5)

您可以避免使用动态SQL;另外,可能是由于动态sql造成的混乱,您使用的是"而不是'。 您可以将代码重写为:

CREATE OR REPLACE PROCEDURE edu_stream(input IN VARCHAR2, vals OUT VARCHAR2) AS
    inp                                     VARCHAR2(30);
    valu                                    VARCHAR2(30);
BEGIN
    inp    := input;

    IF inp = 'secondary education'
    THEN
        WITH secedu AS
                 ((SELECT 'ICSE' AS name FROM DUAL)
                  UNION
                  (SELECT 'CBSE' AS name FROM DUAL)
                  UNION
                  (SELECT 'STATE BOARD' AS name FROM DUAL))
        SELECT name
          INTO valu
          FROM (  SELECT name
                    FROM secedu
                ORDER BY DBMS_RANDOM.RANDOM)
         WHERE ROWNUM < 2;

        vals    := valu;
    ELSE
        IF inp = 'intermediate education'
        THEN
            WITH intedu AS
                     ((SELECT 'MPC' AS name FROM DUAL)
                      UNION
                      (SELECT 'BIPC' AS name FROM DUAL)
                      UNION
                      (SELECT 'MBIPC' AS name FROM DUAL)
                      UNION
                      (SELECT 'CEC' AS name FROM DUAL))
            SELECT name
              INTO valu
              FROM (  SELECT name
                        FROM intedu
                    ORDER BY DBMS_RANDOM.RANDOM)
             WHERE ROWNUM < 2;

            vals    := valu;
        ELSE
            IF inp = 'Graduation'
            THEN
                WITH gedu AS
                         ((SELECT 'ECE' AS name FROM DUAL)
                          UNION
                          (SELECT 'CSE' AS name FROM DUAL)
                          UNION
                          (SELECT 'CE' AS name FROM DUAL)
                          UNION
                          (SELECT 'EEE' AS name FROM DUAL)
                          UNION
                          (SELECT 'ME' AS name FROM DUAL)
                          UNION
                          (SELECT 'AE' AS name FROM DUAL)
                          UNION
                          (SELECT 'BIOTECH' AS name FROM DUAL)
                          UNION
                          (SELECT 'EIE' AS name FROM DUAL))
                SELECT name
                  INTO valu
                  FROM (  SELECT name
                            FROM gedu
                        ORDER BY DBMS_RANDOM.RANDOM)
                 WHERE ROWNUM < 2;

                vals    := valu;
            ELSE
                IF inp = 'post-graduation'
                THEN
                    WITH pgedu AS
                             ((SELECT 'MCA' AS name FROM DUAL)
                              UNION
                              (SELECT 'MTECH' AS name FROM DUAL)
                              UNION
                              (SELECT 'MSC' AS name FROM DUAL)
                              UNION
                              (SELECT 'MBA' AS name FROM DUAL))
                    SELECT name
                      INTO valu
                      FROM (  SELECT name
                                FROM pgedu
                            ORDER BY DBMS_RANDOM.RANDOM)
                     WHERE ROWNUM < 2;

                    vals    := valu;
                ELSE
                    IF inp = 'phd'
                    THEN
                        WITH phdedu AS
                                 ((SELECT 'Doctorate of philosophy' AS name FROM DUAL)
                                  UNION
                                  (SELECT 'doctorate of medicine' AS name FROM DUAL)
                                  UNION
                                  (SELECT 'doctorate of science' AS name FROM DUAL)
                                  UNION
                                  (SELECT 'Doctorate of computer sciences' AS name FROM DUAL))
                        SELECT name
                          INTO valu
                          FROM (  SELECT name
                                    FROM phdgedu
                                ORDER BY DBMS_RANDOM.RANDOM)
                         WHERE ROWNUM < 2;

                        vals    := valu;
                    END IF;
                END IF;
            END IF;
        END IF;
    END IF;
END;

另外,请注意变量inpvalu并非绝对必要:您只需使用参数检查输入值并构建输出参数。

如果你需要使用动态SQL(不在这里,但可能在将来),正确的方法是这样的:

declare
    a number;
begin
    execute immediate 'select 1 from dual' into a;
end;

答案 1 :(得分:0)

作为坚持动态SQL的替代答案。

个人偏好:我总是以' ||结束一行,以明确你没有错过任何空格(即使它应该执行得很好)。

从动态sql中删除into valu并将其设为execute immediate 'query' into vals子句。

作为一个例子,我只是使用你的第一个查询:

Execute immediate 'WITH secedu as ( ' ||
   '(SELECT ''ICSE'' as name FROM dual ) UNION ' ||
   '(SELECT ''CBSE'' as name FROM dual ) UNION ' ||
   '(SELECT ''STATE'' BOARD" as name FROM dual) ' ||
   ')         ' ||
'SELECT name from(SELECT name ' ||
    'FROM  secedu ORDER BY DBMS_RANDOM.RANDOM)where rownum<2'
into vals;

答案 2 :(得分:0)

你可能有自己的学习目标,但是那些放弃代码的人只是糟糕而且不必要的复杂PL / SQL。这是一个部分但功能完全的重写,引用了相关的Oracle PL / SQL文档。希望你会发现所提出的想法很有用!

-- blocks: http://docs.oracle.com/database/121/LNPLS/overview.htm#LNPLS141
declare
  -- nested tables: http://docs.oracle.com/database/121/LNPLS/composites.htm#LNPLS99981
  type str_list_t is table of varchar2(32767);
  -- subprograms: http://docs.oracle.com/database/121/LNPLS/subprograms.htm#LNPLS008
  -- common parts of f() refactored to r()
  function r(p_list in str_list_t) return varchar2 is
  begin
    return p_list(floor(dbms_random.value(1, p_list.count + 1)));
  end;
  function f(p_edu_level in varchar2) return varchar2 is
  begin
    return
      -- simple case: http://docs.oracle.com/database/121/LNPLS/controlstatements.htm#LNPLS394
      case p_edu_level
        when 'secondary' then r(str_list_t('ICSE', 'CBSE', 'STATE BOARD'))
        when 'intermediate' then r(str_list_t('MPC', 'BIPC', 'MIPC', 'CEC'))
        -- add here your other education levels, you should see the pattern ...
        else null
      end;
  end;
begin
  -- for loop: http://docs.oracle.com/database/121/LNPLS/controlstatements.htm#LNPLS411
  for i in 1 .. 10
  loop
    dbms_output.put_line('secondary: ' || f('secondary'));
    dbms_output.put_line('intermediate: ' || f('intermediate'));
  end loop;
  dbms_output.put_line('batman: ' || f('batman'));
end;
/