【问题标题】:Invalid Identifier for input parameter variables on Oracle stored procedureOracle 存储过程中输入参数变量的标识符无效
【发布时间】:2022-01-25 08:37:11
【问题描述】:

我正在尝试创建一个存储过程,该过程将从视图中获取所有列并在 CLOB 上为其生成 XML 数据。

CREATE OR REPLACE PROCEDURE PaGenerarServicioXML(vIdViaje IN NUMBER, vIDCliente IN varchar)
IS
ServicioXML CLOB;
BEGIN

  SELECT DBMS_XMLGEN.GETXML (q'!
       SELECT *
      FROM VwServicio VwS
      WHERE VwS.Identificador_Viaje = vIdViaje 
      AND VwS.Identificador_Cliente = vIdCliente
      !')
    INTO ServicioXML
    FROM DUAL;
    SYS.DBMS_OUTPUT.PUT_LINE(ServicioXML);
END;

EXECUTE PaGenerarServicioXML(2,'304560326')

存储过程保存正确。

当我执行这个存储过程时,会抛出以下错误:

ORA-19202: Error occurred in XML processing
ORA-00904: "VIDCLIENTE": invalid identifier ORA-06512: at "SYS.DBMS_XMLGEN", line 176
ORA-06512: at "SYS.DBMS_XMLGEN", line 7
ORA-06512: at "SYS.DBMS_XMLGEN", line 164
ORA-06512: at line 1
ORA-06512: at "SQL_MBFTRUKIWLGITBRTRBBHFHTSA.PAGENERARSERVICIOXML", line 6
ORA-06512: at line 1
ORA-06512: at "SYS.DBMS_SQL", line 1721

如果我删除 WHERE 子句中的 AND 语句,错误将更改为未将 VIDVIAJE 标识为有效。为什么不接受我刚刚创建的输入变量?

VwServicio 视图中,Identificador_Viaje 是一个INT 数据类型,而Identificador_Cliente 是一个VARCHAR,所以我真的不明白问题出在哪里。

【问题讨论】:

  • 如您所见,getxml 中的 SQL 文本是一个字符串。它不(也不能)知道任何关于外部变量的信息,因为它在不同的事务中执行,具有自己的内容,如execute immediate。您需要将该值注入 SQL 文本

标签: sql oracle


【解决方案1】:

您的查询是一个字符串,DBMS_XMLGEN 在执行内部查询时对外部上下文一无所知。要将参数传递给它,您需要使用此函数签名:

DBMS_XMLGEN.GETXML (
   ctx          IN ctxHandle,
   dtdOrSchema  IN number := NONE)
 RETURN CLOB;

然后从通用游标创建上下文并在此处传递参数:

dbms_xmlgen.newcontext(cursor(
  SELECT *
  FROM VwServicio VwS
  WHERE VwS.Identificador_Viaje = vIdViaje 
    AND VwS.Identificador_Cliente = vIdCliente
))

把它们放在一起,你会得到这样的东西:

create table t
as
select level - 1 as id
from dual
connect by level < 3
create table t_child
as
select mod(level, 6) as id
  , level as child_id
from dual
connect by level < 18
create function f_get_children_xml(
  p_id in int
) return clob
is
  l_cur sys_refcursor;
begin
  open l_cur for
    select *
    from t_child
    where t_child.id = p_id
  ;
  return dbms_xmlgen.getxml(
    ctx => dbms_xmlgen.newcontext(queryString => l_cur)
  );
end;
/
select f_get_children_xml(id)
from t
F_GET_CHILDREN_XML(ID)
<?xml version="1.0"?>
<ROWSET>
<ROW>
<ID>0</ID>
<CHILD_ID>6</CHILD_ID>
</ROW>
<ROW>
<ID>0</ID>
<CHILD_ID>12</CHILD_ID>
</ROW>
</ROWSET>
<?xml version="1.0"?>
<ROWSET>
<ROW>
<ID>1</ID>
<CHILD_ID>1</CHILD_ID>
</ROW>
<ROW>
<ID>1</ID>
<CHILD_ID>7</CHILD_ID>
</ROW>
<ROW>
<ID>1</ID>
<CHILD_ID>13</CHILD_ID>
</ROW>
</ROWSET>

或与普通 SQL 相同:

select
  id,
  dbms_xmlgen.getxml(dbms_xmlgen.newcontext(
    cursor(select * from t_child where t_child.id = t.id)
  )) as dependent_xml
from t
ID DEPENDENT_XML
0
<?xml version="1.0"?>
<ROWSET>
<ROW>
<ID>0</ID>
<CHILD_ID>6</CHILD_ID>
</ROW>
<ROW>
<ID>0</ID>
<CHILD_ID>12</CHILD_ID>
</ROW>
</ROWSET>
1
<?xml version="1.0"?>
<ROWSET>
<ROW>
<ID>1</ID>
<CHILD_ID>1</CHILD_ID>
</ROW>
<ROW>
<ID>1</ID>
<CHILD_ID>7</CHILD_ID>
</ROW>
<ROW>
<ID>1</ID>
<CHILD_ID>13</CHILD_ID>
</ROW>
</ROWSET>

db小提琴here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-02
    • 1970-01-01
    • 2011-03-09
    • 1970-01-01
    相关资源
    最近更新 更多