【问题标题】:Extract data from PostgreSQL DB without using pg_dump不使用 pg_dump 从 PostgreSQL 数据库中提取数据
【发布时间】:2010-05-05 05:17:53
【问题描述】:

有一个 PostgreSQL 数据库,我只有有限的访问权限(例如,我不能使用 pg_dump)。我正在尝试通过从数据库中导出 certain 表来创建本地“镜像”。我没有从 psql 中将表转储为 SQL 所需的权限。现在,我只有一个 Python 脚本,它遍历我的 table_names,选择所有字段,然后将它们导出为 CSV:

for table_name, file_name in zip(table_names, file_names):
    cmd = """echo "\\\copy (select * from %s)" to stdout WITH CSV HEADER | psql -d remote_db | gzip > ./%s/%s.gz"""%(table_name,dir_name,file_name)
    os.system(cmd)

如果可能,我不想使用 CSV,因为我会丢失字段类型并且编码可能会变得混乱。首先最好的方法可能是使用 \copy 获取为表生成 SQL 代码的某种方式。下一个最好的方法是 XML,最好是通过某种方式保留字段类型。如果这不起作用,我认为最后的选择可能是两个查询——一个获取字段数据类型,另一个获取实际数据。

任何想法或建议将不胜感激 - 谢谢!

【问题讨论】:

  • 如何连接数据库? ODBC、JDBC (Jython)、Pygres、psycopg?
  • 为什么不能使用pg_dump?你认为你必须拥有什么样的权限才能使用 pg_dump?

标签: python sql xml postgresql


【解决方案1】:

这让我有点困惑“我没有从 psql 中将表转储为 SQL 所需的权限。” pg_dumppsql 之外独立运行(两者都是客户端) 如果您有权连接到数据库并选择一个表,我猜您也可以使用pg_dump -t <table> 转储它。我错过了什么吗?

【讨论】:

    【解决方案2】:

    如果您使用psycopg2,您可以使用cursor.description 来检查列名,并使用获取的数据类型将其转换为所需的字符串,如数据到可接受的格式。

    此代码创建INSERT 语句,您不仅可以将其用于 PostgreSQL,还可以用于其他数据库(然后您可能必须更改日期格式):

    cursor.execute("SELECT * FROM %s" % (table_name))
    column_names = []
    columns_descr = cursor.description
    for c in columns_descr:
        column_names.append(c[0])
    insert_prefix = 'insert into %s (%s) values ' % (table_name, ', '.join(column_names))
    rows = cursor.fetchall()
    for row in rows:
        row_data = []
        for rd in row:
            if rd is None:
                row_data.append('NULL')
            elif isinstance(rd, datetime.datetime):
                row_data.append("'%s'" % (rd.strftime('%Y-%m-%d %H:%M:%S') ))
            else:
                row_data.append(repr(rd))
        print('%s (%s);' % (insert_prefix, ', '.join(row_data)))
    

    在 psycopg2 中甚至支持COPY。看:their docs上的COPY相关方法

    如果您更喜欢使用元数据,那么您可以使用我的食谱:Dump PostgreSQL db schema to text。它基于 Lorenzo Alberton 的 Extracting META information from PostgreSQL

    【讨论】:

      【解决方案3】:

      您可以使用这些查询(通过使用“psql --echo-hidden”和“\d”获得)来获取基本元数据:

      -- GET OID
      SET oid FROM pg_class WHERE relname = <YOUR_TABLE_NAME>
      
      -- GET METADATA
      SELECT a.attname,
        pg_catalog.format_type(a.atttypid, a.atttypmod),
        (SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128)
         FROM pg_catalog.pg_attrdef d
         WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef),
         a.attnotnull, a.attnum
      FROM pg_catalog.pg_attribute a
      WHERE a.attrelid = <YOUR_TABLES_OID_FROM_PG_CLASS> AND a.attnum > 0 AND NOT a.attisdropped
      ORDER BY a.attnum;
      

      这将为您提供名称、数据类型、默认值、空标志和行内的字段顺序。要获得实际数据,最好的选择仍然是 CSV——内置的 COPY 表 TO STDOUT WITH CSV HEADER 非常强大。但如果您担心编码,请务必在转储 CSV 数据之前获取 server_encoding 和 client_encoding 的值。结合上述查询中的元数据,应该可以提供足够的信息来正确解释 CSV 转储。

      【讨论】:

        猜你喜欢
        • 2015-06-29
        • 1970-01-01
        • 2011-01-13
        • 1970-01-01
        • 2021-02-05
        • 2012-01-29
        • 1970-01-01
        • 2014-02-18
        • 2015-07-21
        相关资源
        最近更新 更多