2013-04-04 22 views
6

Tôi muốn viết một truy vấn đơn giản để chọn một số cột trong PostgreSQL. Tuy nhiên, tôi vẫn gặp lỗi - tôi đã thử một vài tùy chọn nhưng chúng không hoạt động đối với tôi. Tại thời điểm này tôi nhận được lỗi sau:Chọn các cột có tên cột cụ thể trong PostgreSQL

org.postgresql.util.PSQLException: ERROR: syntax error at or near "column"

Để có được cột với các giá trị thử nghiệm trong followig:

select * from weather_data where column like '%2010%' 

Bất kỳ ý tưởng?

+1

Bạn đang cố gắng trả lại các cột có chứa năm 2010 trong đó hay bạn đang cố trả về các hàng có cột cụ thể có giá trị 2010 được bao gồm? Bạn không thể chọn danh sách các cột như thế này (tốt, có lẽ với sql động bạn có thể) ... – sgeddes

+0

Bạn có cột có tên là cột không? –

+0

Vâng, tôi đang cố gắng trả lại các cột với năm 2010 như là một phần của tên của họ. Ví dụ có các cột có tên: m01y2010 - vì vậy tôi muốn điều đó, cũng như: m02y2010 ... v.v. - và các giá trị được lưu trữ trong các cột đó. Vì vậy, không có cách nào để lựa chọn một danh sách các cột với năm 2010 trong tên của họ !? –

Trả lời

8

column là một reserved word. Bạn không thể sử dụng nó làm định danh trừ khi bạn trích dẫn kép nó. Giống như: "column".

Không có nghĩa là bạn nên làm vậy. Chỉ cần không sử dụng các từ dành riêng làm định danh. Không bao giờ.

Để ...

select a list of columns with 2010 in their name:

.. bạn có thể sử dụng chức năng này để xây dựng các lệnh SQL động từ pg_attribute danh mục hệ thống bảng:

CREATE OR REPLACE FUNCTION f_build_select(_tbl regclass, _pattern text) 
    RETURNS text AS 
$func$ 
    SELECT format('SELECT %s FROM %s' 
       , string_agg(quote_ident(attname), ', ') 
       , $1) 
    FROM pg_attribute 
    WHERE attrelid = $1 
    AND attname LIKE ('%' || $2 || '%') 
    AND NOT attisdropped -- no dropped (dead) columns 
    AND attnum > 0;  -- no system columns 
$func$ LANGUAGE sql; 

Gọi:

SELECT f_build_select('weather_data', '2010'); 

Trả lại một cái gì đó như:

SELECT foo2010, bar2010_id, FROM weather_data; 

Bạn không thể thực hiện điều này hoàn toàn năng động, vì kiểu trả về là không xác định cho đến khi chúng tôi thực sự tạo truy vấn.

+1

Em, tôi thực sự không - tôi chỉ cố gắng tìm kiếm tên cột với năm 2010 như một phần của tên của họ, không phải cột được gọi là cột với năm 2010 như là một phần của một trong các giá trị ... –

+0

Cảm ơn! Sử dụng giải pháp của bạn! –

0

Bạn không thể tìm kiếm tất cả các cột như thế. Bạn phải chỉ định một cột cụ thể.

Ví dụ,

select * from weather_data where weather_date like '%2010%' 

hoặc tốt hơn nhưng nếu nó là một ngày, xác định phạm vi ngày:

select * from weather_data where weather_date between '2010-01-01' and '2010-12-31' 
5

Điều này sẽ giúp bạn có được danh sách các cột trong một bảng cụ thể (bạn có thể tùy chọn thêm schema nếu cần):

SELECT column_name 
FROM information_schema.columns 
WHERE table_name = 'yourtable' 
    and column_name like '%2010%' 

SQL Fiddle Demo

Sau đó bạn có thể sử dụng truy vấn để tạo ra một tuyên bố sql động để trả lại kết quả của bạn.

1

Cố gắng sử dụng các cấu trúc động như sau thường cho biết bạn nên sử dụng định dạng dữ liệu như hstore, json, xml, v.v ... có thể truy cập động.

Bạn có thể nhận danh sách cột động bằng cách tạo SQL ngay lập tức trong ứng dụng của bạn. Bạn có thể truy vấn INFORMATION_SCHEMA để nhận thông tin về các cột của bảng và tạo truy vấn.Có thể thực hiện điều này trong PL/PgSQL và chạy truy vấn được tạo với EXECUTE nhưng bạn sẽ thấy khó có thể làm việc với kết quả RECORD, vì bạn phải nhận và giải mã các tuple tổng hợp, bạn không thể mở rộng kết quả được đặt thành danh sách cột bình thường. Quan sát:

craig=> CREATE OR REPLACE FUNCTION retrecset() returns setof record as $$ 
values (1,2,3,4), (10,11,12,13); 
$$ language sql; 

craig=> select retrecset(); 
    retrecset 
--------------- 
(1,2,3,4) 
(10,11,12,13) 
(2 rows) 

craig=> select * from retrecset(); 
ERROR: a column definition list is required for functions returning "record" 

craig=> select (r).* FROM (select retrecset()) AS x(r); 
ERROR: record type has not been registered 

Tất cả những gì bạn có thể làm là lấy bản ghi thô và giải mã nó trong ứng dụng khách. Bạn không thể chỉ mục vào nó từ SQL, bạn không thể chuyển đổi nó thành bất kỳ thứ gì khác, v.v. Hầu hết các API của khách hàng không cung cấp các cơ sở để phân tích cú pháp biểu diễn văn bản của các bản ghi ẩn danh.

Vì vậy: bạn có thể trả lại các bản ghi động từ PL/PgSQL mà không biết loại kết quả của nó, nó không chỉ đặc biệt hữu ích và nó là một nỗi đau để đối phó với phía khách hàng. Bạn thực sự muốn chỉ sử dụng ứng dụng khách để tạo truy vấn ngay từ đầu.

+0

Và bởi "hơi khó", bạn có nghĩa là "bên cạnh không thể", vì loại trả về không xác định. Bạn sẽ được yêu cầu cung cấp danh sách định nghĩa cột, nhưng nếu bạn biết danh sách định nghĩa cột, bạn sẽ không cần truy vấn động để bắt đầu. Bắt 22. –

+0

@ErwinBrandstetter Bạn có thể gọi hàm trả về 'bản ghi' hoặc' bản ghi setof' mà không có danh sách-định nghĩa cột nếu bạn hài lòng với một bản ghi vô danh chưa được mở rộng trong tập kết quả. Xem câu trả lời cập nhật. –

+0

+1 Cập nhật tốt đẹp. Làm rõ vấn đề. –

0

Tìm thấy này here:

SELECT 'SELECT ' || array_to_string(ARRAY(SELECT 'o' || '.' || c.column_name 
     FROM information_schema.columns As c 
      WHERE table_name = 'officepark' 
      AND c.column_name NOT IN('officeparkid', 'contractor') 
    ), ',') || ' FROM officepark As o' As sqlstmt 

Kết quả là một truy vấn SQL SELECT bạn chỉ cần thực hiện tiếp theo. Nó phù hợp với nhu cầu của tôi kể từ khi tôi ống kết quả trong vỏ như thế này:

psql -U myUser -d myDB -t -c "SELECT...As sqlstm" | psql -U myUser -d myDB 

Đó trả về cho tôi những đầu ra định dạng, nhưng nó chỉ hoạt động trong vỏ. Hy vọng điều này sẽ giúp ai đó một ngày nào đó.