我正在使用Postgres,并想进行一个大型更新查询,该查询将从CSV文件中提取,可以说我有一个表,该表具有(id, banana, apple)
。
我想运行一个更新来更改香蕉而不是苹果,每个新的香蕉及其ID都将保存在CSV文件中。
我尝试查看Postgres网站,但这些示例使我丧命。
Answers:
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;
无约束地创建一个与现有表结构匹配的空临时表。
SQLCOPY
为此需要超级用户特权。(本手册):
COPY
仅允许数据库超级用户为文件或命令命名,因为它允许读取或写入服务器有权访问的任何文件。
该psql的元命令\copy
适用于任何数据库的作用。手册:
执行前端(客户端)副本。这是运行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
通常,您需要meta命令\\
在psql元命令和psql中的SQL命令之间切换,但这\copy
是该规则的例外。再次手册:
特殊的解析规则适用于
\copy
meta命令。与大多数其他元命令不同,该行的其余全部始终作为的参数\copy
,并且在参数中既不执行变量插值也不执行反引号扩展。
如果导入表很大,则可能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;
相关答案:
COPY tmp_x FROM '/absolute/path/to/file' (DELIMITER ';', HEADER TRUE, FORMAT CSV)
为我工作得更好。见(postgresql.org/docs/9.1/static/sql-copy.html)
USING
与FROM
在UPDATE
语句来
您可以尝试下面用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()