在PostgreSQL中的TEXT列上使用XMLEXISTS

时间:2017-11-20 12:19:26

标签: sql xml postgresql

我想使用XPATH和XMLEXISTS函数在包含XML内容的text列上执行查询。例如:

select * from om_table tb
WHERE xmlexists('//town[text() = ''Toronto'']' PASSING BY REF tb.config_xml); 

config_xml是text列。但它会出错:

  

错误:函数pg_catalog.xmlexists(未知,文本)不存在

我还在character varying列上对其进行了测试,但也出现了错误:

  

错误:函数pg_catalog.xmlexists(未知,字符变化)不存在

但如果我使用硬编码的XML值,它会成功执行:

select * from om_table tb
WHERE 
xmlexists('//town[text() = ''Toronto'']' PASSING BY REF '<towns><town>Toronto</town><town>Ottawa</town></towns>'); 

我该怎么办? (我使用PostgreSQL 9.6

2 个答案:

答案 0 :(得分:4)

您应该使用例如将文本转换为the XML typeXMLPARSE(DOCUMENT tb.config_xml)就像在这个示例中一样:http://sqlfiddle.com/#!17/9f0fb/7/0

您还可以考虑将config_xml设为XML列而不是文本列。

答案 1 :(得分:2)

您的config_xml类型为text,但您在测试时的字面值为xml类型。

这是因为我需要一段时间才能习惯:Postgres 中的单引号文字不被视为text / varchar值,但实际上是“未知类型的文字”。另一方面,列始终具有固定类型。

规划人员会推断它的类型;在xmlexists('//foo' PASSING BY REF '<foo />')的上下文中,匹配的唯一函数采用类型xml的参数,因此'<foo />'被解释为xml字面值。 与从text转换为xml的值相同,就像写文字123与投射字符串{{1}不同到int。

要直接声明文字的类型,请使用语法'123',因此在这种情况下,正确的显式格式为type 'value'。如果您改为撰写xmlexists(text '//foo' PASSING BY REF xml '<foo />'),则会在使用xmlexists(text '//foo' PASSING BY REF text '<foo />')列时遇到同样的错误。

要解决此问题,您应该将列转换为text类型而不是xml,或者在调用函数时转换值as described in the manual

  

要从字符数据生成xml类型的值,请使用函数xmlparse:
  text
  例子:
  XMLPARSE ( { DOCUMENT | CONTENT } value)
  XMLPARSE (DOCUMENT '<?xml version="1.0"?><book><title>Manual</title><chapter>...</chapter></book>')