2010-05-05 129 views
1

有一個PostgreSQL數據庫,我只有有限的訪問權限(例如,我不能使用pg_dump)。我試圖通過從數據庫導出某些表創建本地「鏡像」。我沒有從psql中將錶轉換爲SQL所需的權限。現在,我只是有一個Python腳本,通過我的table_names迭代,選擇所有字段,然後它們導出爲CSV:從PostgreSQL數據庫中提取數據而不使用pg_dump

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,理想情況下用某種方法保留字段類型。如果這不起作用,我認爲最後的選擇可能是兩個查詢---一個是獲取字段數據類型,另一個是獲取實際數據。

任何想法或建議將不勝感激 - 謝謝!

+0

你如何連接到數據庫? ODBC,JDBC(Jython),Pygres,psycopg? – 2010-05-05 05:59:27

+2

你不能使用pg_dump的情況如何?你認爲你必須擁有什麼樣的權限才能使用pg_dump? – 2010-05-05 09:03:40

回答

3

它困擾我一點關於「我沒有權限所需的只是從psql中轉儲爲SQL表。pg_dump獨立運行,外部psql(都是客戶端),如果您有權連接到數據庫並選擇一個表格,我猜你也可以使用pg_dump -t <table>轉儲它。我錯過了什麼嗎?

1

你可以使用這些查詢(得到通過使用「PSQL --echo隱藏」和「\ 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表格使用CSV HEADER進行標準輸出非常強大。但是如果您擔心編碼問題,請確保在轉儲CSV數據之前獲取server_encoding和client_encoding的值。結合上述查詢的元數據應該提供足夠的信息來正確解釋CSV轉儲。

3

如果使用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甚至支持。看看:關於COPY的相關方法their docs

如果你更喜歡使用元數據,那麼你可以使用我的配方:Dump PostgreSQL db schema to text。它基於Extracting META information from PostgreSQL由洛倫佐艾伯頓