2013-01-02 56 views
0

SQL數據讓我知道你的建議從XML提取SQL數據。示例XML將如下作爲輸入的過程作爲CLOB:提取XML

<filter> 
    <and> 
    <or> 
     <equals field="MARKET_NAME" value="Chicago"/> 
     <equals field="MARKET_NAME" value="BOSTON"/> 
    </or> 
    <or> 
     <equals field="RANK" value="1"/> 
     <equals field="RANK" value="2"/> 
    </or> 
    <between field="current_data" arg1="start_date" arg2="End_date"/> 
    <gt field="CUME" value="20"/> 
    <like field="DMA_NAME" value="%ABC%"/> 
    </and> 
</filter> 

提取的數據應該是這個樣子:

(MARKET_NAME = 'Chicago' or MARKET_NAME = 'BOSTON') and 
(RANK = 1 or RANK = 2) and 
(current_date between start_date and End_Date) and 
CUME > 20 and 
DMA_NAME like '%ABC%' 

讓我知道你寶貴的建議..

在此先感謝

+0

[你有什麼**你**嘗試到目前爲止?](http://www.whathaveyoutried.com) - 還有:你想要做什麼編程語言呢?而這是什麼數據庫系統? –

+0

此XML將被傳遞到一個PL/SQL程序爲CLOB對象。我需要閱讀XML並按給定的方式構建提到的查詢。 – Krishnakumar

+0

DB中的Oracle 11g – Krishnakumar

回答

2

一個辦法是一個XSL樣式表。

,但我會添加到您的XML,數據類型。例如

<filter> 
    <and> 
     <or> 
      <equals field="MARKET_NAME" value="Chicago" datatype="string"/> 
      <equals field="MARKET_NAME" value="BOSTON" datatype="string"/> 
     </or> 
     <or> 
      <equals field="RANK" value="1" datatype="number"/> 
      <equals field="RANK" value="2" datatype="number"/> 
     </or> 
     <between field="current_data" arg1="start_date" arg2="End_date" datatype="field"/> 
     <between field="foo" arg1="20121230" arg2="20130101 01:12:23" datatype="date"/> 
     <gt field="CUME" value="20" datatype="number"/> 
     <like field="DMA_NAME" value="%ABC%" datatype="string"/> 
    </and> 
</filter> 

那麼XSL(這只是一個示例,您將需要改善這種作爲其只爲你一個基本的首發。!)

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl" 
    exclude-result-prefixes="xd" 
    version="1.0"> 
    <xsl:output method="text"/> 

    <xsl:template name="string-replace-all"> 
     <xsl:param name="text"/> 
     <xsl:param name="replace"/> 
     <xsl:param name="by"/> 
     <xsl:choose> 
      <xsl:when test="contains($text,$replace)"> 
       <xsl:value-of select="substring-before($text,$replace)"/> 
       <xsl:value-of select="$by"/> 
       <xsl:call-template name="string-replace-all"> 
        <xsl:with-param name="text" select="substring-after($text,$replace)"/> 
        <xsl:with-param name="replace" select="$replace"/> 
        <xsl:with-param name="by" select="$by"/> 
       </xsl:call-template> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:value-of select="$text"/> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 

    <xsl:template name="processDatatype"> 
     <xsl:param name="value" /> 
     <xsl:param name="datatype" /> 
     <xsl:choose> 
      <xsl:when test="$datatype = 'string'"> 
       <xsl:text>&apos;</xsl:text> 
       <xsl:call-template name="string-replace-all"> 
        <xsl:with-param name="text" select="$value"/> 
        <xsl:with-param name="replace" select='"&apos;"'/> 
        <xsl:with-param name="by" select='"&apos;&apos;"'/> 
       </xsl:call-template> 
       <xsl:text>&apos;</xsl:text> 
      </xsl:when> 
      <xsl:when test="$datatype = 'date'"> 
       <xsl:text>to_date(&apos;</xsl:text> 
       <xsl:value-of select="$value"/> 
       <xsl:text>&apos;,&apos;yyyymmdd hh24:mi:ss&apos;)</xsl:text> 
      </xsl:when> 
      <xsl:otherwise><xsl:value-of select="$value"/></xsl:otherwise> 
     </xsl:choose> 

    </xsl:template> 

    <xsl:template name="gt"> 
     <xsl:value-of select="@field"/> 
     <xsl:text> &gt; </xsl:text> 
     <xsl:call-template name="processDatatype"> 
      <xsl:with-param name="value"><xsl:value-of select="@value"/></xsl:with-param> 
      <xsl:with-param name="datatype"><xsl:value-of select="@datatype"/></xsl:with-param> 
     </xsl:call-template> 
    </xsl:template> 

    <xsl:template name="lt"> 
     <xsl:value-of select="@field"/> 
     <xsl:text> &lt; </xsl:text> 
     <xsl:call-template name="processDatatype"> 
      <xsl:with-param name="value"><xsl:value-of select="@value"/></xsl:with-param> 
      <xsl:with-param name="datatype"><xsl:value-of select="@datatype"/></xsl:with-param> 
     </xsl:call-template> 
    </xsl:template> 

    <xsl:template name="between"> 
     <xsl:value-of select="@field"/> 
     <xsl:text> between </xsl:text> 
     <xsl:call-template name="processDatatype"> 
      <xsl:with-param name="value"><xsl:value-of select="@arg1"/></xsl:with-param> 
      <xsl:with-param name="datatype"><xsl:value-of select="@datatype"/></xsl:with-param> 
     </xsl:call-template> 
     <xsl:text> and </xsl:text> 
     <xsl:call-template name="processDatatype"> 
      <xsl:with-param name="value"><xsl:value-of select="@arg2"/></xsl:with-param> 
      <xsl:with-param name="datatype"><xsl:value-of select="@datatype"/></xsl:with-param> 
     </xsl:call-template> 
    </xsl:template> 

    <xsl:template name="like"> 
     <xsl:value-of select="@field"/> 
     <xsl:text> like </xsl:text> 
     <xsl:call-template name="processDatatype"> 
      <xsl:with-param name="value"><xsl:value-of select="@value"/></xsl:with-param> 
      <xsl:with-param name="datatype"><xsl:value-of select="@datatype"/></xsl:with-param> 
     </xsl:call-template> 
    </xsl:template> 

    <xsl:template name="equals"> 
     <xsl:value-of select="@field"/> 
     <xsl:text> = </xsl:text> 
     <xsl:call-template name="processDatatype"> 
      <xsl:with-param name="value"><xsl:value-of select="@value"/></xsl:with-param> 
      <xsl:with-param name="datatype"><xsl:value-of select="@datatype"/></xsl:with-param> 
     </xsl:call-template> 
    </xsl:template> 


    <xsl:template name="and"> 
     <xsl:for-each select="*"> 
      <xsl:if test="position() != 1"> 
       <xsl:text>and </xsl:text> 
      </xsl:if> 
      <xsl:choose> 
       <xsl:when test="name() = 'like'"> 
        <xsl:text>(</xsl:text> 
        <xsl:call-template name="like" /> 
        <xsl:text>)&#10;</xsl:text> 
       </xsl:when> 
       <xsl:when test="name() = 'gt'"> 
        <xsl:text>(</xsl:text> 
        <xsl:call-template name="gt" /> 
        <xsl:text>)&#10;</xsl:text> 
       </xsl:when> 
       <xsl:when test="name() = 'lt'"> 
        <xsl:text>(</xsl:text> 
        <xsl:call-template name="lt" /> 
        <xsl:text>)&#10;</xsl:text> 
       </xsl:when> 
       <xsl:when test="name() = 'equals'"> 
        <xsl:text>(</xsl:text> 
        <xsl:call-template name="equals" /> 
        <xsl:text>)&#10;</xsl:text> 
       </xsl:when> 
       <xsl:when test="name() = 'between'"> 
        <xsl:text>(</xsl:text> 
        <xsl:call-template name="between" /> 
        <xsl:text>)&#10;</xsl:text> 
       </xsl:when> 
       <xsl:when test="name() = 'or'"> 
        <xsl:text>(</xsl:text> 
        <xsl:call-template name="or" /> 
        <xsl:text>)&#10;</xsl:text> 
       </xsl:when> 
      </xsl:choose> 
     </xsl:for-each> 
    </xsl:template> 

    <xsl:template name="or"> 
     <xsl:for-each select="*"> 
      <xsl:if test="position() != 1"> 
       <xsl:text>or </xsl:text> 
      </xsl:if> 
      <xsl:choose> 
       <xsl:when test="name() = 'like'"> 
        <xsl:text>(</xsl:text> 
        <xsl:call-template name="like" /> 
        <xsl:text>)&#10;</xsl:text> 
       </xsl:when> 
       <xsl:when test="name() = 'gt'"> 
        <xsl:text>(</xsl:text> 
        <xsl:call-template name="gt" /> 
        <xsl:text>)&#10;</xsl:text> 
       </xsl:when> 
       <xsl:when test="name() = 'lt'"> 
        <xsl:text>(</xsl:text> 
        <xsl:call-template name="lt" /> 
        <xsl:text>)&#10;</xsl:text> 
       </xsl:when> 
       <xsl:when test="name() = 'equals'"> 
        <xsl:text>(</xsl:text> 
        <xsl:call-template name="equals" /> 
        <xsl:text>)&#10;</xsl:text> 
       </xsl:when> 
       <xsl:when test="name() = 'between'"> 
        <xsl:text>(</xsl:text> 
        <xsl:call-template name="between" /> 
        <xsl:text>)&#10;</xsl:text> 
       </xsl:when> 
       <xsl:when test="name() = 'and'"> 
        <xsl:text>(</xsl:text> 
        <xsl:call-template name="and" /> 
        <xsl:text>)&#10;</xsl:text> 
       </xsl:when> 
      </xsl:choose> 
     </xsl:for-each> 
    </xsl:template> 

    <xsl:template match="/filter"> 
     <xsl:text>where </xsl:text> 
     <xsl:for-each select="*"> 
      <xsl:choose> 
       <xsl:when test="name() = 'and'"> 
        <xsl:call-template name="and" /> 
       </xsl:when> 
       <xsl:when test="name() = 'or'"> 
        <xsl:call-template name="or" /> 
       </xsl:when> 
      </xsl:choose> 
     </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

例如:

出XSL存儲一個XMLTYPE:

SQL> select * from xsl; 

NAME 
-------------------- 
XSL 
-------------------------------------------------------------------------------- 
xml_to_sql 
<?xml version="1.0" encoding="WINDOWS-1252"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xd="http: 
//www.oxygenxml.com/ns/doc/xsl" exclude-result-prefixes="xd" version="1.0"> 
    <xsl:output method="text"/> 
    <xsl:template name="string-replace-all"> 
    <xsl:param name="text"/> 
... 

現在我們使用的XML輸入XMLTYPE的transform函數來得到結果:

SQL> select dbms_xmlgen.convert(xmltype('<?xml-stylesheet type="text/xsl" href="test.xsl"?> 
    2 <filter> 
    3  <and> 
    4   <or> 
    5    <equals field="MARKET_NAME" value="Chicago" datatype="string"/> 
    6    <equals field="MARKET_NAME" value="BOSTON" datatype="string"/> 
    7   </or> 
    8   <or> 
    9    <equals field="RANK" value="1" datatype="number"/> 
10    <equals field="RANK" value="2" datatype="number"/> 
11   </or> 
12   <between field="current_data" arg1="start_date" arg2="End_date" datatype="field"/> 
13   <between field="foo" arg1="20121230" arg2="20130101 01:12:23" datatype="date"/> 
14   <gt field="CUME" value="20" datatype="number"/> 
15   <like field="DMA_NAME" value="%AB&apos;C%" datatype="string"/> 
16  </and> 
17 </filter>').transform(xsl.xsl).getclobval(), 1) 
18 from xsl 
19/

DBMS_XMLGEN.CONVERT(XMLTYPE('< 
-------------------------------------------------------------------------------- 
where ((MARKET_NAME = 'Chicago') 
or (MARKET_NAME = 'BOSTON') 
) 
and ((RANK = 1) 
or (RANK = 2) 
) 
and (current_data between start_date and End_date) 
and (foo between to_date('20121230','yyyymmdd hh24:mi:ss') and to_date('20130101 
01:12:23','yyyymmdd hh24:mi:ss')) 
and (CUME > 20) 
and (DMA_NAME like '%AB''C%')