Nov 152014
 
This entry is part 21 of 25 in the series Matlab数据库基础班

好久好久没有更新,真不是咱太懒,而是各种瞎忙,很多事情想做却一直没有去做。
闲话打住。这篇博文要解决的是将xml文件导入到Postgresql中,储存成为XML格式。

前言:
我用的Postgresql 9.4 Beta 3 版本 ,已经可以支持XML的内容读取,但是对于直接修改XML格式的数据还没有好的支持,所以很多时候需要直接将XML数据直接写入到数据库中。考虑到有时候XML文件可能很大,所以直接将XML的字符串直接 insert 可能比较局限,于是另外考虑一种办法是直接将文件导入到数据库中。

测试环境:

Postgresql 9.4 Beta 3版本,服务器也就是装在测试机器上,数据目录地址是 I:\pgdata94\ 目录。

测试的数据表为 test._demo, 其中只有一个字段: xx, 其类型是XML。创建此数据表的命令是:
CREATE TABLE test.xml_demo
(
xx xml
)

测试用的XML文件是Matlab任意目录下的一个info.xml 文件。

方法一、文件放在服务器端

这种方法最简单,但是前提要求需要将 info.xml 文件拷贝到数据目录下,原理是通过服务器端的程序直接读取该文件,并导入到数据库中,所用函数是 pg_read_file(),这是因为服务器端的程序只能读取服务器目录(即数据目录)下的内容。

假设我将其拷贝到 I:\pgdata\pg_xlog\ 目录下。

例如用如下命令 select pg_read_file('/2014_11//pg_xlog/info.xml'); 即可直接看到文件的内容。但是这个命令返回的数据类型是 TEXT,还不能直接插入数据表,需用用 CAST ... AS XML 将其转变为XML类型再插入。

INSERT INTO test.xml_demo("xx") VALUES(CAST(pg_read_file('/2014_11//pg_xlog/info.xml') AS XML));

此处 ./pg_xlog/ 这个是相对目录的表示方法,这个点不能去掉,否则它会提示 “ERROR: absolute path not allowed ,SQL 状态: 42501”,即不能用绝对目录表示。

方法二、文件可以放在客户机任意目录下

当前,前提是客户机所用的系统用户有权限读取该文件。原理是先通过客户端的命令 lo_import() 将文件读取为一个 oid(big object对象), 然后用服务器端的命令 lo_read() 将此oid的内容读取,进而转换为XML即可。

在此例子中,我将 info.xml 文件存放在 z:/work/ 目录下

现在在我的测试中,需要将这两步骤分开做,如果写在一个同一行的命令中,可能导致后一步的命令无法找到这个 oid 对象。我估计可能是由于数据库中这两步是同步执行,所以可能第一步还没有运行并返回结果,就直接开始了第二步,此时服务器端可能还没来得及得知第一步的运行结果。

第一步:

SELECT lo_import('/2014_11/z/work/info.xml')

返回的结果是oid对象的编号,例如我得到的这个编号是 184031, 把这个结果记下来。

第二步:

INSERT INTO test.xml_demo("xx") VALUES(CAST(REPLACE(lo_get(184031)::TEXT,'\012',CHR(13)) AS XML))

详细解释一下, lo_get(184031) 是将此oid的内容读取出来,读出来的结果应该是 bytea, 还不能直接转换为 XML, 于是用::TEXT  转换为TEXT类型,但转换过程中原来文本中的回车会被转换为 '\012' 字符,于是用 REPLACE(... , '012', CHR(13)) 将其转换为文字型的回车符,最后就用 CAST(... AS XML)函数,将其转换为XML类型,接着就可以直接插入了。

当然,此处没有解决的一个问题是,第一步结束后的那个 oid 编号,尚未找到办法将其作为一个变量储存,而需要在第二行sql语句中,直接输入这个编号。不过问题不是很大,因为我一般都会在其他语言,如Matlab, Python中调用这个语句,所以将其编号暂存在外部语句中也可以的。

测试成结果

具体的命令不解释了,直接读取这个XML中的“matlabrelease”部分的值:

SELECT xpath('//matlabrelease/text()' ,"xx") FROM test.xml_demo;

返回的就是Matlab的版本号,注意是xml格式的,例如我这里返回 "{R2012a}"

No related posts.

Series Navigation<< Postgresql 9.4发布及操作备忘Json-Matlab-Postgresql联合运用的初步实践 >>
Bookmark/FavoritesSina WeiboGoogle+FacebookQQTwitterYahoo BookmarksBaiduDiggEmailGoogle GmailOutlook.comEvernotePrintAIMLinkedInBlogger PostKindle ItShare

Related Posts:

 Leave a Reply

(required)

(required)


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>