2

假设我有一些客户数据,如下所示保存在文本文件中:

|Mr   |Peter   |Bradley   |72 Milton Rise   |Keynes    |MK41 2HQ   |
|Mr   |Kevin   |Carney    |43 Glen Way      |Lincoln   |LI2 7RD    | 786 3454

customer我使用以下命令将上述数据复制到我的表中:

\copy customer(title, fname, lname, addressline, town, zipcode, phone) from 'customer.txt' delimiter '|'

然而,事实证明,在数据的各个部分之前和之后都有一些额外的空格字符。我想做的是trim()在将数据复制到表中之前调用 - 实现这一目标的最佳方法是什么?

有没有办法调用trim()每一行的每个值并避免首先插入不干净的数据?

谢谢,

4

2 回答 2

1

我认为解决此问题的最佳方法是将BEFORE INSERT触发器添加到您要插入的表中。这样,您可以编写一个存储过程,该过程将在插入每条记录之前执行,并在需要它的任何列上修剪空白(或执行您可能需要的任何其他转换)。完成后,只需删除触发器(或保留它,如果您不想在这些列中使用空格,这将提高数据完整性)。我认为解释如何在 PostgreSQL 中创建触发器和存储过程可能超出了这个问题的范围,但我将链接到每个文档的文档。

我认为这是最好的方法,因为它比通过文本文件解析或编写 shell 代码更简单。这种消毒是触发器做得非常好而且非常简单的事情。

创建触发器

创建触发函数

于 2013-05-31T13:00:06.650 回答
1

我在其中一个项目中有类似的用例。我的输入文件:

  • 将文件中的行数作为最后一行;
  • 需要在每一行上添加行号;
  • 需要将 file_id 添加到每一行。

我使用以下shell代码:

FACT=$( dosql "TRUNCATE tab_raw RESTART IDENTITY;
COPY tab_raw(file_id,lnum,bnum,bname,a_day,a_month,a_year,a_time,etype,a_value)
 FROM stdin WITH (DELIMITER '|', ENCODING 'latin1', NULL '');
$(sed -e '$d' -e '=' "$FILE"|sed -e 'N;s/\n/|/' -e 's/^/'$DSID'|/')
\.
VACUUM ANALYZE tab_raw;
SELECT count(*) FROM tab_raw;
" | sed -e 's/^[ ]*//' -e '/^$/d'
)

dosql是一个 shell 函数,它psql使用正确的连接信息执行并执行作为参数给出的所有内容。

作为这个操作的结果,我将有$FACT一个变量来保存插入记录的总数(用于错误检测)。

后来我又打了一个dosql电话:

dosql "SET work_mem TO '800MB';
SELECT tab_prepare($DSID);
VACUUM ANALYZE tab_raw;
SELECT tab_duplicates($DSID);
SELECT tab_dst($DSID);
SELECT tab_gaps($DSID);
SELECT tab($DSID);"

从辅助表中获取分析并将数据移动到最终表中。

于 2013-05-31T11:34:50.977 回答