【问题标题】:Basic Oracle question基本的 Oracle 问题
【发布时间】:2010-12-02 17:28:42
【问题描述】:

我是甲骨文的新手。当我使用以下方法创建存储过程时:

CREATE OR REPLACE PROCEDURE PROCEDURE1 
AS
BEGIN

  SELECT FIRSTNAME,
         LASTNAME
    INTO FirstName,LastName
    FROM EMPLOYEE;

END PROCEDURE1;

我收到以下错误:

PL/SQL 语句被忽略 必须声明标识符 FIRSTNAME ORA-00904 无效的标识符

【问题讨论】:

    标签: sql oracle stored-procedures plsql ora-00904


    【解决方案1】:

    您需要在尝试填充变量之前声明它们:

    CREATE OR REPLACE PROCEDURE PROCEDURE1 
    AS
    
     FirstName EMPLOYEE.FIRSTNAME%TYPE;
     LastName EMPLOYEE.LASTNAME%TYPE;
    
    BEGIN
    
      SELECT FIRSTNAME,
             LASTNAME
        INTO FirstName,LastName
        FROM EMPLOYEE;
    
    END PROCEDURE1;
    

    %TYPE 表示法是与列数据类型匹配的数据类型声明的简写。如果该数据类型发生变化,您无需更新该过程。

    【讨论】:

    • 最好不要将变量命名为与列相同的名称。
    【解决方案2】:

    你需要声明变量。

    CREATE OR REPLACE
    PROCEDURE PROCEDURE1 AS
     V_FIRSTNAME VARCHAR2(60);
     V_LASTNAME  VARCHAR2(60);
    BEGIN
            SELECT FIRSTNAME,LASTNAME
             INTO V_FIRSTNAME ,V_LASTNAME  
             FROM EMPLOYEE;
    END PROCEDURE1;
    

    在回复您的评论时,PL/SQL 块中的 SQL 语句只能获取 1 条记录。如果需要获取多条记录,则需要将记录存储在游标中并进行处理。

    CREATE OR REPLACE
        PROCEDURE PROCEDURE1 AS
    
         CURSOR EMP_CUR IS
             SELECT FIRSTNAME,LASTNAME
             FROM EMPLOYEE;
        EMP_CUR_REC EMP_CUR%ROWTYPE;
    
        BEGIN
         FOR EMP_CUR_REC IN EMP_CUR LOOP
             -- do your processing
             DBMS_OUTPUT.PUT_LINE('Employee first name is ' || EMP_CUR_REC.FIRSTNAME);
             DBMS_OUTPUT.PUT_LINE('Employee last name is ' || EMP_CUR_REC.LASTNAME);
        END LOOP;
        END PROCEDURE1;
    

    解释: EMP_CUR 保存要执行的 SQL 语句。 EMP_CUR_REC 保存将由 SQL 语句获取的记录。 %ROWTYPE 表示 Record 将与保存数据的行具有相同的数据类型

    FOR LOOP 将获取每条记录,您可以进行任何需要完成的处理。

    【讨论】:

    • 我可以有类似 Select * from Tablename 或 select firstname,lastname from tablename 之类的东西,就像我们在 sql server 中一样
    • 不,这在 PL/SQL 块中是不可能的。
    • 现在我收到此错误,
      ORA-01422:精确提取返回的行数超过了请求的行数
      ORA-06512:在“SYSTEM.PROCEDURE1”,第 5 行
      ORA -06512:在第 2 行
    • 在 PL/SQL 中,您只能获取 1 条记录 - 它不能为零或超过一条。你能解释一下你到底想做什么吗?
    • 不确定,我认为您必须将其作为参考光标返回。参考:stackoverflow.com/questions/304600/…
    【解决方案3】:


    我认为“AS”关键字不起作用。如果它不起作用,请使用“IS”。
    休息很好,非常好的提示。

    如果您需要有关 PL/SQL 的任何帮助,可以查看此链接。非常简单易懂;
    http://plsql-tutorial.com/

    这是我对您遇到的错误的解决方案;

    CREATE OR REPLACE PROCEDURE PROCEDURE1 IS
      v_FIRSTNAME EMPLOYEE.FIRSTNAME%TYPE;
      v_LASTNAME EMPLOYEE.LASTNAME%TYPE;
      CURSOR EMPCURSOR IS
      SELECT FIRSTNAME, LASTNAME FROM EMPLOYEE;      
      BEGIN   
         IF NOT EMPCURSOR%ISOPEN THEN
             OPEN EMPCURSOR;
         END IF;
         LOOP
            FETCH EMPCURSOR INTO V_FIRSTNAME,V_LASTNAME;
            EXIT WHEN EMPCURSOR%NOTFOUND;
         END LOOP;
         IF EMPCURSOR%ISOPEN THEN
            CLOSE EMPCURSOR;
         END;
      END PROCEDURE1;
    

    您也可以在循环内使用DBMS_OUTPUT.PUT_LINE(V_FIRSTNAME || ','|| V_LASTNAME) 来显示输出。但为了做到这一点,您首先需要执行命令server output on

    【讨论】:

    • 我在这里为上一个问题添加我的评论..... into 语句仅在有单个记录或您尝试获取单个记录时才有效。你需要你的游标来遍历记录。
    • 其实可以填充一个%ROWTYPE变量,提供类似于%TYPE——不用担心数据类型变化,除了行变量简写...
    • 在 PL/SQL PROCEDURE(或 FUNCTION)声明中,AS 和 IS 是同义词,可以使用任何一个。
    【解决方案4】:

    在回复@Sathya 上面@kayak 的回答时,我问“我可以有类似 Select * from Tablename 或 select firstname,lastname from tablename 之类的东西,就像我们在 sql server 中一样”。

    是的,您可以这样做,但您需要包含 WHERE 子句或使用游标。如果您包含将结果限制为单行的 WHERE 子句,您可以编写类似

    CREATE OR REPLACE PROCEDURE PROCEDURE1
    IS
      rowEmployees EMPLOYEE%ROWTYPE;
    BEGIN
      SELECT *
        INTO rowEmployees
        FROM EMPLOYEE
        WHERE EMPLOYEE_ID = 12345;
    END PROCEDURE1; 
    

    另一方面,如果您没有 WHERE 子句,因为您希望处理表中的所有行,或者您有一个 WHERE 子句不将结果限制为单行,您可以使用光标的方式如下:

    CREATE OR REPLACE PROCEDURE PROCEDURE1 IS
    BEGIN
      FOR rowEmployees IN (SELECT *
                             FROM EMPLOYEE
                             WHERE EMPLOYEE_ID IN (12345, 67890, 111213, 141516))
      LOOP
        <do something with rowEmployees here>
      END LOOP;
    END PROCEDURE1; 
    

    分享和享受。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-07-13
      • 2012-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多