2016-08-25 78 views
1

我有postgres表,我想在這些表上使用python運行PostgreSQL腳本文件,然後在csv文件中寫入查詢結果。該腳本文件有多個以分號分隔的查詢;。示例腳本如下所示閱讀和使用python postgres腳本

腳本文件:

--Duplication Check 
select p.*, c.name 
from scale_polygons_v3 c inner join cartographic_v3 p 
on (metaphone(c.name_displ, 20) LIKE metaphone(p.name, 20)) AND c.kind NOT IN (9,10) 
where ST_Contains(c.geom, p.geom); 

--Area Check 
select sp.areaid,sp.name_displ,p.road_id,p.name 
from scale_polygons_v3 sp, pak_roads_20162207 p 
where st_contains(sp.geom,p.geom) and sp.kind = 1 
and p.areaid != sp.areaid; 

當我運行Python代碼,它成功地執行沒有任何錯誤,但我面臨的問題是,編寫查詢的結果中一個csv文件。只有上次執行的查詢的結果才寫入csv文件。這意味着第一個查詢結果被第二個查詢覆蓋,第二個查詢結果被第三個覆蓋,直到最後一個查詢。

這裏是我的Python代碼:

import psycopg2 
import sys 
import csv 
import datetime, time 

def run_sql_file(filename, connection): 
''' 
    The function takes a filename and a connection as input 
    and will run the SQL query on the given connection 
''' 
    start = time.time() 

    file = open(filename, 'r') 
    sql = s = " ".join(file.readlines()) 
    #sql = sql1[3:] 
    print "Start executing: " + " at " + str(datetime.datetime.now().strftime("%Y-%m-%d %H:%M")) + "\n" 
    print "Query:\n", sql + "\n" 
    cursor = connection.cursor() 
    cursor.execute(sql) 
    records = cursor.fetchall() 
    with open('Report.csv', 'a') as f: 
     writer = csv.writer(f, delimiter=',') 
     for row in records: 
      writer.writerow(row) 
    connection.commit() 
    end = time.time() 
    row_count = sum(1 for row in records) 
    print "Done Executing:", filename 
    print "Number of rows returned:", row_count 
    print "Time elapsed to run the query:",str((end - start)*1000) + ' ms' 
    print "\t ===============================" 

def main():  
    connection = psycopg2.connect("host='localhost' dbname='central' user='postgres' password='tpltrakker'") 
    run_sql_file("script.sql", connection) 
    connection.close() 

if __name__ == "__main__": 
    main() 

什麼是錯我的代碼?

+0

可能沒有幫助,但代碼看起來不錯。你正在打開文件模式'a',就像[這裏]完成(http://stackoverflow.com/questions/2363731/append-new-row-to-old-csv-file-python) – Matthias

+0

執行腳本單次調用你只會得到最後執行的命令的結果(或者如果出現錯誤,則會出錯)。 – Abelisto

+0

所有的查詢都有相同的列數,它們是相同類型(和順序)? –

回答

1

這是最簡單的將每個查詢輸出爲不同的文件。 copy_expert

query = ''' 
    select p.*, c.name 
    from 
     scale_polygons_v3 c 
     inner join 
     cartographic_v3 p on metaphone(c.name_displ, 20) LIKE metaphone(p.name, 20) and c.kind not in (9,10) 
    where ST_Contains(c.geom, p.geom) 
''' 
copy = "copy ({}) to stdout (format csv)".format(query) 
f = open('Report.csv', 'wb') 
cursor.copy_expert(copy, f, size=8192) 
f.close() 

query = ''' 
    select sp.areaid,sp.name_displ,p.road_id,p.name 
    from scale_polygons_v3 sp, pak_roads_20162207 p 
    where st_contains(sp.geom,p.geom) and sp.kind = 1 and p.areaid != sp.areaid; 
''' 
copy = "copy ({}) to stdout (format csv)".format(query) 
f = open('Report2.csv', 'wb') 
cursor.copy_expert(copy, f, size=8192) 
f.close() 

如果要追加第二輸出到同一個文件,然後自顧自地打開的第一個文件對象。

請注意,這是必要的copy輸出到stdout,以使其可用於copy_expert

+0

這對我有用好吧,但我不明白的代碼,因爲我必須做一些進一步的修改 –

+1

@ShahzadBacha你的意思是爲什麼'copy'到'stdout'?我更新了答案。否則你不明白哪一部分? –

+0

實際上,這應該是一個單獨的問題,但無論如何,我該如何修改代碼,還要計算從查詢返回的行的總數,並且只能在查詢結束時寫入限制行,如「LIMIT 10」 –

1

如果你能夠改變SQL腳本一下,然後在這裏是一個解決辦法:

#!/usr/bin/env python 

import psycopg2 

script = ''' 
    declare cur1 cursor for 
     select * from (values(1,2),(3,4)) as t(x,y); 

    declare cur2 cursor for 
     select 'a','b','c'; 
    ''' 
print script 

conn = psycopg2.connect(''); 

# Cursors exists and available only inside the transaction 
conn.autocommit = False; 

# Create cursors from script 
conn.cursor().execute(script); 

# Read names of cursors 
cursors = conn.cursor(); 
cursors.execute('select name from pg_cursors;') 
cur_names = cursors.fetchall() 

# Read data from each available cursor 
for cname in cur_names: 
    print cname[0] 
    cur = conn.cursor() 
    cur.execute('fetch all from ' + cname[0]) 
    rows = cur.fetchall() 
    # Here you can save the data to the file 
    print rows 


conn.rollback() 

print 'done' 

免責聲明:我是Python的新手。