将整个文件导入为一个字符串

时间:2014-02-02 19:14:39

标签: python bash postgresql psql

如何将整个文件作为一个字符串导入PostgreSQL?

create table text_files (
  id serial primary key,
  file_content text
);

我尝试了\copy text_files (file_content) from /home/test.txt,但这会在文本文件中每行创建一行。

我有数百个小文本文件,我想在里面使用一些带有\copy的bash循环。

更新:如果bash和\copy不是此任务的最佳工具集,我可以使用其他编程语言 - 也许Python可以提供。

4 个答案:

答案 0 :(得分:3)

如果你真的必须用bash来做,你需要手动做一些事情:

psql regress -c "insert into text_files(file_content) values ('$(sed "s/'/''/g" test.txt)');"

但它会有点脆弱。我个人建议使用更复杂的脚本语言。它还会将整个文件至少加载到内存中几次。

psql\lo_import,但会将文件导入pg_largeobject,而不是text字段。

答案 1 :(得分:1)

这是由文档制作的python中的一个基本示例!

请注意,没有使用try catch块(这是不好的),但它应该有效。你最终可能会遇到UTF-8错误,IO错误或者我没有打扰的东西(我会在必要时修改代码)......无论如何,将下面的代码保存到文件中(假设“myfile.py”) ,输入正确的信息以连接到您的数据库,用实际路径替换“/ path / to / files /”,最后在控制台中运行“python myfile.py”。

如果您有大量文件,可能需要一些时间,并注意系统的内存状态。每个文件都将被读取并放入系统的内存中。如果文件大小超过内存限制,脚本可能会崩溃。如果文件很小,你就可以了。

先测试一下!

要求:安装了psycopg2的python

import os
import psycopg2

connection = psycopg2.connect(database='my_db', user='my_postgres_user', password='my_postgres_pass')
cursor = connection.cursor()
cursor.execute('DROP TABLE IF EXISTS text_files;CREATE TABLE text_files (id SERIAL UNIQUE PRIMARY KEY, file_name TEXT, file_content TEXT);')

directory = os.path.normpath('/path/to/files/')

for root, dirs, files in os.walk(directory):
  for filename in files:
    print filename
    with open(os.path.join(root, filename), 'rb+') as f:
      cursor.execute('INSERT INTO text_files (file_name, file_content) VALUES (%s, %s);', (filename, f.read()))
    f.closed  

connection.commit()
cursor.close()
connection.close()

答案 2 :(得分:0)

例如,你有这个文件:

test
test
create table text_files (
  id serial primary key,
  file_content text
);
test
create table text_files (
  id serial primary key,
  file_content text
);

运行sed命令:

sed '/(/{:a;N;/)/!ba};s/\n/ /g' file

test
test
create table text_files (   id serial primary key,   file_content text );
test
create table text_files (   id serial primary key,   file_content text );

它会将创建表格行合并为一个,这是你要找的吗?

答案 3 :(得分:0)

我最终使用临时表,其中文件按行存储。

表格设计:

drop table if exists text_files_temp;
create table text_files_temp (
  id serial primary key,
  file_content text
);

drop table if exists text_files;
create table text_files (
  id serial primary key,
  file_name text,
  file_content text
);

Bash脚本:

#!/bin/sh

for f in /home/tgr/tmp/*
do
  psql -c"delete from text_files_temp;"
  psql -c"\copy text_files_temp (file_content) from $f delimiter '$'"
  psql -c"insert into text_files (file_content) select array_to_string(array_agg(file_content order by id),E'\n') from text_files_temp;"
  psql -c"update text_files set file_name = '$f' where file_name is null;"    
done

这仅适用于没有$字符的文件 - 我文件中唯一可用的字符。