繁体   English   中英

Oracle SQL-从XML标记中选择一个日期并将其转换为DATE类型以允许比较日期

[英]Oracle SQL - Selecting a date from an XML tag and casting it to a DATE type to allow comparison of the dates

我有一个存储XML文档的CLOB类型列(称为xml)。 xml文档具有名为<productionDate>的标记。

我想做的是搜索表并检索包含两个日期之间具有productionDate的xml文档的任何行。

我知道如何读取xml标记作为值:

Select 
xmltype(xml).extract('//product/productionDate/text()').getStringVal() from myTable

上面的查询返回以下日期。

1999-09-23 00:00:00.0 UTC
2000-01-18 00:00:00.0 UTC
2000-01-18 00:00:00.0 UTC
1999-11-02 00:00:00.0 UTC
1999-11-02 00:00:00.0 UTC
1999-11-02 00:00:00.0 UTC
1999-11-02 00:00:00.0 UTC
1999-11-02 00:00:00.0 UTC
1999-11-02 00:00:00.0 UTC

我只列出1999年11月1日至2000年1月1日之间的内容。 为此,我尝试将值转换为DATE类型

Select 
XMLCast(xmltype(xml).extract('//product/productionDate/text()').getStringVal() as DATE) from myTable

我收到以下错误:

ORA-01830: date format picture ends before converting entire input string

大概是因为日期格式无法转换为日期格式。 我该怎么做才能将日期读取为有效日期(忽略时间和UTC文本),以便可以对日期进行比较。

也许一个子串可能有效,但是我想听听那里还有哪些其他更有效的选择。

您以字符串形式获取值,因此您应该只能使用to_dateto_timestamp

Select 
  to_timestamp(xmltype(xml).extract('//product/productionDate/text()').getStringVal(),
    'YYYY-MM-DD HH24:MI:SS.FF "UTC"')
from myTable

SQL Fiddle演示

如果需要,可以同时将其移至其他时区。

当然,给定日期格式,您可以将其作为字符串进行比较并跳过转换...

用于基于文件的数据类型的查询优化的穷人方法

有多种方法可以优化基于文件的数据类型(CLOB / XML)的存储和检索。 如果您使用Oracle等关系数据库解决方案,这里有一些简单的建议,这些建议使用即用型功能,而无需购买,许可或安装其他附加组件和产品。

初步思路:有关流量和使用的思考

它可以帮助您考虑需要多长时间探查XML文件以提取其属性。 考虑这些XML文件的内容一旦添加到基于CLOB的表中后,更改的频率也很重要。

如果涉及CLOB类型表的DML通信量不太高,请考虑构建一个辅助对象,该对象的钩子类型将帮助您在需要时找到正确的XML文件。 有了它之后,就可以将查询活动从源表转移到特定的基于主键的查询之外。

内联函数转换及其优化

话虽如此,您可以即时应用转换函数并在每次查询时转换日期值。 甚至还有用于Oracle的加载项,它们可以优化数据库以查询和搜索LOB对象中的值。

甚至还有一个称为FUNCTION BASED INDEX的优化约定,它提示Oracle使用备用引用(索引),该备用引用也使用TO_DATE / SUBSTR函数组合,您需要在XML文档中转换值。

对于INLINE转换,还有其他方法可能会好得多,因为每次调用查询时都会应用INLINE转换。 通常,没有转换功能和原始格式的数据(即日期作为日期,日期时间或时间戳记)以更快的速度运行,而现有数据库资源的成本却更低。

从外部标记您的XML文档

假设带有XML文件的CLOB表也有一个主键列,那么会想到两个想法:

  1. 使用转换后的值(例如PRODUCTION_DATE )创建第二个表,并使用其来源的CLOB的PK ID标识每个日期记录。 当您发现查询经常访问的新属性时,可以扩展该表。 通过在CLOB表上放置触发器来管理第二个表。

    每当添加Clob记录时,数据值就被提取并转换一次。 如果有任何查询未更改的Clob记录,则自上次查询以来,就无需提取和转换该值。

  2. 创建包含提取和转换功能的实例化视图,以便可以将PRODUCTION_DATE的MView列定义为实际的DATE类型。 MView也可以像Idea(1)一样工作,但是要优雅一些。

    如果可能,FAST可刷新视图将很好地工作,因为它可以自动管理MView并几乎实时响应CLOB表中的更改。 FAST可刷新视图仅使用更改和添加来更新MView,因此,即使源表很大,日常操作也仅基于增量效果。

不了解数据的数量,使用情况或状态,如果没有其他折衷或假设,完全刷新类型MView可能会或可能不会有效。 有时,MView查询定义太复杂而无法使用FAST可刷新格式。

无论哪种情况,您最终都会得到另一个对象(MVIEW或TABLE),该对象包含PRODUCTION_DATE的DATE格式值。 而是查询此TAG表,并使用关联的PK值来确定在缩小满足查询条件的集合或单个记录后应访问CLOB表中的哪个记录。

离别的想法(可选...有点)

如果可能具有NULL PRODUCTION_DATE值,那么在查询TAG支持表时仅应用NVL()内联函数将很诱人。 根据所讨论的数据量,这可能不应该成为问题。 理想情况下,您将始终希望在那里拥有一个值...并在该DATE列上具有NOT NULL约束...这些事情可以帮助db优化器对如何深入表进行更好的假设...特别是如果那里有很多记录。

总之,您还可以使用XMLTYPE数据类型,该数据类型实际上是为处理XML而优化的。 而且它将比您想象的要胜过更多的替代解决方案。 不需要穷人的解决方案(如果不仅如此,在8i / 9.1 / 9.2数据库版本中,这也是一个糟糕的“解决方案”)。 也就是说,XML(DB)是可以免费使用的“无成本选择” /不需要额外的许可证。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM