PLS-00201:必须声明标识符“TYPE”
Posted
技术标签:
【中文标题】PLS-00201:必须声明标识符“TYPE”【英文标题】:PLS-00201: identifier 'TYPE' must be declared 【发布时间】:2017-01-06 10:38:51 【问题描述】:我以user1
的身份连接到Oracle 数据库。在数据库中,user2
存在并有一个包pack1
,其中包含两个存储过程,proc1
和proc2
。
我正在尝试调用这些程序,但出现上述错误。错误提到了类型中定义的“type1”。
经过一些研究,建议检查权限,但这些似乎没问题。我正在使用 Oracle SQL Developer,当我在 pack1
和 type1
上单击“授予”时,我的用户同时拥有 EXECUTE 和 DEBUG 权限。
我认为这是代码中的错误,但这会引发不同的错误。我想为包创建一个同义词,因为我读到这些可以提供帮助,但我没有这样做的必要权利,在我问之前,我想用尽我所有的选择。
当我尝试运行这些存储过程时,我尝试使用我准备好的调用和 SQL Developer 创建的默认调用。有趣的是,当我运行我的代码时,会抛出提到的错误。当我运行“默认”代码时,出现“绝对 URI 中的相对路径”错误。
有什么我可能错过的吗?
这是我用来调用该过程的代码。
DECLARE
ClientData type1;
BEGIN
pack1.proc1(param1,param2,ClientData);
FOR i IN 1..ClientData.LAST LOOP
DBMS_OUTPUT.PUT_LINE(ClientData(i).kid ||' '...;
--DBMS_OUTPUT.PUT_LINE(ClientData(i).portfolioName);
--DBMS_OUTPUT.PUT_LINE(ClientData(i).clientCategory);
--DBMS_OUTPUT.PUT_LINE(ClientData(i).typ_pf);
--DBMS_OUTPUT.PUT_LINE(ClientData(i). ptf_ccy);
END LOOP;
END;
编辑 1:这是完整的错误:
ORA-06550: row 2, column 14:
PLS-00201: identifier 'SYSADMIN(user2).CLIENTDATAINSTRESB_A(type1)' must be declared
ORA-06550: row 2, column 14:
PL/SQL: Item ignored
ORA-06550: row 4, column 53:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: row 4, column 1:
PL/SQL: Statement ignored
ORA-06550: row 5, column 13:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: row 5, column 1:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
在正常情况下,我会包含程序的主体,但是,它是业务,因此我不能分享。 据我了解,在调用开始时,声明失败,因此会导致其余错误,因为这些错误与调用“type1”的位置相对应。 为了进一步解释“type1”是什么,它是对表(“type2”)的引用。它由以下代码创建:
create or replace TYPE type1 IS TABLE OF type2;
编辑 2 正如@Alex Poole 建议的那样,我修改了我的声明:
DECLARE
ClientData user2.type1;
但是,它重现了同样的错误:
PLS-00201: identifier 'user2.type1' must be declared
编辑 3 不正确的名称是由于我忘记对代码进行消毒造成的,已修复。 包和这两种类型都归 user2 所有。当我连接到数据库时,我看不到任何东西。没有表格、包或类型。只有当我浏览,,其他用户”并从user2的角度看时,我才能看到所需的程序。 另外,我很肯定我对所有必需的对象都拥有特权(执行和调试)。那是包和定义的类型。 在谈论如何授予特权时,有没有办法检查?我用了命令
SELECT * FROM USER_TAB_PRIVS;
将 user2 列为 Grantor 和 Owner,将 user1 列为 Grantee 编辑 4 这是 SELECT * FROM USER_TAB_PRIVS 的结果;
GRANTEE OWNER TABLE_NAME GRANTOR PRIVILEGE GRANTABLE HIERARCHY COMMON TYPE
USER1 USER2 TYPE2 USER2 DEBUG NO NO NO TYPE
USER1 USER2 TYPE2 USER2 EXECUTE NO NO NO TYPE
USER1 USER2 TYPE1 USER2 DEBUG NO NO NO TYPE
USER1 USER2 TYPE1 USER2 EXECUTE NO NO NO TYPE
USER1 USER2 PACK1 USER2 DEBUG NO NO NO PACKAGE
USER1 USER2 PACK1 USER2 EXECUTE NO NO NO PACKAGE
PUBLIC SYS USER1 USER1 INHERIT PRIVILEGES NO NO NO USER
编辑 5:将结果表从小写变为大写。然而,正如建议的那样,我仔细检查了包的名称和类型,它们确实是大写的。
【问题讨论】:
用户是否直接或通过角色(例如 DBA 角色)拥有权限? 好的,所以你已经用它的所有者来限定类型了;那么您确定您的用户已被授予该 SYSADM 拥有的类型的权限吗?表类型和它是表的基础类型? (正如 Wernfried 所说,直接授予软管还是通过角色授予软管可能很重要 - 但如果您真的使用匿名块则无关紧要)。另外,您显示的create type
与错误消息中的类型名称不匹配?
不,我期待那部分。如果您可以在“其他用户”下看到类型和包,这意味着您至少拥有一些权限。但是你必须有资格调用;你现在正在做的事情。而且你没有从你展示的包中得到错误。除非您的类型名称拼写错误(或者它可能有一个带引号的标识符?希望没有)我不确定。这可能是我们看不到的明显而简单的事情。澄清一下:作为您的用户,您已经对表类型及其下属类型执行了 privs?
针对USER_TAB_PRIVS
showed 标识符的查询:user1 user2 type1 type2 etc - 全部小写。这意味着它们可能是使用带引号的标识符 创建的,您必须使用带引号的标识符 来引用它们,例如"user1"."type1"
。如果您使用不带引号的标识符,例如:user1.type1
' - 那么 Oracle 会存储它们并将它们视为大写。详情请见:docs.oracle.com/cd/B19306_01/server.102/b14200/…
@Lone_Wanderer 并且以两个用户的身份运行查询时是否相同? (如果用户拥有必要的权限,all_objects 将返回该对象)
【参考方案1】:
我认为你的主要问题是你类型的定义。
您必须检查在哪一行中使用了哪种类型。
你应该拥有的:
user1 -> NO TYPES,一个调用user2-stuff的包
user2 -> Type1, Pack1, Proc1
例子:
-- Create your type on schema user2
CREATE OR REPLACE TYPE USER2.TestType AS OBJECT
(
NEWATTRIB1 VARCHAR2(1000)
)
/
-- Create your package at user2
CREATE OR REPLACE PACKAGE user2.TestPackage AS
FUNCTION MyFunction(Param1 IN TestType) RETURN TestType;
END TestPackage;
/
CREATE OR REPLACE PACKAGE BODY user2.TestPackage AS
FUNCTION MyFunction(Param1 IN TestType) RETURN TestType IS
BEGIN
RETURN Param1;
END;
END TestPackage;
/
-- Grant rights user1 (run with user2)
GRANT ALL ON TestType TO User1 WITH GRANT OPTION;
GRANT EXECUTE ON TestPackage TO User1 WITH GRANT OPTION;
-- Call proc from User1
declare
tmp USER2.TestType;
tmp2 USER2.TestType;
begin
tmp := USER2.TestType('Mr.Smith');
tmp2 := USER2.TESTPACKAGE.MYFUNCTION(tmp);
dbms_output.put_line('tmp: ' || tmp.NEWATTRIB1);
dbms_output.put_line('tmp2: ' || tmp2.NEWATTRIB1);
end;
请记住: 两种类型永远不一样!如果您在模式中使用类型,则不允许在另一个模式中定义类似类型来检索对象。您必须在其他模式 (=user2.type1) 中显式命名该类型。 您必须向想要使用该类型的架构/用户授予权限(在您的示例中授予类型和包权限)。
作为现有项目的故障排除,您可以逐步检查:
-
使用 user1 登录
写一些使用你的类型的plsql
declare
tmp user2.type1;
begin
tmp := user2.type1('Mr.Smith');
-- if this works, your type-privs are correct.
end;
写一些使用包的plsql
【讨论】:
以上是关于PLS-00201:必须声明标识符“TYPE”的主要内容,如果未能解决你的问题,请参考以下文章
PLS-00201 标识符必须声明为引用用户定义类型为 SYS