Postgres:在表中插入动态的列数和值

时间:2019-02-18 09:48:53

标签: postgresql

我对Postgres SQL非常陌生。我的要求是传递动态数量的columnId,columnValue对并​​将此组合插入表中(例如:employeeId,employeeName组合)。列表的长度可以是任何值。我正在考虑在代码端构建动态查询,并将其作为字符串传递给函数并执行语句。有没有更好的方法来解决此问题。任何示例或想法将不胜感激。

1 个答案:

答案 0 :(得分:2)

如果允许您将该信息作为结构化JSON值传递,这将变得非常容易。 Postgres具有使用功能json_populate_record

将JSON值映射到表类型的功能

样品表:

create table some_table 
( 
  id integer primary key, 
  some_name text, 
  some_date date, 
  some_number integer
);

插入函数:

create function do_insert(p_data text)
 returns void
as 
$$
  insert into some_table (id, some_name, some_date, some_number)
  select (json_populate_record(null::some_table, p_data::json)).*;
$$
language sql;

然后您可以使用:

select do_insert('{"id": 42, "some_name": "Arthur"}');
select do_insert('{"id": 1, "some_value": 42}');

请注意,使用此方法将不属于所传递的JSON字符串的列明确设置为NULL

如果传递的字符串包含不存在的列名,则将其忽略,因此

select do_insert('{"id": 12, "some_name": "Arthur", "not_there": 123}');

将忽略not_there“列”。

在线示例:https://rextester.com/JNIBL25827


修改

可以使用类似的方法进行更新:

create function do_update(p_data text)
 returns void
as 
$$
  update some_table 
     set id = t.id,
         some_name = t.some_name, 
         some_date = t.some_date, 
         some_number = t.some_number
  from json_populate_record(null::some_table, p_data::json) as t;
$$
language sql;

或使用insert on conflict通过一个功能涵盖两个用例:

create function do_upsert(p_data text)
 returns void
as 
$$
  insert into some_table (id, some_name, some_date, some_number)
  select (json_populate_record(null::some_table, p_data::json)).*
  on conflict (id) do update
     set id = excluded.id,
         some_name = excluded.some_name, 
         some_date = excluded.some_date, 
         some_number = excluded.some_number
$$
language sql;