PostgresQL:使用键值而不是两个列表插入
PostgresQL: Insert with key-value instead of two lists
PostgresQL 允许您使用两个列表进行 INSERT,一个是字段名,另一个是值。
INSERT INTO products (product_no, name, price) VALUES (1, 'Cheese', 9.99);
对于长列表,很难确定您在哪个列表索引上。有没有办法通过在值旁边指定列名来插入,即键值对?注意:这与 hstore
.
不同
即
INSERT INTO products (product_no => 1, name => 'Cheese', price => 9.99);
常规DML是不可能的。
替代方案:
使用值列表来缩短 DML:
INSERT INTO products (product_no, name, price) VALUES
(1, 'Cheese', 9.99),
(2, 'Sausages', 9.99),
...;
或者创建可以使用参数指定执行的函数:
create or replace function insert_product(
in product_no products.product_no%type,
in name products.name%type,
in price products.price%type) returns products.product_no%type as $$
insert into products(product_no, name, price) values (product_no, name, price) returning product_no;
$$ language sql;
select insert_product(1, 'Mashrooms', 1.99); -- Parameters by order
select insert_product(product_no := 2, name := 'Cheese', price := 9.99); -- Parameters by name
select insert_product(product_no := 3, price := 19.99, name := 'Sosages'); -- Order does mot matter
我创建了一个供我使用。下面将 json 作为输入并创建动态 SQL 查询并执行相同的查询。
示例用法
create table employee(name character varying(20), address character varying(100), basic integer);
--sample call-1
call insert_into(true, 'employee', '{
"name" : "''Ravi Kumar''",
"address" : "''#1, 2nd Cross, Bangalore''",
"basic" : 35000
}',
'');
--sample call-2
call insert_into(true, 'employee', '{
"name" : "eo.name",
"address" : "eo.address",
"basic" : "eo.basic"
}',
'
from employee_old eo
');
程序
CREATE or REPLACE PROCEDURE insert_into(
debug BOOLEAN,
tableName TEXT,
jsonTxt json,
fromWhere TEXT
)
LANGUAGE plpgsql
as $$
DECLARE
field TEXT;
fieldQuery TEXT;
valueQuery TEXT;
finalQuery TEXT;
noOfRecords INT;
BEGIN
IF debug THEN
raise notice 'preparing insert query';
END IF;
fieldQuery := CONCAT('INSERT INTO ', tableName, '(', E'\n');
valueQuery := CONCAT('SELECT ', E'\n');
FOR field IN SELECT * FROM json_object_keys(jsonTxt)
LOOP
fieldQuery := CONCAT(fieldQuery, field, E',\n');
valueQuery := CONCAT(valueQuery, json_extract_path_text(jsonTxt, field), E',\n');
END LOOP;
fieldQuery := RTRIM(fieldQuery, E',\n');
fieldQuery := CONCAT(fieldQuery, ')');
valueQuery := RTRIM(valueQuery, E',\n');
finalQuery := CONCAT(fieldQuery, E'\n', valueQuery, E'\n', fromWhere, ';');
IF debug THEN
RAISE NOTICE 'query:: %', finalQuery;
END IF;
EXECUTE finalQuery;
get diagnostics noOfRecords = row_count;
RAISE NOTICE 'Inserted:: %', noOfRecords;
END
$$;
PostgresQL 允许您使用两个列表进行 INSERT,一个是字段名,另一个是值。
INSERT INTO products (product_no, name, price) VALUES (1, 'Cheese', 9.99);
对于长列表,很难确定您在哪个列表索引上。有没有办法通过在值旁边指定列名来插入,即键值对?注意:这与 hstore
.
即
INSERT INTO products (product_no => 1, name => 'Cheese', price => 9.99);
常规DML是不可能的。
替代方案:
使用值列表来缩短 DML:
INSERT INTO products (product_no, name, price) VALUES
(1, 'Cheese', 9.99),
(2, 'Sausages', 9.99),
...;
或者创建可以使用参数指定执行的函数:
create or replace function insert_product(
in product_no products.product_no%type,
in name products.name%type,
in price products.price%type) returns products.product_no%type as $$
insert into products(product_no, name, price) values (product_no, name, price) returning product_no;
$$ language sql;
select insert_product(1, 'Mashrooms', 1.99); -- Parameters by order
select insert_product(product_no := 2, name := 'Cheese', price := 9.99); -- Parameters by name
select insert_product(product_no := 3, price := 19.99, name := 'Sosages'); -- Order does mot matter
我创建了一个供我使用。下面将 json 作为输入并创建动态 SQL 查询并执行相同的查询。
示例用法
create table employee(name character varying(20), address character varying(100), basic integer);
--sample call-1
call insert_into(true, 'employee', '{
"name" : "''Ravi Kumar''",
"address" : "''#1, 2nd Cross, Bangalore''",
"basic" : 35000
}',
'');
--sample call-2
call insert_into(true, 'employee', '{
"name" : "eo.name",
"address" : "eo.address",
"basic" : "eo.basic"
}',
'
from employee_old eo
');
程序
CREATE or REPLACE PROCEDURE insert_into(
debug BOOLEAN,
tableName TEXT,
jsonTxt json,
fromWhere TEXT
)
LANGUAGE plpgsql
as $$
DECLARE
field TEXT;
fieldQuery TEXT;
valueQuery TEXT;
finalQuery TEXT;
noOfRecords INT;
BEGIN
IF debug THEN
raise notice 'preparing insert query';
END IF;
fieldQuery := CONCAT('INSERT INTO ', tableName, '(', E'\n');
valueQuery := CONCAT('SELECT ', E'\n');
FOR field IN SELECT * FROM json_object_keys(jsonTxt)
LOOP
fieldQuery := CONCAT(fieldQuery, field, E',\n');
valueQuery := CONCAT(valueQuery, json_extract_path_text(jsonTxt, field), E',\n');
END LOOP;
fieldQuery := RTRIM(fieldQuery, E',\n');
fieldQuery := CONCAT(fieldQuery, ')');
valueQuery := RTRIM(valueQuery, E',\n');
finalQuery := CONCAT(fieldQuery, E'\n', valueQuery, E'\n', fromWhere, ';');
IF debug THEN
RAISE NOTICE 'query:: %', finalQuery;
END IF;
EXECUTE finalQuery;
get diagnostics noOfRecords = row_count;
RAISE NOTICE 'Inserted:: %', noOfRecords;
END
$$;