我想使用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
)
答案 0 :(得分:4)
您应该使用例如将文本转换为the XML type。 XMLPARSE(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>')