【问题标题】:Accessing external XML files as variables in a PSQL script (sourced from a bash script)将外部 XML 文件作为 PSQL 脚本中的变量访问(源自 bash 脚本)
【发布时间】:2018-04-27 01:47:44
【问题描述】:

this example 之后,我在 *.sql 脚本中使用 PostgreSQL 变量时遇到问题:

  • 我想使用 BASH 脚本迭代多个 XML 数据文件

  • BASH 脚本将 XML 文件名分配给一个变量,然后传递给 SQL 脚本

  • 由该 BASH 脚本调用的 SQL 脚本将这些数据加载到 PostgreSQL 中

如果我直接获取 XML 文件,没有问题;但是,我无法在我的 SQL 脚本中访问该变量:

在我的 SQL 脚本 (hmdb.sql) 中,我可以访问 PSQL 变量 :bash_var(从 BASH 脚本传递):

\echo '\nEXTERNAL VARIABLE (= "datafile", HERE):' :bash_var '\n'

和/或直接引用 XML 文件,

datafile text := 'hmdb/hmdb.xml';

但不作为变量:

datafile text := 'bash_var';

hmdb.sh

#!/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

【问题讨论】:

  • 我每天都要处理大量的 XML 文件,我总是发现这种方法易于实施和维护:stackoverflow.com/questions/49862106/… 这样做可以大大简化数据导入。
  • @JimJones:谢谢;有趣的时机,嗯?在您的回答(其他SO question)中提到,我也在使用xml_split,因为我的文件很大(3.4 GB),而且我遇到了OOM问题。一旦我解决了这个问题,我会在这里发帖。 :-)

标签: xml bash postgresql xpath psql


【解决方案1】:

好的,这是我的解决方案。

我在Persagen.com blog 上发布了更详细的答案。

基本上,我决定废除DO $$DECLARE ... 方法(在SO 49950384 中描述),转而采用下面的简化方法。

然后我就可以访问 BASH / PSQL 共享变量 :bash_var,因此:

xpath('//metabolite', XMLPARSE(DOCUMENT convert_from(pg_read_binary_file(:'bash_var'))))

这是一个示例 SQL 脚本,说明了该用法:

hmdb.sql

\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 '\n[hmdb.sql] bash_var:' :bash_var '\n'

-- 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 长度)超过了 SQL varchar(300) 长度限制,则这些数据会抛出PSQL 错误且表未更新(即空表结果)。

我在此 Gist 上传了此答案中使用的 XML 数据文件

https://gist.github.com/victoriastuart/d1b1959bd31e4de5ed951ff4fe3c3184

直接链接:


更新(2019-05-15)

在我的研究博客文章Exporting Plain Text to PostgreSQL 中详细介绍的后续工作中,我直接将 XML 数据加载到 PostgreSQL 中,而不是使用临时表。

TL/DR。在那个项目中,我观察到了以下改进。

Parameter | Temp Tables  | Direct Import | Reduction
    Time: | 1048 min     | 1.75 min      | 599x
   Space: | 252,000 MB   | 18 MB         | 14,000x

【讨论】:

    猜你喜欢
    • 2013-09-12
    • 2014-03-12
    • 2021-02-24
    • 1970-01-01
    • 1970-01-01
    • 2021-12-26
    • 2017-02-07
    • 1970-01-01
    • 2013-04-07
    相关资源
    最近更新 更多