批量更新所有列

Jha*_*ood 4 postgresql update

我想知道 PostgreSQL 是否有更新查询有点像他们的插入值语法。

我目前在此表单中有一组更新的数据:

INSERT INTO bought_in_control_panel(ID,PARENT_ID,BOUGHT_IN_FORM_TYPE_ID,PRIORITY,NAME,HEADING,DESCRIPTION,ICON,BOUGHT_IN_CONTROL_PANEL_FILE_ID)
VALUES(109,1,28,100,'Tooling','Tooling','Enter your Machine Tools here','tooling.png',null);
Run Code Online (Sandbox Code Playgroud)

并且我想将已有的行更新为新数据,我正在寻找类似以下内容的内容,我可以在其中更新所有行而无需重复自己:

UPDATE ON ID
bought_in_control_panel(ID,PARENT_ID,BOUGHT_IN_FORM_TYPE_ID,PRIORITY,NAME,HEADING,DESCRIPTION,ICON,BOUGHT_IN_CONTROL_PANEL_FILE_ID) 
VALUES(
        (109,1,28,100,'Tooling','Tooling','Enter your Machine Tools here','tooling.png',null), 
        (1,0,1,200,'Bought In','Bought In','','boughtin.png',null)
);
Run Code Online (Sandbox Code Playgroud)

以上将检查匹配ID值,并用新数据更新匹配。

注意:我真的希望避免手动映射所有列名。PostgreSQL 已经知道我的列,而且我已经将它们映射到数据上。为什么要以更长的格式再次这样做?

a_h*_*ame 8

如果您只想更新数据,我不确定INSERT您的问题中的陈述是什么。

如果你只想用一条语句更新多行,你可能会寻找这个:

with update_values (ID,PARENT_ID,BOUGHT_IN_FORM_TYPE_ID,PRIORITY,NAME,HEADING,DESCRIPTION,ICON,BOUGHT_IN_CONTROL_PANEL_FILE_ID) as 
(
  VALUES
     (109,1,28,100,'Tooling','Tooling','Enter your Machine Tools here','tooling.png',null), 
     (1,0,1,200,'Bought In','Bought In','','boughtin.png',null)
)
update bought_in_control_panel
   set parent_id = ud.parent_id, 
       bought_in_form_type_id = ud.bought_in_form_type_id,
       ....
from update_values ud
where ud.id = bought_in_control_panel.id;
Run Code Online (Sandbox Code Playgroud)

  • @Jharwood:由于 SQL 标准没有定义这样的“快捷方式”,我怀疑这是否会在 Postgres 中实现。您可以将这样的请求发布到 Postgres 邮件列表:http://www.postgresql.org/community/lists/ (2认同)

Erw*_*ter 5

实际上有一个更短的语法变体,从 Postgres 8.2(2006 年发布!)开始可用。发行说明:

  • 允许UPDATE使用值列表设置多个列 (Susanne Ebrecht)

这基本上是成对分配列和值的简写。语法是UPDATE tab SET (column, ...) = (val, ...).

适用于您的查询:

UPDATE bought_in_control_panel b
SET   (  parent_id,   bought_in_form_type_id,   priority,   name,   heading,   description,   icon,   bought_in_control_panel_file_id) 
    = (v.parent_id, v.bought_in_form_type_id, v.priority, v.name, v.heading, v.description, v.icon, v.bought_in_control_panel_file_id) 
FROM (
   VALUES
      (109,1,28,100,'Tooling','Tooling','Enter your Machine Tools here','tooling.png',null)
    , (1,0,1,200,'Bought In','Bought In','','boughtin.png',null)
   ) AS v(id,parent_id,bought_in_form_type_id,priority,name,heading
         ,description,icon,bought_in_control_panel_file_id)
WHERE  b.id = v.id;
Run Code Online (Sandbox Code Playgroud)

您仍然需要列出所有列,但是您可以消除一些噪音,并且更容易组合列表、复制它并在源表的表别名前面添加。您也可以动态地执行此操作。见下文。

还使用子查询,其工作原理与 CTE 相同,但开销(性能)要少一些。

如果您愿意的话,您甚至可以自由地混合列表和单列。结果没有区别,但对于格式化或更重要的是对于动态生成的命令可能会派上用场:

UPDATE bought_in_control_panel b
SET    parent_id = v.parent_id
    , (  bought_in_form_type_id,   priority,   name,   heading) 
    = (v.bought_in_form_type_id, v.priority, v.name, v.heading) 
    , (  description,   icon,   bought_in_control_panel_file_id) 
    = (v.description, v.icon, v.bought_in_control_panel_file_id) 
FROM (
   VALUES
      (109,1,28,100,'Tooling','Tooling','Enter your Machine Tools here','tooling.png',null)
    , (1,0,1,200,'Bought In','Bought In','','boughtin.png',null)
   ) AS v(id,parent_id,bought_in_form_type_id,priority,name,heading
         ,description,icon,bought_in_control_panel_file_id)
WHERE  b.id = v.id;
Run Code Online (Sandbox Code Playgroud)

一切都在手册中仔细看的

说到动态 SQL,SO 上的相关答案演示了如何从系统目录中获取列列表pg_attribute并在函数中执行所有操作: