2014-08-29 71 views
-1

我试图执行一个相当简单的函数。我想传递一个主机名到这个函数,我希望它获取该主机名并使用它来查找与该主机名关联的systemID并返回它。oracle pl/sql函数名称解析错误

下面你会看到,我有一个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; 
+2

可能是名称冲突。尝试重命名参数:'FUNCTION GET_SYSTEMID(p_Hostname varchar2)' – 2014-08-29 18:29:48

+0

正如Egor所说,'mySystems.HOSTNAME = Hostname'就像'1 = 1',所以所有的行都被返回! SQL是_NOT_区分大小写。 – 2014-08-29 18:35:35

回答

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; 

这也适用和容易(在我心中)是不是增加显函数名称前缀更清楚所有的地方。

+0

这个答案是正确的,写得很好。谢谢@justin解释我很惊讶,我没有遇到过这一次教自己pl/sql。再次感谢 – Andrew 2014-08-29 20:34:14