Generating XML from SQL Data with SQL XML Functions
Generating XML from SQL Data with SQL XML FunctionsFunction NameDescriptionxmlElement()Returns an XML element in an XMLType when given the XML element name, an optional list of XML attributes (XMLATTRIBUTES()), and an optional list of values as the content of the new element. XMLELEMENT() can also contain other XML elements or XML fragments (XMLFOREST() ) as its children.xmlAttributes()Used within XMLELEMENT() to specify attributes for the element.xmlForest()Returns an XML fragment in an XMLType when given a list of named expressions for the XML elements. Each expression specifies the name of an XML element and its content.XMLCONCAT()Returns an XML fragment in an XMLType by concatenating a list of XML elements/values.XMLAGG()Returns an XML fragment in an XMLType by aggregating XML fragments, with the option of XML element sorting. SYS_xmlGen()Generates an XML document with the <?XML?> prolog from one scalar type, a user-defined object type, or an instance of XMLType.XMLSEQUENCE()Returns a collection of XMLTypes in an XMLSEQUENCEType, which is a VARRAY of XMLType instances in the database.SYS_XMLAGG()Aggregates XML elements from one scalar type, a user-defined object type, or an instance of XMLType.XMLCOLATTVAL()Generates a set of <column/> elements with the name attributes specifying the column names or the name aliases.UPDATEXML()Updates XML documents in XMLTypes using XPath expressions.XMLTRANSFORM()Applies XSL transformation on XML documents in XMLTypes.EXTRACTVALUE()Returns scalar content, such as numbers or strings, when passed an XPath expression pointing to an XML element with only a single text child.SELECT [XMLELEMENT |XMLATTRIBUTES |XMLFOREST|XMLCONCAT |XMLAGG|…]FROM table_name, [table (XMLSEQUENCE)]WHERE search_conditionsUsing XMLELEMENT(), XMLATTRIBUTES(), and XMLFOREST() functions, you can create XML elements, the attributes for those elements, and XML document fragments. The XML elements and XML document fragments then can be concatenated and aggregated using XMLCONCAT() and XMLAGG(). The XMLSEQUENCE() function is different from the other functions. It creates a collection of XMLType instances, which can then be used to create temporary tables in the FROM clause of the SQL queries.XMLELEMENT() and XMLATTRIBUTES()XMLELEMENT() takes an element name and zero or more arguments that make up the element’s content to create the XML element as an instance of XMLType. You can also specify the collection of attributes for the element using XMLATTRIBUTES(). For example, logging in to the HR sample schema, you can create an XML element by using the following SQL command:SELECTXMLELEMENT("Employee",XMLATTRIBUTES(employee_id AS "empno", job_id AS "job"),XMLELEMENT("Name",first_name||' '||last_name),'is hired on ', hire_date) AS resultFROM employeesWHERE rownum=1;<Employee empno="100" job="AD_PRES"> <Name>Steven King</Name>is hired on 17-JUN-87</Employee>In line 2, an Employee element is defined with two attributes, empno and job. The content of the attributes comes from the employee_id and job_id column in the employees table. Then, a child element of Employee is created, called Name, with its content coming from the concatenation of the first_name and last_name columns. Additionally, you can add mixed content in the query; for example, ‘is hired on ’ is concatenated with the content of the hire_date column in lines 6 and 7, and the text is inserted after the <Name> element. The SQL query produces the following XML element with attributes, along with a child element with mixed content:Note that if the element name or attribute name is not specified, the table column name will be used by default. SYS_XMLGEN()SYS_XMLGEN() function allows creating the <?XML?> XML prolog and adding the XML Processing Instructions (PIs), such as XSLT stylesheet PI, to the created XML documents. For example, you can create an XML document with a prolog with the following SQL command:SELECT SYS_XMLGEN(XMLELEMENT("Employee", ?XMLATTRIBUTES(employee_id AS "empno", job_id AS "job"),XMLELEMENT("Name",first_name||' '||last_name),'is hired on ', hire_date))AS resultFROM EMPLOYEESWHERE rownum=1;Executing this query returns the following result:<?xml version="1.0"?><ROW> ?<Employee empno="100" job="AD_PRES"> ???<Name>Steven King</Name>is hired on 17-JUN-87 ?</Employee></ROW>The SYS_XMLGEN() requires taking one scalar value, a user-defined object type or an XMLType instance as the input. You can also use the XMLFORMAT object to specify the XML formatting options (PIs, root tag, etc.) for the XML document:SELECT SYS_XMLGEN(XMLELEMENT("Employee", ?XMLATTRIBUTES(employee_id AS "empno", job_id AS "job"), ??XMLELEMENT("Name",first_name||' '||last_name), ?'is hired on ', ?hire_date), ?XMLFORMAT.createformat('EmployeeList','NO_SCHEMA', ????????????null,'','', ???'<?xml-stylesheet href="htmlRend.xsl" type="text/xsl" ?>'))FROM employeesWHERE rownum <3;The XML created contains an XSL stylesheet PI and the default root element, the <ROW> element, is replaced by the <EmployeeList> element:<?xml version="1.0"?><?xml-stylesheet href="htmlRend.xsl" type="text/xsl" ?><EmployeeList><Employee empno="100" job="AD_PRES"> ?<Name>Steven King</Name>is hired on 17-JUN-87</Employee></EmployeeList>XMLFOREST()The XMLFOREST() function produces an XML fragment that contains a set of XML elements. The following example adds additional sub-elements to the <Employee> element:SELECT XMLELEMENT("Employee", ??XMLATTRIBUTES(employee_id AS "empno", job_id AS "job"), ??XMLELEMENT("Name",first_name||' '||last_name), ??'is hired on ', hire_date, ??XMLFOREST(EMAIL, PHONE_NUMBER))AS resultFROM employeesWHERE rownum=1;This produces the following result:<Employee empno="100" job="AD_PRES"> <Name>Steven King</Name>is hired on 17-JUN-87 <EMAIL>SKING</EMAIL> <PHONE_NUMBER>515.123.4567</PHONE_NUMBER></Employee>Note that some of the characters allowed in SQL identifiers are not valid for XML element names. When element or attribute names are not specified as quoted aliases such as using XMLELEMENT(“<element_name>“) or using the AS clauses as we did for the XMLATTRIBUTES() function, the fully escaped character mapping is used to map table column names to the XML element names, such as <EMAIL> and <PHONE_NUMBER> in the XMLFOREST() are fully escaped names from the corresponding table column names. The fully escaped character mapping will convert all of the invalid XML characters in the SQL names, such as the : character, to their Unicode representation in hexadecimal format starting with an x sign. For example, if the following object and table are created, where the object name contains a : character:CREATE TYPE mydesc AS OBJECT ("my:desc" VARCHAR(200))/CREATE TABLE mydesc_tbl of mydesc/ INSERT INTO mydesc_tbl VALUES('fully escaped character mapping');After inserting the sample data, you can submit an SQL query as follows:SELECT XMLELEMENT("Test", XMLFOREST("my:desc")) FROM mydesc_tbl;It gives you the XML element <my_x003A_desc> with the SQL name fully escaped:<Test><my_x003A_desc>fully escaped character mapping</my_x003A_desc></Test>Because : is not a legal character for the name of XML elements, it is escaped to be x003A, which is its Unicode representation. If you need to keep the : character in the XML element/attribute names, you need to specify the name aliases for the XML elements and attributes to enable partially escaped character mapping, as shown in the following SQL query:SELECT XMLELEMENT("Test", XMLFOREST("my:desc" AS "my:desc"))FROM mydesc_tbThis allows you to create XML elements and attributes with namespaces as follows:SELECT XMLELEMENT("TEST", ?????????XMLATTRIBUTES('' ????????????AS "xmlns:my"), XMLFOREST("my:desc" as "my:desc"))FROM mydesc_tbl;The result is<TEST xmlns:my=""><my:desc>fully escaped character mapping</my:desc></TEST>The XML document defines a namespace prefix my for the <my:desc> element.XMLSEQUENCE()The function XMLSEQUENCE() returns a sequence of XMLTypes in XMLSEQUENCEType, which is a VARRAY of XMLType instances. The following example shows the output of XMLSEQUENCE() when given a SQL cursor expression as the input: SELECT XMLSEQUENCE( ????????CURSOR( ??????????????SELECT employee_id, first_name, last_name ??????????????FROM employees where rownum <3)) AS resultFROM dual;The result isXMLSEQUENCETYPE(XMLTYPE( <ROW> ?<EMPLOYEE_ID>100</EMPLOYEE_ID> ?<FIRST_NAME>Steven</FIRST_NAME> ?<LAST_NAME>King</LAST_NAME> </ROW>), XMLTYPE( <ROW> ?<EMPLOYEE_ID>101</EMPLOYEE_ID> ?<FIRST_NAME>Neena</FIRST_NAME> ?<LAST_NAME>Kochhar</LAST_NAME> </ROW>))The query returns a collection of XMLType instances containing the <EMPLOYEE_ID>, <FIRST_NAME>, and <LAST_NAME> elements in XML. Since the <ROW> element is used within each row of XMLTypes, you need to make sure it is included in the XPath expressions when accessing the XML data returned as follows:SELECT value(e).extract('/ROW/EMPLOYEE_ID').getClobVal()FROM TABLE(SELECT XMLSEQUENCE( ????????CURSOR( ???????????????SELECT employee_id, first_name, last_name ???????????????FROM employees where rownum <3)) ????????FROM dual) e;The result is<EMPLOYEE_ID>100</EMPLOYEE_ID><EMPLOYEE_ID>101</EMPLOYEE_ID>In the first line of the preceding SQL query, the XPath expression /ROW/EMPLOYEE_ID is used to extract the employees’ IDs.XMLCONCAT()XMLCONCAT() takes an XMLSEQUENCEType or a number of XMLType instances and returns an XML fragment with all the passed-in XML content concatenated. For example, the following SQL concatenates all XML elements within an XML sequence:SELECT (XMLCONCAT( ??????????XMLSEQUENCE( ????????????CURSOR(SELECT * FROM employees WHERE rownum<3))))FROM dual;You can also use XMLCONCAT() with a set of XMLTypes, as shown in the following SQL query:SELECT XMLCONCAT(XMLELEMENT("Email",email), ?????????????????XMLELEMENT("Name", first_name||' '||last_name))FROM employeesWHERE ROWNUM<3;This function is useful when creating a single XML fragment from multiple XMLTypes.XMLAGG()The XMLAGG() function aggregates all the XML elements returned by the SQL query into an XML document fragment and allows an optional ORDER BY clause to order the XML values during the aggregation. The following SQL query returns all the employees ordered by their first_name:SELECT XMLAGG(value(e) ORDER BY EXTRACTVALUE(value(e),'/ROW/FIRST_NAME') DESC NULLS FIRST)FROM TABLE(XMLSEQUENCE(CURSOR(SELECT first_name, last_name,salary ?????????????????????????????FROM employees))) eWHERE EXTRACTVALUE(value(e), '/ROW/SALARY') BETWEEN 12000 AND 18000;The difference between XMLCONCAT() and XMLAGG() is that XMLAGG() operates over the rows of data returned by the SQL query, while XMLCONCAT() doesn’t work across rows. SYS_XMLAGG()SYS_XMLAGG() provides similar functionality to XMLAGG() except that SYS_XMLAGG() adds an additional <ROWSET> root element and the <?XML?> prolog to make sure the result is a well-formed XML document. Like SYS_XMLGEN(), SYS_XMLAGG() can use the XMLFORMAT object to specify the output formats. However, you need to make sure the input of SYS_XMLAGG() is a scalar type, an object type or an XMLType instance. Therefore, if multiple XMLType objects are needed for SYS_XMLAGG(), you need to use XMLCONCAT() to concatenate them into one XMLType object instead of passing them directly to the SYS_XMLAGG():SELECT SYS_XMLAGG(XMLCONCAT(value(e)), ???????XMLFORMAT.createFormat('EmployeeList'))FROM TABLE(XMLSEQUENCE(CURSOR(SELECT first_name, last_name,salary ?????????????????????????????FROM employees))) eWHERE EXTRACTVALUE(value(e), '/ROW/SALARY') BETWEEN 12000 AND 18000;XMLCOLATTVAL()The XMLCOLATTVAL() function creates an XML fragment containing a set of <column> elements where the name attributes are used to keep the column names or the name aliases provided by SQL queries. For example, the following SQL query returns three <column> elements with their name attributes coming from the hire_date and job_id column names and the dept name alias:SELECT XMLELEMENT("Employee", XMLATTRIBUTES(first_name||' '||last_name AS "name"), XMLCOLATTVAL(hire_date, job_id, department_id AS "dept")) AS "result"FROM employees eWHERE rownum=1The result is<Employee name="Steven King"> <column name = "HIRE_DATE">17-JUN-87</column> <column name = "JOB_ID">AD_PRES</column> <column name = "dept">90</column></Employee>This function is useful when table column names contain illegal XML characters.UPDATEXML()The UPDATEXML() function is a useful XML extension function that accepts an XMLType instance and a set of XPath expression and string value pairs to update the XPath-referred elements or attributes with the provided values. It returns a new transient XMLType instance consisting of the original XMLType instance with appropriate XML nodes updated.The UPDATEXML() function offers multiple updates on the XML document and allows multiple namespace declarations:SELECT UPDATEXML(column_name, 'XPath1', 'text1', …'XPathN', 'textN','Namespace1 NamespaceN') FROM table_name;The following example illustrates how to use namespaces in an update:SQL> SELECT UPDATEXML(XMLType( ?2 ??'<Employee xmlns:app1="ns1" ????????????????xmlns:app2="ns2"> ?3 ???<Name app1:type="Customer">Janet Jones</Name> ?4 ???<Job app2:type="IT">Manager</Job> ?5 ???<Salary app2:type="Hidden">12000</Salary> ?6 ???<Commission app2:type="Hidden">3400</Commission> ?7 ??</Employee>'), ?8 ??'/Employee/Name/text()', 'Janet Lee', ?9 ??'/Employee/Name/@app1:type', 'Important Customer', 10 ??'/Employee/Job/@app2:type', 'Hidden', 11 ??'/Employee//*[@app2:type="Hidden"]',null, 12 ??'xmlns:app1="ns1" 13 ???xmlns:app2="ns2"') AS result 14 FROM dual;The result is<Employee xmlns:app1="ns1" xmlns:app2="ns2"> ?<Name app1:type="Important Customer">Janet Lee</Name> ?<Job/> ?<Salary/> ?<Commission/></Employee>The input XML document contains two namespaces, the xmlns:app1=“ns1” and xmlns:app2=“ns2”. However, you don’t have to declare the namespaces for the UPDATEXML() unless the XML elements in the XPath expressions needed to be qualified by the namespaces. For example, you do not have to declare any namespace if you just need to update the /Employee/Name/text() node to be Janet Lee.Note?When updating the text content in the XML elements, you should use the text() function in XPath expressions. Otherwise, for example, if you want to update the /Employee/Name element, you need to specify the XPath as /Employee/Name and the update content as <Name>Janet Lee</Name>. However, if XML elements in XPath need to be qualified by the namespaces, you have to declare the namespaces in UPDATEXML() as shown in line 12 and line 13, where namespaces are delimited by whitespaces.The order of updates is determined by the order of the XPath expressions in the UPDATEXML() from left to right. Updates can be cascaded because each successive update is based on the result of the previous ones. Therefore, after updating the /Employee/Job/@app2:type to be Hidden, the next update, which sets the elements satisfied /Employee//*[@app2:type=“Hidden”] to be NULL, updates the <Job> element in addition to the <Salary> and <Commission> elements. To update the data stored in the tables, you can use UPDATEXML() in a SQL INSERT statement, as shown in this example:UPDATE temp SET doc=UPDATEXML(doc, ????'/a:foo/a:lastupdate/text()',SYSDATE, ????'xmlns:a=""');The result is<foo xmlns="" xmlns:xsd=""> ?<lastupdate xsd:type="date">12-MAY-03</lastupdate></foo>Generating XML from SQL Data with?DBM?XMLGENDBMS_XMLGEN is a PL/SQL package supplied in Oracle Database 10g to generate XML in CLOBs or XMLTypes. It is a C-based implementation, which provides much better performance than the Java-based DBMS_XMLQUERY package in the Oracle8i and Oracle9i database. While DBMS_XMLGEN provides similar functionality to the SQL/XML functions, it is most useful when you need toUtilize the “fetching” interfaces in DBMS_XMLGEN for paginationPerform PL/SQL processing during the XML document generationDBMS_XMLGEN is not limited to PL/SQL statements. You can also call its functions directly from any SQL statement using DBMS_XMLGEN.GETXML() or DBMS_XMGEN.GETXMLTYPE(). In many cases, you will find that this is easier than using the SQL/XML functions, as the input is simply a SQL statement. The following sections providing some typical examples and describe how you can use this package.Canonical MappingUnlike the SQL/XML functions, DBMS_XMLGEN uses a canonical mapping to map the SQL data to XML. The format is exactly the same format used by the DBMS_XMLQUERY PL/SQL package or the XML SQL Utility (XSU) Java packages. The following example generates an XML document containing a set of employee records:SQL> SET AUTOPRINT ONSQL> SET LONG 100000SQL> VAR result CLOBSQL> DECLARE ?qryCtx DBMS_XMLGEN.CTXHANDLE;BEGIN ?qryCtx := ????DBMS_XMLGEN.NEWCONTEXT('SELECT employee_id AS "@id", ??????????????????????????????????first_name AS "FirstName", ??????????????????????????????????last_name AS "LastName", ??????????????????????????????????email AS "Email", ??????????????????????????????????phone_number AS "Phone" ???????????????????????????FROM employees ???????????????????????????WHERE salary > 20000'); ?DBMS_XMLGEN.SETROWSETTAG(qryCtx,'EMPLOYEES'); ?DBMS_XMLGEN.SETROWTAG(qryCtx,'EMPLOYEE'); ?:result := DBMS_XMLGEN.GETXML(qryCtx); ??DBMS_XMLGEN.CLOSECONTEXT(qryCtx);END;The result is<?xml version="1.0"?><EMPLOYEES> <EMPLOYEE id = "100"> ?<FirstName>Steven</FirstName> ?<LastName>King</LastName> ?<Email>SKING</Email> ?<Phone>515.123.4567</Phone> </EMPLOYEE></EMPLOYEES>Note?In the example, the SQL*Plus command SET AUTOPRINT ON is used to automatically display the value of the bind variables (the result variable in the CLOB data type).The canonical mapping uses the <ROW> element to enclose each row of data returned by the SQL query. The <ROW> elements are then included by the <ROWSET> element to create the XML document. In the example, the <ROWSET> or <ROW> element names are changed to EMPLOYEES and EMPLOYEE respectively by calling the DBMS_XMLGEN.SETROWSETTAG() and DBMS_XMLGEN.SETROWTAG() procedures.Note?By setting the parameters of DBMS_XMLGEN.SETROWSETTAG() and DBMS_XMLGEN.SETROWTAG() to NULL, you can suppress the <ROWSET> and <ROW> elements. However, suppressing the <ROWSET> element may result in no root element for the XML document and the following error: ORA-19336: Missing XML root element. By default, the child elements of <ROW> use the table column names as their element names. There is no PL/SQL procedure provided in the DBMS_XMLGEN package to customize the names of these elements, but, you can modify them via the AS clause in the SQL query. In the example, the LastName is set as the alias for the last_name column, and the employee_id column uses the alias @id. The difference between aliases with or without @ in the aliases, is that the column with an alias with @ is mapped to an XML attribute instead of an XML element.Print FormattingUsing DBMS_XMLGEN, you can set the output formats using the following procedures: ?PROCEDURE SETINDENTATIONWIDTH(ctx IN CTXHANDLE, width IN NUMBER); ?PROCEDURE SETPRETTYPRINTING(ctx IN CTXHANDLE, pp IN BOOLEAN);By default, the output is in “pretty” print format with all the whitespaces, indentations and linefeeds between the XML elements, and you can set the number of whitespace characters used for indentation by calling DBMS_XMLGEN.SETINDENTATIONWIDTH(). By setting the second parameter of DBMS_XMLGEN.SETPRETTYPRINTING() to be FALSE, you can to get the XML documents generated in “compact” format with all the whitespaces between the XML element tags stripped out, as shown in the following example:DECLARE qryCtx DBMS_XMLGEN.CTXHANDLE;BEGIN qryCtx := ?DBMS_XMLGEN.NEWCONTEXT('SELECT employee_id AS "@id", ???????????????????????????????????first_name as "FirstName", ????????????????????????????????????last_name as "LastName", ????????????????????????????????????email as "Email", ????????????????????????????????????phone_number as "Phone" ?????????????????????????????FROM employees ?????????????????????????????WHERE salary > 20000'); ?DBMS_XMLGEN.SETPRETTYPRINTING(qryCtx, FALSE); ?:result := DBMS_XMLGEN.GETXML(qryCtx); ?DBMS_XMLGEN.CLOSECONTEXT(qryCtx);END;The result is<?xml version="1.0"?><ROWSET><ROW><EMPLOYEE_ID>100</EMPLOYEE_ID><FIRST_NAME>Steven</FIRST_NAME><LAST_NAME>King</LAST_NAME><EMAIL>SKING</EMAIL><PHONE_NUMBER>515.123.4567</PHONE_NUMBER><HIRE_DATE>17-JUN-87</HIRE_DATE><JOB_ID>AD_PRES</JOB_ID><SALARY>24000</SALARY><DEPARTMENT_ID>90</DEPARTMENT_ID></ROW></ROWSET>Though this output is not the pretty format that you can easily read, an XML parser considers the data to be equivalent. Note?The output format customization is the new feature for the DBMS_XMLGEN package in Oracle Database 10g. Data FetchingWhen a large amount of data is returned by the SQL query, it is not efficient to generate a single huge XML document containing all the data. This will result in memory issues when performing DOM-based processing or transmitting the document to another user. The data “fetching” feature in DBMS_XMLGEN allows you to generate a set of small XML documents using the following procedures:FUNCTION GETNUMROWSPROCESSED(ctx IN CTXHANDLE) RETURN NUMBER;PROCEDURE SETMAXROWS(ctx IN CTXHANDLE, maxRows IN NUMBER);Here is an example using these functions in a PL/SQL FOR...LOOP:SQL> SET SERVEROUTPUT ON SIZE 1000000SQL> DECLARE ??????qryCtx DBMS_XMLGEN.CTXHANDLE; ??????res BOOLEAN; ??????result XMLType; ??????i NUMBER :=0; ????BEGIN ??????-- Create the query context ??????qryCtx := DBMS_XMLGEN.NEWCONTEXT( ?????????????????'SELECT * FROM employees ORDER BY employee_id'); ??????DBMS_XMLGEN.SETMAXROWS(qryCtx,10); ??????LOOP ????????result:= DBMS_XMLGEN.GETXMLTYPE(qryCtx); ????????EXIT WHEN DBMS_XMLGEN.GETNUMROWSPROCESSED(qryCtx) =0; ????????i :=i+1; ????????-- Create XML DB Resources ????????res := DBMS_XDB.CREATERESOURCE('/public/emp'||i||'.xml',result); ????????IF res = FALSE THEN ??????????DBMS_OUTPUT.PUT_LINE('Error creating XML DB resource'); ????????ELSE ??????????DBMS_OUTPUT.PUT_LINE('/public/emp'||i||'.xml'||' is created'); ????????END IF; ??????END LOOP; ??????COMMIT; ???END;The SQL query gets all the employees in order of their employee_id. By setting Max Rows to be 10, each XML document contains no greater than ten records. The DBMS_XMLGEN.GETNUMROWSPROCESSED() function keeps track of the number of rows that get decremented by 10 from the previous DBMS_XMLGEN.GETXML() calls. Once the loops have completed, the DBMS_XMLGEN.GETNUMROWSPROCESSED() returns zero, and the procedure exits. During the creation of the outputs, DBMS_XMLGEN.GETXMLTYPE() is used to return the query result in XMLType. This XMLType is then used by DBMS_XDB.CREATERESOURCE() to create a resource file in the XML DB Repository. After the resource files are created, you can access the XML documents either through the WebDAV/HTTP or the FTP interfaces. For example, when you type the following HTTP address in Internet Explorer: window pops up asking for login information. You can log in using any database username and its associated password. However, because the resource is created as a private resource by default, you need to log in as HR user to access the generated files from HR user, as shown in Figure 10-1. HYPERLINK "mk:@MSITStore:L:\\E_Gramatas\\_Oracle_DBS\\Ora_XML\\Ora10g_XML.chm::/8173final/images/f10%2D01%5F0%2Ejpg" \t "_parent" Figure 10-1: HTTP access of XDB (XML DB) repository From these interfaces, you can easily download the files from the database server to other client systems. Using REF CursorIn addition to creating the query context from SQL queries, DBMS_XMLGEN.NEWCONTEXT() allows you to create the query context based on REF cursors. This is done by specifying a SYS_REFCURSOR as the initialization parameter, as shown in the following example:SQL> SET AUTOPRINT ONSQL> VAR result CLOB;SQL> DECLARE ????salary NUMBER :=20000; ????refcur SYS_REFCURSOR; ????qryCtx DBMS_XMLGEN.CTXHANDLE; ??BEGIN ??OPEN refcur FOR ??????'SELECT * FROM employees WHERE salary> :1' USING salary; ????qryCtx := DBMS_XMLGEN.NEWCONTEXT(refcur); ????:result := DBMS_XMLGEN.GETXML(qryCtx,DBMS_XMLGEN.NONE); ????DBMS_XMLGEN.CLOSECONTEXT(qryCtx); ?END;This is useful when you need to create XML from a result set returned by another PL/SQL process.Using Bind VariablesWhenever you use a SQL query repeatedly by simply updating several variables, you should think about using bind variables, because they eliminate the need to reparse the SQL statement, thus saving processing time. In the following example, we open a SYS_REFCURSOR for the department_id in the department table and use it to find all the employees within each department. When creating the loop for each department_id, DBMS_XMLGEN.SETBINDVALUE() is used to set the bind variable for the SQL query, and DBMS_XMLGEN.CLEARBINDVALUE() is used to clear the bind variable data.DECLARE ?qryCtx DBMS_XMLGEN.CTXTYPE; ?v_sql VARCHAR2(100); ?v_clob CLOB; ?TYPE deptType IS RECORD (department_id NUMBER(4)); ?v_deprec deptType; ?v_refcur SYS_REFCURSOR;BEGIN ?qryCtx := DBMS_XMLGEN.NEWCONTEXT( ?????????'SELECT * FROM employees WHERE department_id = :MID'); ?-- Open Ref Cursor ?OPEN v_refcur FOR ???'SELECT department_id FROM departments WHERE location_id = 1700'; ?-- Loop each department ?LOOP ???-- Fetch from cursor variable. ????FETCH v_refcur INTO v_deprec; ????EXIT WHEN v_refcur%NOTFOUND; ????DBMS_XMLGEN.SETBINDVALUE( qryCtx, 'MID', v_deprec.department_id); ????v_clob := DBMS_XMLGEN.GETXML( qryCtx ); ????INSERT INTO temp VALUES(v_clob); ??END LOOP; ??DBMS_XMLGEN.CLOSECONTEXT(qryCtx);EXCEPTION ??WHEN OTHERS THEN ????DBMS_XMLGEN.CLOSECONTEXT(qryCtx);END;Querying the V$SQL view in SYS user, we can see how many times the SQL query is parsed and executed:SQL> SELECT parse_calls,executions ????FROM v$sql ????WHERE sql_text ???????LIKE 'SELECT * FROM employees WHERE department_id =%';PARSE_CALLS EXECUTIONS---------- ---------- ????????1 ????????21Note?The V$SQL view is one of the V$ views created on the dynamic performance tables, in which every parsed and stored SQL statement in the shared pool is presented as a row in the view. You need to run GRANT SELECT ON v_$sql TO HR before running the query on V$sql.The result shows that the SQL query is executed 21 times but is only parsed once. This shows the value of using bind variables in SQL.Dealing with Special CharactersSome characters—such as ‘, <, and >—are special characters in XML documents and must be in escaped format, also known as character entities format. For example, the escaped format for ‘ is ', the escaped format for > is >, and the escaped format for < is <. By default, all special characters are escaped. For example, the following SQL query contains a ‘ character:SELECT DBMS_XMLGEN.GETXML( ???????'SELECT ''Don''''t escape me!'' AS result FROM dual') FROM dual;The following XML document is generated with the ' escaped:<?xml version="1.0"?><ROWSET> <ROW> ?<RESULT>Don't escape me!</RESULT> </ROW></ROWSET>To avoid the character escaping, you can call the DBMS_XMLGEN.SETCONVERTSPECIALCHARS() procedure with FALSE, as in the following example:DECLARE ?qryCtx DBMS_XMLGEN.CTXHANDLE;BEGIN ?qryCtx := ???DBMS_XMLGEN.NEWCONTEXT( ?????'SELECT ''Don''''t escape me!'' as result FROM dual'); ?DBMS_XMLGEN.SETCONVERTSPECIALCHARS(qryCtx, FALSE); ?:result := DBMS_XMLGEN.GETXML(qryCtx); ?DBMS_XMLGEN.CLOSECONTEXT(qryCtx);END;The generated XML document will have the following format:<?xml version="1.0"?><ROWSET> <ROW> ?<RESULT>Don't escape me!</RESULT> </ROW></ROWSET> ................
................
In order to avoid copyright disputes, this page is only a partial summary.
To fulfill the demand for quickly locating and searching documents.
It is intelligent file search solution for home and business.