PostgreSQL `COPY TO` 命令是否(或可以)保证特定的行顺序?

mag*_*nus 1 sql postgresql copy export-to-csv

我知道 PostgreSQL 9 允许使用该COPY (SELECT ...) ...语法,但我需要一个与 PostgreSQL 7 兼容的解决方案。

例如,COPY TO命令是按照写入表的顺序输出数据,还是使用特定的索引(或主键)?

Cra*_*ger 5

COPY 从物理表的开始到结束,逐页地线性读取表。

如果表是使用COPY或使用一系列INSERTs创建的,而没有任何UPDATEs 或DELETEs 那么这将是它的写入顺序 - 尽管 PostgreSQL 不保证这一点,并且表的顺序在技术上是未定义的。

如果您需要从古老的 PostgreSQL 生成有序的类 CSV 输出,我建议让一个外部程序(例如 Python +psycopg2脚本)连接并执行 a SELECT ... ORDER BY,读取结果,将它们转换为所需的格式,然后将它们写入输出文件。

另一种选择(虽然不能保证有效)是CLUSTER在所需排序键上的原始输入表。这会将表重写为所需的物理顺序,COPY然后在扫描表时发出。

到目前为止,最好的选择是首先不要使用 PostgreSQL 的史前化石版本。

在评论中解释后编辑

您根本不需要COPY,只需要一个模糊有效的提取工具/脚本。您可以使用任何现有的 ETL 工具(Pentaho Kettle、Talend Studio、CloverETL 等),或者只是一个简单的脚本。对于速度,libpq如果您热衷,甚至可以使用C 语言编写一个简单的程序。

这是一个简单的 Python 示例:

#!/usr/bin/env python

import os
import sys
import psycopg2
import csv

csvf = open("csv.out","wb")
csvw = csv.writer(csvf, dialect='excel-tab')

conn = psycopg2.connect("dbname=regress")
curs = conn.cursor()

# Read blocks of 1000 records from the DB
curs.itersize = 1000

curs.execute("SELECT id, name FROM devices ORDER BY id");
csvw.writerow(("id", "name"))
for row in curs:
    csvw.writerow(row)

csvf.close()
Run Code Online (Sandbox Code Playgroud)

当然,它是单线程的、基本的,并且不会自动找出列名,但它为您提供了思路。如果您想要自动列名,请参阅psycopg2 字典游标...或使用像 libpq 或 PgJDBC 这样的直接提供所有元数据的东西。

一个libpq版本可能需要一两个小时的工作。