Within a PL/SQL procedure, wrap a query or refcursor in HTML table

后端 未结 2 790
甜味超标
甜味超标 2021-01-05 22:20

It seems really easy if you are using SQL*Plus to use

SQL> set markup html on;

and get some lovely results to the SQL*Plus window. we

相关标签:
2条回答
  • 2021-01-05 23:02

    From posting over On the DBA site I got close to the answer that I was looking for. Tom Kyte has a great blog post with a function that does exactly what I was hoping for. In short here is what I implemented:

    I created a function that took a sys_refcursor as a variable:

    CREATE OR REPLACE FUNCTION fncRefCursor2HTML(rf SYS_REFCURSOR)  RETURN CLOB
    IS
        lRetVal      CLOB;
        lHTMLOutput  XMLType; 
        lXSL         CLOB;
        lXMLData     XMLType;
    
        lContext     DBMS_XMLGEN.CTXHANDLE;
    BEGIN
        -- get a handle on the ref cursor --
        lContext := DBMS_XMLGEN.NEWCONTEXT(rf);
        -- setNullHandling to 1 (or 2) to allow null columns to be displayed --
        DBMS_XMLGEN.setNullHandling(lContext,1);
        -- create XML from ref cursor --
        lXMLData := DBMS_XMLGEN.GETXMLTYPE(lContext,DBMS_XMLGEN.NONE);
    
        -- this is a generic XSL for Oracle's default XML row and rowset tags --
        -- " " is a non-breaking space --
        lXSL := lXSL || q'[<?xml version="1.0" encoding="ISO-8859-1"?>]';
        lXSL := lXSL || q'[<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">]';
        lXSL := lXSL || q'[ <xsl:output method="html"/>]';
        lXSL := lXSL || q'[ <xsl:template match="/">]';
        lXSL := lXSL || q'[ <html>]';
        lXSL := lXSL || q'[  <body>]';
        lXSL := lXSL || q'[   <table border="1">]';
        lXSL := lXSL || q'[     <tr bgcolor="cyan">]';
        lXSL := lXSL || q'[      <xsl:for-each select="/ROWSET/ROW[1]/*">]';
        lXSL := lXSL || q'[       <th><xsl:value-of select="name()"/></th>]';
        lXSL := lXSL || q'[      </xsl:for-each>]';
        lXSL := lXSL || q'[     </tr>]';
        lXSL := lXSL || q'[     <xsl:for-each select="/ROWSET/*">]';
        lXSL := lXSL || q'[      <tr>]';    
        lXSL := lXSL || q'[       <xsl:for-each select="./*">]';
        lXSL := lXSL || q'[        <td><xsl:value-of select="text()"/> </td>]';
        lXSL := lXSL || q'[       </xsl:for-each>]';
        lXSL := lXSL || q'[      </tr>]';
        lXSL := lXSL || q'[     </xsl:for-each>]';
        lXSL := lXSL || q'[   </table>]';
        lXSL := lXSL || q'[  </body>]';
        lXSL := lXSL || q'[ </html>]';
        lXSL := lXSL || q'[ </xsl:template>]';
        lXSL := lXSL || q'[</xsl:stylesheet>]';
    
        -- XSL transformation to convert XML to HTML --
        lHTMLOutput := lXMLData.transform(XMLType(lXSL));
        -- convert XMLType to Clob --
        lRetVal := lHTMLOutput.getClobVal();
    
        RETURN lRetVal;
    END;
    

    Then to test it in a Test window in PL/SQL Developer

    declare 
      l_cursor sys_refcursor;
    begin
      open l_cursor for select * from employees;
      :x:= fncRefCursor2HTML(l_cursor);
      close l_cursor;  
    end;
    

    This is something that I have been hoping to find for a long time. THANKS Tom Kyte!

    0 讨论(0)
  • 2021-01-05 23:08

    One option is to use hypertext functions HTF:

    set define off
    
    create table so14t (id number, data varchar2(25));
    
    insert all
    into so14t values(101, 'one hundred & one')
    into so14t values(202, 'two hundred & two')
    into so14t values(303, 'three hundred & three')
    select 1 from dual;
    
    declare
      v_html varchar2(32767);
    begin
      v_html := htf.tableopen;
    
      for i in (select * from so14t) loop
        v_html := v_html || htf.tablerowopen;
        v_html := v_html || htf.tabledata(i.id);
        v_html := v_html || htf.tabledata(htf.escape_sc(i.data));
        v_html := v_html || htf.tablerowclose;
      end loop;
    
      v_html := v_html || htf.tableclose;
    
      dbms_output.put_line(v_html);
    end;
    /
    

    Prints (formatted for readability):

    <TABLE ><TR><TD>101</TD><TD>one hundred &amp; one</TD></TR>
            <TR><TD>202</TD><TD>two hundred &amp; two</TD></TR>
            <TR><TD>303</TD><TD>three hundred &amp; three</TD></TR></TABLE>
    
    0 讨论(0)
提交回复
热议问题