我正在尝试将XML保存在表中。 XML的格式如下:
<employees>
<employees_id> 1</employees_id>
<employees_name>Teradata</employees_name>
<department_id>100</department_id>
<department_name>Techinical</department_name>
<department_id>200</department_id>
<department_name>Management</department_name>
<department_id>300</department_id>
<department_name>Telecom</department_name>
</employees>
<employees>
<employees_id> 2</employees_id>
<employees_name>AT&T</employees_name>
<department_id>400</department_id>
<department_name>Techinical</department_name>
<department_id>500</department_id>
<department_name>Management</department_name>
<department_id>600</department_id>
<department_name>Telecom</department_name>
</employees>
我的表只有一个id列和xmltype列。
我使用的程序如下:
DECLARE
CTX DBMS_XMLGEN.CTXHANDLE;
LCLOB$XML_AS_CLOB CLOB;
LREC$EMPLOYEES_EMPNO NUMBER;
BEGIN
FOR LREC$EMPLOYEES_EMPNO IN (198, 197, 180)
LOOP
--Create context for XML
CTX :=
DBMS_XMLGEN.NEWCONTEXT (
'SELECT employees.EMPLOYEE_ID, employees.FIRST_NAME,
departments.DEPARTMENT_ID, departments.DEPARTMENT_NAME
FROM EMPLOYEES, departments
WHERE employees.department_id = departments.department_id and
employees.employees_id =' || LREC$EMPLOYEES_EMPNO);
--Get XML file of Context
-- Set the row header to be EMPLOYEE
DBMS_XMLGEN.setRowTag(CTX, 'EMPLOYEE');
LCLOB$XML_AS_CLOB := DBMS_XMLGEN.GETXML (CTX);
DBMS_XMLGEN.CLOSECONTEXT (CTX);
INSERT INTO HR.OFFLINE_XML (id, XML_FILE)
VALUES ( LREC$EMPLOYEES_EMPNO, XMLTYPE (LCLOB$XML_AS_CLOB));
END LOOP;
COMMIT;
END;
错误报告:
ORA-06550: line 7, column 4:
PLS-00103: Encountered the symbol "LOOP" when expecting one of the following:
* & - + / at mod remainder rem .. <an exponent (**)> ||
multiset year day
ORA-06550: line 18, column 16:
PLS-00103: Encountered the symbol "." when expecting one of the following:
constant exception <an identifier>
<a double-quoted delimited-identifier> table long double ref
char time timestamp interval date binary national charac
ORA-06550: line 19, column 23:
PLS-00103: Encountered the symbol "=" when expecting one of the following:
constant exception <an identifier>
<a double-quoted delimited-identifier> table long double ref
char time timestamp interval date binary national charac
ORA-06550: line 20, column 16:
PLS-00103: Encountered the symbol "." when expecting one of the following:
constant exception <an identifier>
<a double-quoted delimited-identifier> table long double ref
char time timestamp interval date binary national charac
ORA-06550: line 21, column 5:
PLS-00103: Encountered the symbol "INSERT" when expecting one of the following:
begin function pragma procedure subtype type <an identifier>
<a double-quoted delimited-identifier> current cursor delete
exists prior
The symbol "b
ORA-06550: line 24, column 4:
PLS-00103: Encountered the symbol "COMMIT" when expecting one of the following:
end not pragma final instantiable order overriding static
member constructor map
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
答案 0 :(得分:2)
声明一个迭代的数组:
DECLARE
CTX DBMS_XMLGEN.CTXHANDLE;
LCLOB$XML_AS_CLOB CLOB;
type number_tab is table of number;
t_num number_tab := number_tab(198,197,180);
BEGIN
FOR idx IN t_num.first..t_num.last
LOOP
--Create context for XML
CTX :=
DBMS_XMLGEN.NEWCONTEXT (
'SELECT employees.EMPLOYEE_ID, employees.FIRST_NAME,
departments.DEPARTMENT_ID, departments.DEPARTMENT_NAME
FROM EMPLOYEES, departments
WHERE employees.department_id = departments.department_id and
employees.employees_id =' || t_num(idx));
--Get XML file of Context
-- Set the row header to be EMPLOYEE
DBMS_XMLGEN.setRowTag(CTX, 'EMPLOYEE');
LCLOB$XML_AS_CLOB := DBMS_XMLGEN.GETXML (CTX);
DBMS_XMLGEN.CLOSECONTEXT (CTX);
INSERT INTO HR.OFFLINE_XML (id, XML_FILE)
VALUES ( t_num(idx), XMLTYPE (LCLOB$XML_AS_CLOB));
END LOOP;
COMMIT;
END;
/
其他几点。首先使用dbmx_xmlgen,你应该在这里使用绑定而不是拼接:
employees.employees_id =' || LREC$EMPLOYEES_EMPNO);
最后,您可以使用getxmltype
代替getxml
,以节省获取clob,然后在插入中使用XMLTYPE()。
答案 1 :(得分:2)
正如诺埃尔所说,你无法像这样向for
循环提供固定值。 (报告中的所有其他错误都是由此引起的,尽管存在其他问题)。您可以提供范围for i in 1..10 loop
,但这对您没有帮助,即使对于您的示例数据也是如此。由于它只是用于测试,您现在可以使用虚拟光标:
FOR LREC$EMPLOYEES_EMPNO IN (
SELECT 198 AS employee_id FROM dual
UNION ALL SELECT 197 FROM dual
UNION ALL SELECT 180 FROM dual
) LOOP
(虽然我实际上更喜欢DazzaL的阵列,但我现在会坚持这个)。您不必声明游标,并且使用该名称声明的number
变量将被此版本取代。当你引用它返回的一个值时,它必须是名字,所以在这种情况下LREC$EMPLOYEES_EMPNO.employee_id
。 Persoanlly我会选择一个较短的名字* 8 - )
正如DazzaL所提到的,你也不需要中间CLOB。当你可以使用绑定变量时,似乎没有必要每次在循环周围创建和关闭上下文。
这样可以获得与您的版本相同的结果(经过适当修改),但不是您在问题中建议的输出结果:
DECLARE
ctx DBMS_XMLGEN.CTXHANDLE;
BEGIN
ctx := DBMS_XMLGEN.NEWCONTEXT(
'SELECT employees.EMPLOYEE_ID, employees.FIRST_NAME,
departments.DEPARTMENT_ID, departments.DEPARTMENT_NAME
FROM EMPLOYEES, departments
WHERE employees.department_id = departments.department_id and
employees.employee_id = :id');
DBMS_XMLGEN.setRowTag(ctx, 'EMPLOYEE');
FOR r IN (
SELECT 198 AS employee_id FROM dual
UNION ALL SELECT 197 FROM dual
UNION ALL SELECT 180 FROM dual
) LOOP
DBMS_XMLGEN.SETBINDVALUE(ctx, 'ID', r.employee_id);
INSERT INTO OFFLINE_XML (id, xml_file)
VALUES (r.employee_id, DBMS_XMLGEN.GETXMLTYPE(ctx));
END LOOP;
DBMS_XMLGEN.CLOSECONTEXT(ctx);
END;
/
用表填充表:
ID XML_FILE
---------- --------------------------------------------------
198 <ROWSET>
<EMPLOYEE>
<EMPLOYEE_ID>198</EMPLOYEE_ID>
<FIRST_NAME>Bob</FIRST_NAME>
<DEPARTMENT_ID>1</DEPARTMENT_ID>
<DEPARTMENT_NAME>First</DEPARTMENT_NAME>
</EMPLOYEE>
</ROWSET>
197 <ROWSET>
<EMPLOYEE>
<EMPLOYEE_ID>197</EMPLOYEE_ID>
<FIRST_NAME>Adam</FIRST_NAME>
<DEPARTMENT_ID>1</DEPARTMENT_ID>
<DEPARTMENT_NAME>First</DEPARTMENT_NAME>
</EMPLOYEE>
</ROWSET>
180 <ROWSET>
<EMPLOYEE>
<EMPLOYEE_ID>180</EMPLOYEE_ID>
<FIRST_NAME>Charlie</FIRST_NAME>
<DEPARTMENT_ID>2</DEPARTMENT_ID>
<DEPARTMENT_NAME>Second</DEPARTMENT_NAME>
</EMPLOYEE>
</ROWSET>
答案 2 :(得分:0)
我认为你不能用这种方式编写FOR循环。您应该编写一个光标来选择员工编号,然后在FOR循环中使用光标。
declare
cursor cur_emp is select employee_id from employees;
begin
for i in cur_emp
loop
/*your code here. Use i.employee_id to get the employee_id*/
end loop;
end;