我正在使用Postgres并希望制作一个可以从CSV文件中获取的大型更新查询,假设我有一张表(id, banana, apple)
。
我想运行一个更新香蕉而不是苹果的更新,每个新香蕉及其ID都将在CSV文件中。
我试着查看Postgres网站,但这些例子正在扼杀我。
答案 0 :(得分:125)
我会COPY
将文件放到临时表中并从那里更新实际的表。
可能看起来像这样:
CREATE TEMP TABLE tmp_x (id int, apple text, banana text); -- but see below
COPY tmp_x FROM '/absolute/path/to/file' (FORMAT csv);
UPDATE tbl
SET banana = tmp_x.banana
FROM tmp_x
WHERE tbl.id = tmp_x.id;
DROP TABLE tmp_x; -- else it is dropped at end of session automatically
如果导入的表与要更新的表匹配,则可能很方便:
CREATE TEMP TABLE tmp_x AS SELECT * FROM tbl LIMIT 0;
创建一个与现有表的结构匹配的空临时表,没有约束。
SQL COPY
需要超级用户权限。 (The manual):
COPY
仅允许将文件或命令命名为数据库 超级用户,因为它允许读取或写入任何文件 服务器有权访问。
psql 元命令 \copy
适用于任何数据库角色。 The manual:
执行前端(客户端)副本。这是一个运行的操作 SQL COPY命令,而不是服务器读取或写入 指定的文件,psql读取或写入文件并路由数据 服务器和本地文件系统之间。这意味着该文件 可访问性和权限是本地用户的权限,而不是 服务器,并且不需要SQL超级用户权限。
临时表的范围仅限于单个角色的单个会话,因此上述操作必须在同一个psql会话中执行:
CREATE TEMP TABLE ...;
\copy tmp_x FROM '/absolute/path/to/file' (FORMAT csv);
UPDATE ...;
如果您使用bash命令编写脚本,请确保将其全部包含在单 psql调用中。像:
echo 'CREATE TEMP TABLE tmp_x ...; \copy tmp_x FROM ...; UPDATE ...;' | psql
通常,您需要元命令\\
在psql中的psql元命令和SQL命令之间切换,但\copy
是此规则的一个例外。再次手册:
特殊解析规则适用于
\copy
元命令。与大多数其他元命令不同,该行的整个剩余部分始终被视为\copy
的参数,并且在参数中不执行变量插值或反引号扩展。
如果import-table很大,可能需要为会话暂时增加temp_buffers
(会话中的第一件事):
SET temp_buffers = '500MB'; -- example value
向临时表添加索引:
CREATE INDEX tmp_x_id_idx ON tmp_x(id);
并手动运行ANALYZE
,因为autovacuum / auto-analyze不包含临时表。
ANALYZE tmp_x;
相关答案:
答案 1 :(得分:-1)
您可以尝试下面用python编写的代码,输入文件是csv文件,您要将其内容更新到表中。每行都基于逗号进行拆分,因此对于每行,row [0]是第一列下的值,row [1]是第二列下的值,等等。
import csv
import xlrd
import os
import psycopg2
import django
from yourapp import settings
django.setup()
from yourapp import models
try:
conn = psycopg2.connect("host=localhost dbname=prodmealsdb
user=postgres password=blank")
cur = conn.cursor()
filepath = '/path/to/your/data_to_be_updated.csv'
ext = os.path.splitext(filepath)[-1].lower()
if (ext == '.csv'):
with open(filepath) as csvfile:
next(csvfile)
readCSV = csv.reader(csvfile, delimiter=',')
for row in readCSV:
print(row[3],row[5])
cur.execute("UPDATE your_table SET column_to_be_updated = %s where
id = %s", (row[5], row[3]))
conn.commit()
conn.close()
cur.close()
except (Exception, psycopg2.DatabaseError) as error:
print(error)
finally:
if conn is not None:
conn.close()