簡體   English   中英

PL / SQL JAVA ORACLE ERROR ORA-00904:無效標識符

[英]PL/SQL JAVA ORACLE ERROR ORA-00904: INVALID IDENTIFIER

當我運行我的程序時,我收到一個錯誤:

ORACLE ERROR ORA-00904: "PACJENT_ODDZIAL": INVALID IDENTIFIER

我不知道問題出在哪里。
我正在使用NetBeans和SQL Developer。

這是我的Java代碼:

private String PacjentOddzial() {
    String PacjentOddzial = "null";

    con = Polaczenie.ConnectDB();

    String sql = "SELECT pacjent_oddzial (" + Login.login + ") from dual";
    try {
        pst = con.prepareStatement(sql);
        rs = pst.executeQuery();

        if (rs.next()) {
            String add1 = rs.getString(1);
            PacjentOddzial = add1;
        }
    } catch (SQLException | HeadlessException e) {
        JOptionPane.showMessageDialog(null, e);
    }
    return PacjentOddzial;
}

這是PL / SQL函數:

create or replace FUNCTION pacjent_oddzial
    (PES IN NUMBER)
    RETURN VARCHAR2
IS
    ILE VARCHAR2(30);
    ZMIENNA NUMBER;
BEGIN
    SELECT PACJENTID INTO ZMIENNA FROM PACJENT WHERE PESEL=PES;

    SELECT NAZWAODDZIALU INTO ILE FROM PRZYJECIE_NA_ODDZIAL WHERE 
    PACJENTID=ZMIENNA and rownum=1;

    RETURN ILE;
end;

SELECT的語法錯誤:

String sql = "SELECT pacjent_oddzial ("+Login.login+") from dual";

該查詢的結果應如下所示:

SELECT pacjent_oddzial (some_string) from dual
-- ------------------------^^^^^^

這不是一個正確的語法。


如果您嘗試調用函數,那么這也不正確您可以使用以下語法:

{? = call CREATE_A_PERSON (?)}
 1              2          3

哪一個 :

  • (1)是返回值
  • (2)你的功能名稱
  • (3)是你方法的參數
String query = "{? = call pacjent_oddzial (?)}";
    CallableStatement stm = conn.prepareCall(query);
    stm.registerOutParameter(1, Types.VARCHAR);//return value
    stm.setString(2, Login.login);//set the parametter
    String return = stm.getString(1);//the result of your function

看看這里:

JDBC CallableStatement - 存儲過程OUT參數示例

通常,ORA-00904錯誤意味着數據庫無法看到您所指的東西。 所以要么:

  1. 它確實不存在,至少不是你輸入它的方式。 檢查拼寫,在數據字典( all_objects等)中查找它,或者如果它是一個代碼項,它在哪里聲明,檢查你是不是指一個過程就好像它是一個函數,反之亦然,檢查是否有任何雙引號標識符因為這些是區分大小寫的。
  2. 它確實存在,但您的帳戶無法看到它。 檢查授權和同義詞,並確保您以正確的用戶身份進行連接。

關於過程與函數,假設您創建了一個名為give_raise的過程。 現在你可以像這樣調用它:

begin
    give_raise(123, 10);
end;

或這個:

call give_raise(123, 10);

但不是這樣的:

select give_raise(empno, 10) from employees;

因為程序和功能是兩回事。

關於雙引號標識符,默認名稱不區分大小寫,因此您可以互換地引用give_raiseGIVE_RAISE等,因為SQL解析器和PL / SQL編譯器在內部將所有內容都作為第一步。 但是,雙引號會使其區分大小寫(以及允許其他通常無效的名稱,例如"012 Crazy huh?" )。 如果您將程序命名為"GiveRaise" (在引號中),那么您必須永遠引用它,引號和所有內容。

此外,在Oracle SQL中,您可以做和不能對別名項執行某些操作。 例如,您可以在order by子句中引用別名:

select dummy as myalias from dual
order by myalias;

但不是在group by子句中:

/* Invalid, gives ORA-00904: */
select dummy as myalias from dual
group by myalias;

關於權限,請注意標准的定義權限存儲的PL / SQL( create procedure等)不使用角色,因此即使您已經以具有HR_QUERY角色的JOE登錄,並且Joe的SQL查詢可以訪問HR中的所有內容,但Joe存儲了程序只能看到自己的對象和直接授予他的任何東西(不是通過角色)。

關於命名空間問題,假設用戶HR已將EMPLOYEES上的SELECT授予Joe。 Joe仍然不能只select * from employees那里select * from employees因為他必須說出它在哪里,而不是需要在文件系統中指定路徑,或者在其他語言中使用點符號。 默認值是當前架構,即JOE.EMPLOYEES ,當然不存在。 那么選項是:

  1. 明確HR.EMPLOYEES (盡管硬編碼並不理想)。
  2. HR.EMPLOYEES創建一個公共同義詞(雖然由於公共同義詞的全局特性,以后可能會限制您的選項,並且它會廣播您的對象名稱,這可能是一個安全問題)。
  3. JOE模式中為HR.EMPLOYEES創建一個私有同義詞。
  4. 有喬把他的默認模式到HR使用alter session set current_schema = HR

你的SQL來自......

String sql = "SELECT pacjent_oddzial (" + Login.login + ") from dual";

......變得......

SELECT pacjent_oddzial (someLoginValue) from dual;

...在這種情況下,參數是標識符,而不是字符串。

如果通過引入單引號來更改sql ...

String sql = "SELECT pacjent_oddzial ('" + Login.login + "') from dual";

......變得......

SELECT pacjent_oddzial ('someLoginValue') from dual;

......即使使用現有代碼也應該有效。

但是,您應該閱讀sql注入和綁定變量。 當您將用戶提供的值連接到sql時,您很容易受到SQL注入攻擊。 所以,相反,你應該使用像...這樣的SQL

String sql = "SELECT pacjent_oddzial (?) from dual";

...然后通過......應用價值

pst.setString(1, Login.login);

暫無
暫無

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

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