Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 将TXT加载到postgres数据库中,将不存在的列填充为null_Python_Database_Postgresql_Psycopg2 - Fatal编程技术网

Python 将TXT加载到postgres数据库中,将不存在的列填充为null

Python 将TXT加载到postgres数据库中,将不存在的列填充为null,python,database,postgresql,psycopg2,Python,Database,Postgresql,Psycopg2,我是一个python新手,所以如果有一个我没有看到的简单解决方案,请原谅我。我有大量的txt文件(~280),需要读入postgres数据库的表中。该表的结构使其包含txt文件中存在的所有可能的列/变量。考虑下面的例子… ID | Var_A | Var_B 1 | Apple | Dog 2 | Peach | Bird file1.txt: ID | Var_A | Var_B 1 | Apple | Dog 2 | Peach | Bird file2.txt: ID | Va

我是一个python新手,所以如果有一个我没有看到的简单解决方案,请原谅我。我有大量的txt文件(~280),需要读入postgres数据库的表中。该表的结构使其包含txt文件中存在的所有可能的列/变量。考虑下面的例子…

ID | Var_A | Var_B
1  | Apple | Dog
2  | Peach | Bird
file1.txt

ID | Var_A | Var_B
1  | Apple | Dog
2  | Peach | Bird
file2.txt

ID | Var_A | Var_B
1  | Apple | Dog
2  | Peach | Bird
ID | Var_A | Var_C
5  | Grape | Cat      
3  | Apple | Dog   
file3.txt

ID | Var_A | Var_B
1  | Apple | Dog
2  | Peach | Bird
ID | Var_B | Var_C
7  | Apple | Cat
6  | Peach | Bird
理想情况下,我希望我的表包含txt文件中的所有数据,并将txt文件中不存在的列/变量记录为空白或null。(为了演示和清晰起见,我在下面将它们写为null。)

ID | Var_A | Var_B
1  | Apple | Dog
2  | Peach | Bird
postgres_表:

ID | Var_A | Var_B
1  | Apple | Dog
2  | Peach | Bird
ID | Var_A | Var_B | Var_C
1  | Apple | Dog   | NULL
2  | Peach | Bird  | NULL
3  | Apple | NULL  | Dog
5  | Grape | NULL  | Cat
6  | NULL  | Peach | Bird
7  | NULL  | Apple | Cat
鉴于文件数量庞大,这一过程需要自动化。我一直在使用python中的psycopg2来完成这项任务,之前做过很多尝试,但都没有成功。我相信
COPY
查询将是最有效的(有数百万行数据),但在尝试将其复制到txt文件时,我很难处理txt文件中不存在的列

ID | Var_A | Var_B
1  | Apple | Dog
2  | Peach | Bird
cursor = db.cursor()
query = "COPY postgres_table FROM '{}'(DELIMITER('|'));".format(~/file1.txt)
cursor.execute(query)
db.commit()
此查询产生以下错误:

ID | Var_A | Var_B
1  | Apple | Dog
2  | Peach | Bird
psycopg2.DataError: missing data for column "Var_C"

也许有人能看到我没有的东西。我还对这项任务的其他潜在解决方案感兴趣。

一个选项是将文本文件作为字符串读取,然后修改字符串以有效地添加空值,然后将其传递给format方法,而不是文件

ID | Var_A | Var_B
1  | Apple | Dog
2  | Peach | Bird

因此,您可以读取文件的第一行,查看缺少哪些字段(将其与数据库表中的字段进行比较),然后添加“|”在字符串的每一行中缺少字段的位置。

您可以使用临时表将所有文件中的数据加载到临时表中,然后使用
plpgsql
甚至
plpython
对其执行所需操作

ID | Var_A | Var_B
1  | Apple | Dog
2  | Peach | Bird
例如:

ID | Var_A | Var_B
1  | Apple | Dog
2  | Peach | Bird
-- Destination table
create table if not exists dest(
  id int,
  var_a varchar,
  var_b varchar,
  var_c varchar);

begin; -- Start transaction

-- Temporary table to load data from all files
create temporary table tt(
  tt_order serial,
  tt_id varchar,
  tt_var_1 varchar,
  tt_var_2 varchar,
  tt_file varchar)
on commit drop; -- It will be drooped at the end of transaction

-- Load data, header will be included
copy tt(tt_id, tt_var_1, tt_var_2) from '~/file1.txt' (delimiter '|', header false);
update tt set tt_file = '~/file1.txt' where tt_file is null;

copy tt(tt_id, tt_var_1, tt_var_2) from '~/file2.txt' (delimiter '|', header false);
update tt set tt_file = '~/file2.txt' where tt_file is null;

copy tt(tt_id, tt_var_1, tt_var_2) from '~/file3.txt' (delimiter '|', header false);
update tt set tt_file = '~/file3.txt' where tt_file is null;

-- Remove spaces
update tt set
  tt_id = trim(tt_id),
  tt_var_1 = trim(tt_var_1),
  tt_var_2 = trim(tt_var_2);

select * from tt;

-- Result is
/*
 tt_order | tt_id | tt_var_1 | tt_var_2 |   tt_file   
----------+-------+----------+----------+-------------
        1 | ID    | Var_A    | Var_B    | ~/file1.txt
        2 | 1     | Apple    | Dog      | ~/file1.txt
        3 | 2     | Peach    | Bird     | ~/file1.txt
        4 | ID    | Var_A    | Var_C    | ~/file2.txt
        5 | 5     | Grape    | Cat      | ~/file2.txt
        6 | 3     | Apple    | Dog      | ~/file2.txt
        7 | ID    | Var_B    | Var_C    | ~/file3.txt
        8 | 7     | Apple    | Cat      | ~/file3.txt
        9 | 6     | Peach    | Bird     | ~/file3.txt
(9 rows)
*/

-- Move data to destination table
do language plpgsql $$
declare
  r record;
  q text;
begin
  for r in select * from tt order by tt_order loop
    if lower(r.tt_id) = 'id' then -- If header from next file
      -- Build insert query
      q := 'insert into dest (id, ' || lower(r.tt_var_1) || ', ' || lower(r.tt_var_2) || ') values ($1::int, $2, $3)';
    else
      -- Insert data record
      execute q using r.tt_id, r.tt_var_1, r.tt_var_2;
    end if;
  end loop;
end; $$;

commit;

select * from dest;

-- Result is
/*
 id | var_a | var_b | var_c 
----+-------+-------+-------
  1 | Apple | Dog   | 
  2 | Peach | Bird  | 
  5 | Grape |       | Cat
  3 | Apple |       | Dog
  7 |       | Apple | Cat
  6 |       | Peach | Bird
(6 rows)
*/