我想知道 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 已经知道我的列,而且我已经将它们映射到数据上。为什么要以更长的格式再次这样做?
如果您只想更新数据,我不确定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)
实际上有一个更短的语法变体,从 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并在函数中执行所有操作: