Accessing external XML files as variables in a PSQL script (sourced from a bash script)
在这个例子之后,我在* .sql脚本中使用PostgreSQL变量时遇到问题:
-
我想使用BASH脚本迭代大量XML数据文件
-
BASH脚本将XML文件名分配给变量,该变量将传递给SQL脚本
-
由该BASH脚本调用的SQL脚本将这些数据加载到PostgreSQL中
如果我直接获取XML文件,则没有问题; 但是,在我的SQL脚本中,我无法访问该变量:
在我的SQL脚本(
1 2 3 | \echo ' EXTERNAL VARIABLE (="datafile", HERE):' :bash_var ' ' |
和/或直接引用XML文件,
1 | datafile text := 'hmdb/hmdb.xml'; |
但不是变量:
1 | datafile text := 'bash_var'; |
hmdb.sh
1 2 3 4 5 6 7 8 9 10 | #!/bin/bash DATA_DIR=data/ for file in $DATA_DIR/*.xml do bash_var=$(echo ${file##*/}) echo $bash_var psql -d hmdb -v bash_var=$bash_var -f hmdb.sql done |
好的,这是我的解决方案。
我在Persagen.com博客上发布了更详细的答案。
基本上,我决定废除
然后,我可以访问BASH / PSQL共享变量
1 | xpath('//metabolite', XMLPARSE(DOCUMENT convert_from(pg_read_binary_file(:'bash_var')))) |
这是一个示例SQL脚本,说明了这种用法:
hmdb.sql
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | \c hmdb CREATE TABLE hmdb_identifiers ( id SERIAL, accession VARCHAR(15) NOT NULL, name VARCHAR(300) NOT NULL, cas_number VARCHAR(12), pubchem_cid INT, PRIMARY KEY (id), UNIQUE (accession) ); \echo ' [hmdb.sql] bash_var:' :bash_var ' ' -- UPDATE (2019-05-15): SEE MY COMMENTS BELOW RE: TEMP TABLE! CREATE TEMP TABLE tmp_table AS SELECT (xpath('//accession/text()', x))[1]::text::varchar(15) AS accession ,(xpath('//name/text()', x))[1]::text::varchar(300) AS name ,(xpath('//cas_registry_number/text()', x))[1]::text::varchar(12) AS cas_number ,(xpath('//pubchem_compound_id/text()', x))[1]::text::int AS pubchem_cid -- FROM unnest(xpath('//metabolite', XMLPARSE(DOCUMENT convert_from(pg_read_binary_file('hmdb/hmdb.xml'), 'UTF8')))) x FROM unnest(xpath('//metabolite', XMLPARSE(DOCUMENT convert_from(pg_read_binary_file(:'bash_var'), 'UTF8')))) x ; INSERT INTO hmdb_identifiers (accession, name, cas_number, pubchem_cid) SELECT lower(accession), lower(name), lower(cas_number), pubchem_cid FROM tmp_table; DROP TABLE tmp_table; |
SQL脚本说明:
-
在xpath语句中,我根据Postgres表模式重新构造
::text (例如:::text::varchar(15) )。 -
更重要的是,如果我没有在xpath语句中重新设置数据类型并且字段条目(例如
name 长度)超过SQLvarchar(300) 长度限制,则这些数据会引发PSQL错误并且表未更新(即空白)表结果)。
我在这个Gist上传了这个答案中使用的XML数据文件
https://gist.github.com/victoriastuart/d1b1959bd31e4de5ed951ff4fe3c3184
直接链接:
-
hmdb_metabolites_5000-01.xml
-
hmdb_metabolites_5000-02.xml
-
hmdb_metabolites_5000-03.xml
-
资料来源:HMDB.ca
- 引文
更新(2019-05-15)
在后续工作中,详细内容在我的研究博客文章Exporting Plain Text to PostgreSQL中,我直接将XML数据加载到PostgreSQL中,而不是使用临时表。
TL / DR。在该项目中,我观察到以下改进。
1 2 3 | Parameter | Temp Tables | Direct Import | Reduction Time: | 1048 min | 1.75 min | 599x Space: | 252,000 MB | 18 MB | 14,000x |