Sql 如何使用Postgres中CSV文件中的值更新选定行?

Sql 如何使用Postgres中CSV文件中的值更新选定行?,sql,database,postgresql,file-io,csv,Sql,Database,Postgresql,File Io,Csv,我使用的是Postgres,我想做一个大的更新查询,可以从CSV文件中获取,假设我得到一个表,它包含(id、香蕉、苹果) 我想运行一个更新,改变香蕉,而不是苹果,每个新的香蕉和他们的ID将在一个CSV文件 我试着查看Postgres站点,但是这些示例让我非常痛苦。将文件保存到临时临时暂存表中,然后从那里更新实际的表。比如: CREATE TEMP TABLE tmp_x(id int,apple text,banana text);--但见下文 将tmp_x从'/absolute/path/复制

我使用的是Postgres,我想做一个大的更新查询,可以从CSV文件中获取,假设我得到一个表,它包含
(id、香蕉、苹果)

我想运行一个更新,改变香蕉,而不是苹果,每个新的香蕉和他们的ID将在一个CSV文件

我试着查看Postgres站点,但是这些示例让我非常痛苦。

将文件保存到临时临时暂存表中,然后从那里更新实际的表。比如:

CREATE TEMP TABLE tmp_x(id int,apple text,banana text);--但见下文
将tmp_x从'/absolute/path/复制到/file'(格式为csv);
更新tbl
设置香蕉=tmp_x香蕉
来自tmp_x
其中tbl.id=tmp_x.id;
升降台tmp_x;——否则它会在会话结束时自动删除
如果导入的表与要更新的表完全匹配,这可能很方便:

CREATE TEMP TABLE tmp_x AS SELECT * FROM tbl LIMIT 0;
创建与现有表的结构匹配的空临时表,无约束

特权 SQL
COPY
为此需要超级用户权限。():

COPY
仅允许对数据库命名文件或命令 超级用户,因为它允许读取或写入 服务器具有访问权限

psql元命令
\copy
适用于任何数据库角色

执行前端(客户端)复制。这是一个运行 SQL命令,但不是服务器读取或写入 指定的文件,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 meta命令和SQL命令之间切换,但是
\copy
是此规则的一个例外

特殊解析规则适用于
\copy
元命令。与大多数其他元命令不同,该行的整个剩余部分始终被视为
\copy
的参数,并且在参数中既不执行变量插值也不执行反引号展开

大桌子 如果导入表很大,可能需要为会话临时增加
temp\u buffers
(会话中的第一件事):

向临时表添加索引:

CREATE INDEX tmp_x_id_idx ON tmp_x(id);
并手动运行,因为自动真空/自动分析不包括临时表

ANALYZE tmp_x;
有关答案:


您可以尝试以下用python编写的代码,输入文件是csv文件,您希望将其内容更新到表中。每一行都是基于逗号分割的,因此对于每一行,第[0]行是第一列下的值,第[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()

您并不是在pgadmin3中尝试这样做,是吗?您可能需要某种脚本语言(例如Python等),您还需要澄清“更新”的含义。我的猜测是,您的CSV文件包含的项目可能在数据库中,也可能不在数据库中,您必须插入它们或更新它们-只有在它们是香蕉的情况下。但是,请澄清。是的,不错。当事情有时变得如此简单时,我总是倾向于使用大型机器。@user519753:刚学了一个新名词——从我在互联网上看到的情况来看,“谢谢你!”是正确的<代码>将tmp_x从“/absolute/path/to/file”(分隔符“;”,标题为TRUE,格式为CSV)对我更有效。请参阅()@taper:我通常不带任何参数运行COPY。但是问题是关于CSV的,你可能已经注意到了。这只适用于我(Postgres 9.3),在
更新
-语句中将
使用
替换为
FROM
    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()