繁体   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