PostgresQL:插入键值而不是两个列表

Posted

技术标签:

【中文标题】PostgresQL:插入键值而不是两个列表【英文标题】:PostgresQL: Insert with key-value instead of two lists 【发布时间】:2016-02-19 01:12:47 【问题描述】:

PostgresQL 允许您插入两个列表,一个是字段名称,另一个是值。

INSERT INTO products (product_no, name, price) VALUES (1, 'Cheese', 9.99);

对于长列表,很难确定您所在的列表索引。有没有办法通过在值旁边指定列名来插入,即键值对?注意:这与hstore 不同。

即。

INSERT INTO products (product_no => 1, name => 'Cheese', price => 9.99);

【问题讨论】:

【参考方案1】:

常规的 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

【讨论】:

【参考方案2】:

我创建了一个供我使用。下面以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:插入键值而不是两个列表的主要内容,如果未能解决你的问题,请参考以下文章

c# JSON序列化使用值而不是属性名

Oracle Apex 5.1:基于 LOV(值列表)的报告列显示返回值而不是显示值

逗号运算符返回参数列表中的第一个值而不是第二个值?

Laravel 插入默认值而不是通过请求发送的数据

为啥 SQL 服务器在我的表中插入 0 值而不是使用函数的正确值

如何按值而不是按引用将数组添加到列表中?