oracle pl / sql函数名称解析错误

时间:2014-08-29 18:16:50

标签: oracle function plsql namespaces

我正在尝试执行一个相当简单的功能。我想将一个主机名传递给此函数,我希望它获取该主机名并使用它来查找与该主机名关联的systemID并将其返回。

下面你会看到我有一个pl / sql块正在调用一个名为GET_SYSTEMID的函数,当我将一个varchar传递给这个函数时,我得到一个错误。当我在函数内部硬编码相同的字符串时,我得到了正确的结果。保存主机名的列有一个唯一的约束,所以如果我使用我的一个服务器的确切主机名(我肯定),应该只有一个匹配的行。

这是我的呼叫块:

Declare
    sysid number;
Begin
    sysid := Server.GET_SYSTEMID('MyHost');
    DBMS_OUTPUT.PUT_LINE('SYSID is '||sysid);    
END;

如果我使用该块来调用此函数它不起作用:

FUNCTION GET_SYSTEMID(Hostname varchar2)
RETURN NUMBER
IS
    SysID number;
BEGIN 
    SELECT mySystems.SYSTEMID
    INTO SysID
    FROM mySystems
    where mySystems.HOSTNAME = Hostname;

    return SysID;
END GET_SYSTEMID;

当我运行以上内容时,我收到此错误消息:

Declare
    sysid number;
Begin
    sysid := Server.GET_SYSTEMID('MyHost');
    DBMS_OUTPUT.PUT_LINE('SYSID is '||sysid);    
END;
Error at line 3
ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at "MySchema.Server", line 33
ORA-06512: at line 12

接下来的两个确实有效,但是当他们硬编码主机名时,他们不会做我需要这个功能的事情:

第一名:

FUNCTION GET_SYSTEMID(Hostname varchar2)
RETURN NUMBER
IS 
    SysID number;
    tmp varchar2(8) := 'MyHost';--should be identical to passed in value
BEGIN 
    SELECT mySystems.SYSTEMID
    INTO SysID
    FROM mySystems
    where mySystems.HOSTNAME = tmp;

    return SysID;
END GET_SYSTEMID;

第二名:

FUNCTION GET_SYSTEMID(Hostname varchar2)
RETURN NUMBER
IS
    SysID number;
BEGIN 

    SELECT mySystems.SYSTEMID
    INTO SysID
    FROM mySystems
    where mySystems.HOSTNAME = 'MyHost';--should be identical to passed in value

    return SysID;
END GET_SYSTEMID;

1 个答案:

答案 0 :(得分:3)

问题是名称解析之一。

当您在表格中引用参数hostnamehostname列时,范围解析规则会导致大多数人产生混淆。这就是为什么许多人建议使用参数和局部变量的命名约定来区分它们与表名。例如,在我的代码中,我使用p_为参数名称添加前缀,使用l_为本地变量添加前缀。

在您的代码中,当您有

SELECT mySystems.SYSTEMID
INTO SysID
FROM mySystems
where mySystems.HOSTNAME = Hostname;

hostname被解析为表中的列,而不是参数。这会导致查询返回表中hostname不为空的每一行,从而导致错误。您可以使用函数名称为参数名称显式添加前缀,以强制hostname解析为参数

SELECT mySystems.SYSTEMID
INTO SysID
FROM mySystems
where mySystems.HOSTNAME = GET_SYSTEMID.Hostname;

有效。但添加函数名称前缀通常会很烦人。如果采用前缀参数名称和局部变量名称的约定,则可以获得类似

的内容
FUNCTION GET_SYSTEMID(p_hostname varchar2)
RETURN NUMBER
IS
    l_sysID number;
BEGIN 
    SELECT mySystems.SYSTEMID
    INTO l_sysID
    FROM mySystems
    where mySystems.HOSTNAME = p_hostname;

    return l_sysID;
END GET_SYSTEMID;

与在整个地方添加显式函数名称前缀相比,这也有效并且(在我看来)更清晰。