2013-07-28 41 views
11

Bây giờ tôi sử dụng để tự phân tích json vào chuỗi chèn như vậyPostgreSQL: chèn dữ liệu vào bảng từ json

insert into Table (field1, field2) values (val1, val2) 

nhưng cách không thoải mái của nó để chèn dữ liệu từ json! tôi đã tìm thấy chức năng json_populate_record và cố gắng sử dụng nó:

create table test (id serial, name varchar(50)); 
insert into test select * from json_populate_record(NULL::test, '{"name": "John"}'); 

nhưng nó không thành công với thông điệp: giá trị null trong cột "id" vi phạm không null constraint PG biết id đó là nối tiếp nhưng giả vờ là một kẻ ngốc. Tương tự nó làm cho tất cả các fieds với mặc định.

Có khoản vay thanh lịch hơn để chèn dữ liệu từ json vào bảng không?

+1

"Tôi tìm thấy hàm' json_populate_record' ". Um. *Ở đâu*? Định nghĩa hàm là gì? Bạn đang chạy PostgreSQL 9.3 beta, hoặc nó là một chức năng bạn cài đặt từ một nơi khác? –

+0

Chức năng 9.3 beta – user2627000

Trả lời

10

Không có cách nào dễ dàng để json_populate_record trả về điểm đánh dấu có nghĩa là "tạo giá trị này".

PostgreSQL không không cho phép bạn chèn NULL để chỉ định giá trị sẽ được tạo. Nếu bạn yêu cầu NULL Pg mong đợi có nghĩa làNULL và không muốn đoán trước bạn. Ngoài ra, hoàn toàn OK để có một cột được tạo ra không có ràng buộc NOT NULL, trong trường hợp đó hoàn toàn tốt đẹp để chèn NULL vào nó.

Nếu bạn muốn có PostgreSQL sử dụng mặc định bảng cho một giá trị có hai cách để làm điều này:

  • Bỏ qua đó hàng từ INSERT cột danh sách; hoặc
  • Rõ ràng viết DEFAULT, mà chỉ có giá trị trong một biểu thức VALUES

Vì bạn không thể sử dụng VALUES(DEFAULT, ...) đây, lựa chọn duy nhất của bạn là để bỏ qua các cột từ cột INSERT-list:

regress=# create table test (id serial primary key, name varchar(50)); 
CREATE TABLE 
regress=# insert into test(name) select name from json_populate_record(NULL::test, '{"name": "John"}'); 
INSERT 0 1 

Có, điều này có nghĩa là bạn phải liệt kê các cột. Hai lần, trên thực tế, một lần trong danh sách SELECT và một lần trong danh sách cột INSERT.

Để tránh sự cần thiết rằng PostgreSQL này sẽ cần phải có một cách để xác định DEFAULT như một giá trị cho một kỷ lục, vì vậy có thể trở lại json_populate_recordDEFAULT thay vì NULL cho các cột không được xác định. Đó có thể không phải là những gì bạn dự định cho tất cả các cột và sẽ dẫn đến câu hỏi về cách DEFAULT sẽ được xử lý khi json_populate_recordkhông đang được sử dụng trong biểu thức INSERT.

Vì vậy, tôi đoán json_populate_record có thể kém hữu ích hơn bạn mong đợi cho các hàng có khóa được tạo.

+0

rất tuyệt. có cách nào để 'UPDATE' quá, dựa trên một đầu vào json? – jney

+0

@ jney Tôi không thực sự chắc chắn những gì bạn đang yêu cầu. Tôi khuyên bạn nên đăng câu hỏi chi tiết mới và liên kết lại câu hỏi này cho ngữ cảnh. –

+0

Thông tin rất hữu ích (tài liệu cho 'json_populate_record' hơi thưa thớt). Nhưng có thực sự dường như là một trường hợp tốt cho một tùy chọn để có hiệu lực của "nơi không có giá trị quy định, sử dụng mặc định". – beldaz

6

Tiếp tục từ Craig's answer, có lẽ bạn cần phải viết một số loại thủ tục lưu trữ để thực hiện các lệnh SQL động cần thiết, giống như như sau:

CREATE OR REPLACE FUNCTION jsoninsert(relname text, reljson text) 
    RETURNS record AS 
$BODY$DECLARE 
ret RECORD; 
inputstring text; 
BEGIN 
    SELECT string_agg(quote_ident(key),',') INTO inputstring 
    FROM json_object_keys(reljson::json) AS X (key); 
    EXECUTE 'INSERT INTO '|| quote_ident(relname) 
    || '(' || inputstring || ') SELECT ' || inputstring 
    || ' FROM json_populate_record(NULL::' || quote_ident(relname) || ' , json_in($1)) RETURNING *' 
    INTO ret USING reljson::cstring; 
    RETURN ret; 
END; 
$BODY$ 
LANGUAGE plpgsql VOLATILE; 

nào sau đó bạn muốn gọi với

SELECT jsoninsert('test', '{"name": "John"}');