Lệnh sao chép máy khách (\ copy) không có quyền truy cập vào bảng tạm thời?


8

Tôi đang tạo một danh sách các lệnh SQL để xuất một số dữ liệu mà cuối cùng tôi chạy bằng psql -f. Tất cả các truy vấn đều có cùng một tập hợp dữ liệu, vì vậy tôi nghĩ rằng tôi nên tính các tiêu chuẩn và đưa ra một danh sách các id người dùng đủ điều kiện trong một bảng tạm thời như vậy

create temporary table tmp_export_users as (select id from users where ...)

sau đó tham khảo lại điều đó trong các lệnh \ copy của tôi như

\copy (select ... from table where user_id in (select id from tmp_export_users)) TO 'filename.csv' WITH CSV HEADER

Tất cả đều nằm trong cùng một tệp, mỗi dòng trên một dòng và chạy chúng -f Tôi gặp lỗi khi các lệnh sao chép không thể nhìn thấy bảng tạm thời, vì vậy tôi đoán rằng lệnh sao chép máy khách không thực sự sử dụng cùng một postgres phiên như psql.

Đúng không? Có cách nào để thay đổi hành vi đó không?

Câu trả lời:


16

\copy có thể sử dụng một bảng tạm thời.

Đầu tiên tôi đã thử nghiệm và xác nhận điều này với phiên bản 9.0 tại dòng lệnh.
Sau đó, tôi đã tạo một tệp với lệnh meta SQL và psql \copybằng nhiều bảng tạm thời. Điều đó cũng làm việc cho tôi.

CREATE TEMP TABLE tmp as SELECT * FROM tbl;
\copy (SELECT * FROM tmp JOIN tbl USING (id)) TO '/var/lib/postgres/test1.csv';

Gọi:

psql -p5432 mydb -f test.sql

Lưu ý dấu chấm phẩy chấm dứt, là tùy chọn ở cuối tệp (chấm dứt hoàn toàn), nhưng được yêu cầu sau bất kỳ câu lệnh SQL nào khác và sau câu lệnh cuối cùng nếu được thực thi trong psql tương tác.

Thông thường , các lệnh meta psql không thể được trộn lẫn với SQL trên cùng một dòng trong một tệp được thực thi mỗi psql -f. Tôi trích dẫn hướng dẫn trên psql :

Phân tích cú pháp cho các đối số dừng ở cuối dòng hoặc khi tìm thấy dấu gạch chéo ngược không trích dẫn khác. Dấu gạch chéo ngược không trích dẫn được lấy làm khởi đầu của một lệnh meta mới. Chuỗi đặc biệt \\(hai dấu gạch chéo ngược) đánh dấu sự kết thúc của các đối số và tiếp tục phân tích cú pháp các lệnh SQL, nếu có. Bằng cách đó, các lệnh SQL và psql có thể được trộn tự do trên một dòng. Nhưng trong mọi trường hợp, các đối số của một lệnh meta không thể tiếp tục vượt quá cuối dòng.

Quy tắc khác nhau áp dụng sau \copy , mặc dù. Về cơ bản, psql tự động chuyển về chế độ SQL sau khi \copyXem:

Nhưng bạn đã viết bạn có tất cả các lệnh trên các dòng riêng biệt. Vì vậy, đó không thể là lời giải thích trong trường hợp của bạn.


Bỏ qua một bên, bạn đã cân nhắc sử dụng COPY( lệnh SQL ) thay vì \copy( lệnh meta psql ) chưa?

Tất nhiên, tệp mục tiêu sẽ phải là cục bộ cho máy chủ chứ không phải máy khách trong trường hợp này. Và đặc quyền tập tin khác nhau áp dụng. Hướng dẫn sử dụng :

Các tệp có tên trong một COPYlệnh được đọc hoặc ghi trực tiếp bởi máy chủ, không phải bởi ứng dụng khách. Do đó, chúng phải nằm trên hoặc có thể truy cập được vào máy chủ cơ sở dữ liệu, không phải máy khách. Chúng phải có thể truy cập và có thể đọc hoặc ghi được bởi người dùng PostgreSQL (ID người dùng mà máy chủ chạy dưới dạng), chứ không phải máy khách.


sao chép chạy như người dùng postgres, \ copy sao chép kết thúc để ghi vào std out và được chuyển hướng đến tệp bạn gửi nó. Bạn cũng có thể gọi psql, sử dụng \ o để gửi đầu ra đến một tệp và sau đó chạy một bản sao vào thiết bị xuất chuẩn để có được hiệu ứng tương tự.
Scott Marlowe

Để chắc chắn, tôi đã chạy thử nghiệm trong câu trả lời của mình với một siêu người dùng (postgres) và một người dùng giả. Cả hai đều làm việc cho tôi. Kết quả tương tự trên v8.4.
Erwin Brandstetter

1
Vâng, việc người dùng postgres unix có thể truy cập vào những thứ như / tmp hay không tùy thuộc vào những thứ như liệu Selinux có được cài đặt hay không và liệu nó có cho phép nó ra khỏi hộp không. \ Sao chép hoặc sao chép vào thiết bị xuất chuẩn chắc chắn là hai cách đáng tin cậy hơn để sử dụng bản sao.
Scott Marlowe

1
Cám ơn tất cả mọi người vê câu trả lời. Có vẻ như tôi đã bỏ qua việc kết thúc dòng đã tạo một bảng tạm thời bằng dấu chấm phẩy, vì vậy nó không được tạo. Làm việc như mong đợi ngay bây giờ
jkebinger
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.