Câu trả lời:
Bạn có muốn tập tin kết quả trên máy chủ, hoặc trên máy khách?
Nếu bạn muốn một cái gì đó dễ sử dụng lại hoặc tự động hóa, bạn có thể sử dụng lệnh COPY tích hợp của Postgresql . ví dụ
Copy (Select * From foo) To '/tmp/test.csv' With CSV DELIMITER ',' HEADER;
Cách tiếp cận này chạy hoàn toàn trên máy chủ từ xa - nó không thể ghi vào PC cục bộ của bạn. Nó cũng cần được chạy như một "siêu người dùng" của Postgres (thường được gọi là "root") vì Postgres không thể ngăn nó làm những việc khó chịu với hệ thống tệp cục bộ của máy đó.
Điều đó không thực sự có nghĩa là bạn phải được kết nối như một superuser (tự động đó sẽ là một nguy cơ bảo mật của một loại khác nhau), bởi vì bạn có thể sử dụng các SECURITY DEFINER
tùy chọn đểCREATE FUNCTION
để thực hiện một chức năng mà chạy như thể bạn là một superuser .
Phần quan trọng là chức năng của bạn ở đó để thực hiện kiểm tra bổ sung, không chỉ là vượt qua bảo mật - vì vậy bạn có thể viết một hàm xuất dữ liệu chính xác mà bạn cần hoặc bạn có thể viết một cái gì đó có thể chấp nhận các tùy chọn khác nhau miễn là chúng đáp ứng một danh sách trắng nghiêm ngặt. Bạn cần kiểm tra hai điều:
GRANT
s trong cơ sở dữ liệu, nhưng chức năng hiện đang chạy như một siêu người dùng, do đó, các bảng thường là "ngoài giới hạn" sẽ có thể truy cập đầy đủ. Có lẽ bạn không muốn để ai đó gọi chức năng của mình và thêm hàng vào cuối người dùng của bạn.Tôi đã viết một bài đăng blog mở rộng về phương pháp này , bao gồm một số ví dụ về các chức năng xuất (hoặc nhập) tệp và bảng đáp ứng các điều kiện nghiêm ngặt.
Cách tiếp cận khác là xử lý tệp ở phía máy khách , tức là trong ứng dụng hoặc tập lệnh của bạn. Máy chủ Postgres không cần biết bạn đang sao chép tập tin nào, nó chỉ lấy ra dữ liệu và máy khách sẽ đặt nó ở đâu đó.
Cú pháp cơ bản cho điều này là COPY TO STDOUT
lệnh và các công cụ đồ họa như pgAdmin sẽ gói nó cho bạn trong một hộp thoại đẹp.
Máy psql
khách dòng lệnh có một "lệnh meta" đặc biệt được gọi \copy
, có tất cả các tùy chọn giống như "thực" COPY
, nhưng được chạy bên trong máy khách:
\copy (Select * From foo) To '/tmp/test.csv' With CSV
Lưu ý rằng không có kết thúc ;
, bởi vì các lệnh meta được kết thúc bởi dòng mới, không giống như các lệnh SQL.
Từ các tài liệu :
Đừng nhầm lẫn COPY với hướng dẫn psql \ copy. \ copy gọi COPY TỪ STDIN hoặc SAO CHÉP sang STDOUT, sau đó tìm nạp / lưu trữ dữ liệu trong một tệp có thể truy cập vào máy khách psql. Do đó, quyền truy cập tệp và quyền truy cập tùy thuộc vào máy khách thay vì máy chủ khi \ copy được sử dụng.
Ngôn ngữ lập trình ứng dụng của bạn có thể cũng có hỗ trợ để đẩy hoặc lấy dữ liệu, nhưng bạn không thể thường sử dụng COPY FROM STDIN
/ TO STDOUT
trong một câu lệnh SQL chuẩn, bởi vì không có cách nào để kết nối các dòng đầu vào / đầu ra. Trình xử lý PostgreSQL của PHP ( không phải PDO) bao gồm các hàm rất cơ bản pg_copy_from
và pg_copy_to
chức năng sao chép vào / từ một mảng PHP, có thể không hiệu quả đối với các tập dữ liệu lớn.
\copy
hoạt động - ở đó, các đường dẫn có liên quan đến máy khách và không cần dấu chấm phẩy / cho phép. Xem chỉnh sửa của tôi.
\copy
cần phải là một lót. Vì vậy, bạn không có được vẻ đẹp của việc định dạng sql theo cách bạn muốn và chỉ cần đặt một bản sao / chức năng xung quanh nó.
\copy
là một lệnh meta đặc biệt trong psql
máy khách dòng lệnh . Nó sẽ không hoạt động trong các khách hàng khác, như pgAdmin; họ có thể sẽ có các công cụ riêng, như trình hướng dẫn đồ họa, để thực hiện công việc này.
Có một số giải pháp:
psql
lệnhpsql -d dbname -t -A -F"," -c "select * from users" > output.csv
Điều này có lợi thế lớn mà bạn có thể sử dụng thông qua SSH, như ssh postgres@host command
- cho phép bạn có được
copy
Lệnh 2 postgresCOPY (SELECT * from users) To '/tmp/output.csv' With CSV;
>psql dbname
psql>\f ','
psql>\a
psql>\o '/tmp/output.csv'
psql>SELECT * from users;
psql>\q
Tất cả chúng có thể được sử dụng trong các tập lệnh, nhưng tôi thích # 1 hơn.
Trong thiết bị đầu cuối (trong khi được kết nối với db) đặt đầu ra cho tệp cvs
1) Đặt bộ tách trường thành ','
:
\f ','
2) Đặt định dạng đầu ra không được chỉ định:
\a
3) Chỉ hiển thị các bộ dữ liệu:
\t
4) Đặt đầu ra:
\o '/tmp/yourOutputFile.csv'
5) Thực hiện truy vấn của bạn:
:select * from YOUR_TABLE
6) Đầu ra:
\o
Sau đó, bạn sẽ có thể tìm thấy tệp csv của mình ở vị trí này:
cd /tmp
Sao chép nó bằng scp
lệnh hoặc chỉnh sửa bằng nano:
nano /tmp/yourOutputFile.csv
COPY
hoặc \copy
xử lý chính xác (chuyển đổi sang định dạng CSV tiêu chuẩn); thực hiện điều này?
Nếu bạn quan tâm đến tất cả các cột của một bảng cụ thể cùng với các tiêu đề, bạn có thể sử dụng
COPY table TO '/some_destdir/mycsv.csv' WITH CSV HEADER;
Đây là một chút đơn giản hơn so với
COPY (SELECT * FROM table) TO '/some_destdir/mycsv.csv' WITH CSV HEADER;
trong đó, theo sự hiểu biết tốt nhất của tôi, là tương đương.
Thông tin này không thực sự được thể hiện tốt. Vì đây là lần thứ hai tôi cần có được điều này, tôi sẽ đặt nó ở đây để tự nhắc nhở mình nếu không có gì khác.
Thực sự cách tốt nhất để làm điều này (lấy CSV ra khỏi postgres) là sử dụng COPY ... TO STDOUT
lệnh. Mặc dù bạn không muốn làm theo cách được hiển thị trong các câu trả lời ở đây. Cách chính xác để sử dụng lệnh là:
COPY (select id, name from groups) TO STDOUT WITH CSV HEADER
Thật tuyệt khi sử dụng qua ssh:
$ ssh psqlserver.example.com 'psql -d mydb "COPY (select id, name from groups) TO STDOUT WITH CSV HEADER"' > groups.csv
Thật tuyệt khi sử dụng bên trong docker trên ssh:
$ ssh pgserver.example.com 'docker exec -tu postgres postgres psql -d mydb -c "COPY groups TO STDOUT WITH CSV HEADER"' > groups.csv
Nó thậm chí còn tuyệt vời trên máy cục bộ:
$ psql -d mydb -c 'COPY groups TO STDOUT WITH CSV HEADER' > groups.csv
Hoặc bên trong docker trên máy cục bộ?:
docker exec -tu postgres postgres psql -d mydb -c 'COPY groups TO STDOUT WITH CSV HEADER' > groups.csv
Hoặc trên cụm kubernetes, trong docker, qua HTTPS ??:
kubectl exec -t postgres-2592991581-ws2td 'psql -d mydb -c "COPY groups TO STDOUT WITH CSV HEADER"' > groups.csv
Thật đa năng, nhiều dấu phẩy!
Có tôi đã làm, đây là ghi chú của tôi:
Sử dụng /copy
hiệu quả thực thi các thao tác tệp trên bất kỳ hệ thống nào mà psql
lệnh đang chạy, vì người dùng đang thực thi nó 1 . Nếu bạn kết nối với một máy chủ từ xa, thật đơn giản để sao chép các tệp dữ liệu trên hệ thống thực thi psql
đến / từ máy chủ từ xa.
COPY
thực thi các thao tác tệp trên máy chủ dưới dạng tài khoản người dùng quá trình phụ trợ (mặc định postgres
), đường dẫn và quyền của tệp được kiểm tra và áp dụng tương ứng. Nếu sử dụng TO STDOUT
thì kiểm tra quyền truy cập tập tin được bỏ qua.
Cả hai tùy chọn này đều yêu cầu di chuyển tệp tiếp theo nếu psql
không thực thi trên hệ thống nơi bạn muốn CSV kết quả cuối cùng cư trú. Đây là trường hợp rất có thể, theo kinh nghiệm của tôi, khi bạn chủ yếu làm việc với các máy chủ từ xa.
Việc cấu hình một cái gì đó như đường hầm TCP / IP qua ssh sang hệ thống từ xa sẽ đơn giản hơn đối với đầu ra CSV đơn giản, nhưng đối với các định dạng đầu ra khác (nhị phân), có thể tốt /copy
hơn là kết nối qua đường hầm, thực thi cục bộ psql
. Trong một tĩnh mạch tương tự, đối với nhập khẩu lớn, di chuyển tệp nguồn đến máy chủ và sử dụng COPY
có lẽ là tùy chọn hiệu suất cao nhất.
Với các tham số psql, bạn có thể định dạng đầu ra như CSV nhưng có những nhược điểm như phải nhớ để tắt máy nhắn tin và không nhận được tiêu đề:
$ psql -P pager=off -d mydb -t -A -F',' -c 'select * from groups;'
2,Technician,Test 2,,,t,,0,,
3,Truck,1,2017-10-02,,t,,0,,
4,Truck,2,2017-10-02,,t,,0,,
Không, tôi chỉ muốn lấy CSV ra khỏi máy chủ của mình mà không cần biên dịch và / hoặc cài đặt công cụ.
psql
có thể làm điều này cho bạn:
edd@ron:~$ psql -d beancounter -t -A -F"," \
-c "select date, symbol, day_close " \
"from stockprices where symbol like 'I%' " \
"and date >= '2009-10-02'"
2009-10-02,IBM,119.02
2009-10-02,IEF,92.77
2009-10-02,IEV,37.05
2009-10-02,IJH,66.18
2009-10-02,IJR,50.33
2009-10-02,ILF,42.24
2009-10-02,INTC,18.97
2009-10-02,IP,21.39
edd@ron:~$
Xem man psql
để được giúp đỡ về các tùy chọn được sử dụng ở đây.
Phiên bản mới - psql 12 - sẽ hỗ trợ --csv
.
--csv
Chuyển sang chế độ đầu ra CSV (Giá trị phân tách bằng dấu phẩy). Điều này tương đương với \ pset định dạng csv .
csv_fieldsep
Chỉ định dấu tách trường sẽ được sử dụng ở định dạng đầu ra CSV. Nếu ký tự dấu tách xuất hiện trong giá trị của trường, trường đó là đầu ra trong dấu ngoặc kép, tuân theo quy tắc CSV tiêu chuẩn. Mặc định là dấu phẩy.
Sử dụng:
psql -c "SELECT * FROM pg_catalog.pg_tables" --csv postgres
psql -c "SELECT * FROM pg_catalog.pg_tables" --csv -P csv_fieldsep='^' postgres
psql -c "SELECT * FROM pg_catalog.pg_tables" --csv postgres > output.csv
Trong pgAdmin III, có một tùy chọn để xuất thành tệp từ cửa sổ truy vấn. Trong menu chính, đó là Truy vấn -> Thực thi tệp hoặc có một nút thực hiện điều tương tự (đó là hình tam giác màu xanh lá cây với đĩa mềm màu xanh đối lập với hình tam giác màu lục đơn giản chỉ chạy truy vấn). Nếu bạn không chạy truy vấn từ cửa sổ truy vấn thì tôi sẽ làm những gì IMSoP đề xuất và sử dụng lệnh sao chép.
Tôi đã thử một vài thứ nhưng một vài trong số chúng có thể cung cấp cho tôi CSV mong muốn với các chi tiết tiêu đề.
Đây là những gì làm việc cho tôi.
psql -d dbame -U username \
-c "COPY ( SELECT * FROM TABLE ) TO STDOUT WITH CSV HEADER " > \
OUTPUT_CSV_FILE.csv
Tôi đã viết một công cụ nhỏ gọi là psql2csv
đóng gói COPY query TO STDOUT
mẫu, dẫn đến CSV thích hợp. Giao diện của nó tương tự như psql
.
psql2csv [OPTIONS] < QUERY
psql2csv [OPTIONS] QUERY
Truy vấn được coi là nội dung của STDIN, nếu có hoặc đối số cuối cùng. Tất cả các đối số khác được chuyển tiếp đến psql ngoại trừ:
-h, --help show help, then exit
--encoding=ENCODING use a different encoding than UTF8 (Excel likes LATIN1)
--no-header do not output a header
Tôi rất muốn giới thiệu DataGrip , một IDE cơ sở dữ liệu của JetBrains. Bạn có thể xuất truy vấn SQL sang tệp CSV và có thể dễ dàng thiết lập đường hầm ssh. Khi tài liệu đề cập đến "tập kết quả", chúng có nghĩa là kết quả được trả về bởi một truy vấn SQL trong bảng điều khiển.
Tôi không liên kết với DataGrip, tôi chỉ thích sản phẩm này!
JackDB , một ứng dụng khách cơ sở dữ liệu trong trình duyệt web của bạn, làm cho việc này thực sự dễ dàng. Đặc biệt nếu bạn đang ở Heroku.
Nó cho phép bạn kết nối với cơ sở dữ liệu từ xa và chạy các truy vấn SQL trên chúng.
Nguồn
(nguồn: jackdb.com )
Khi DB của bạn được kết nối, bạn có thể chạy truy vấn và xuất sang CSV hoặc TXT (xem dưới cùng bên phải).
Lưu ý: Tôi không có cách nào liên kết với JackDB. Tôi hiện đang sử dụng các dịch vụ miễn phí của họ và nghĩ rằng đó là một sản phẩm tuyệt vời.
Theo yêu cầu của @ skeller88, tôi đang đăng lại nhận xét của mình dưới dạng câu trả lời để nó không bị mất bởi những người không đọc mọi phản hồi ...
Vấn đề với DataGrip là nó gây khó khăn cho ví tiền của bạn. Nó không miễn phí. Hãy thử phiên bản cộng đồng của DBeaver tại dbeaver.io. Nó là một công cụ cơ sở dữ liệu đa nền tảng FOSS dành cho các lập trình viên SQL, DBA và nhà phân tích hỗ trợ tất cả các cơ sở dữ liệu phổ biến: MySQL, PostgreQuery, SQLite, Oracle, DB2, SQL Server, Sybase, MS Access, Teradata, Firebird, Hive, Presto, v.v.
DBeaver Community Edition khiến việc kết nối với cơ sở dữ liệu trở nên tầm thường, đưa ra các truy vấn để truy xuất dữ liệu và sau đó tải xuống tập kết quả để lưu nó vào CSV, JSON, SQL hoặc các định dạng dữ liệu phổ biến khác. Đây là đối thủ cạnh tranh FOSS khả thi với TOAD cho Postgres, TOAD cho SQL Server hoặc Toad cho Oracle.
Tôi không có liên kết với DBeaver. Tôi yêu giá và chức năng, nhưng tôi ước họ sẽ mở ứng dụng DBeaver / Eclipse nhiều hơn và giúp dễ dàng thêm các widget phân tích vào DBeaver / Eclipse, thay vì yêu cầu người dùng trả tiền cho đăng ký hàng năm để tạo biểu đồ và biểu đồ trực tiếp trong ứng dụng. Các kỹ năng mã hóa Java của tôi rất yếu và tôi không muốn mất hàng tuần để học cách xây dựng các công cụ Eclipse, chỉ để thấy rằng DBeaver đã vô hiệu hóa khả năng thêm các tiện ích của bên thứ ba vào Phiên bản Cộng đồng DBeaver.
Người dùng DBeaver có hiểu biết sâu sắc về các bước để tạo tiện ích phân tích để thêm vào Phiên bản cộng đồng của DBeaver không?
import json
cursor = conn.cursor()
qry = """ SELECT details FROM test_csvfile """
cursor.execute(qry)
rows = cursor.fetchall()
value = json.dumps(rows)
with open("/home/asha/Desktop/Income_output.json","w+") as f:
f.write(value)
print 'Saved to File Successfully'