【问题标题】:postgresql / plpgsql - function with a loop and multiple actionspostgresql / plpgsql - 具有循环和多个动作的函数
【发布时间】:2019-12-18 17:22:52
【问题描述】:

我对 Postgres 还很陌生,但我已经通过 pgAdmin 4.15 创建了一个函数,Postgres 的版本是 9.6。
问题是我不能让它工作,我认为语法有问题?
INSERT 和 UPDATE 语句在起作用(在函数之外),所以它必须是函数语法...

目的是通过 jdbc 插件 (Logstash) 调用此函数,并使用给定的“输入”字符串作为键更新一些表。
“键”用于选择要操作的警报 ID。
因此,对于我获得的每个 id,我都需要对这些表执行一些 UPDATE/INSERT。

# \sf close_event
CREATE OR REPLACE FUNCTION public.close(input text)
 RETURNS void
 LANGUAGE plpgsql
AS $function$
DECLARE
  _event_idnumber INTEGER;
BEGIN
  FOR _event_idnumber IN
    SELECT id FROM public.alerts WHERE data ->> 'field_name' = input
  LOOP
    INSERT INTO public.comments ( created_date, content, alert_id, user_id) VALUES (current_timestamp, 'text1 text', _event_idnumber, 1);
    INSERT INTO public.comments ( created_date, content, alert_id, user_id) VALUES (current_timestamp, 'text2 text.', _event_idnumber, 1);
    INSERT INTO public.analysis ( alert_id, created_date, last_updated, notes) VALUES (_event_idnumber, current_timestamp, current_timestamp, 'text3 text');
    UPDATE public.alerts SET status='DONE', outcome='completed', last_updated=current_timestamp, assigned_user_id=1 WHERE id = _event_idnumber;
    UPDATE public.alerts SET data = jsonb_set(data, '{other_field}'::text[], input::jsonb) WHERE id = _event_idnumber;
  END LOOP;
  COMMIT;
EXCEPTION
  WHEN OTHERS THEN
END;
$function$;

我已经读过某些版本的 postgres 我必须使用 DO 语句,但不知道如何使用。
我正在按照此页面上的说明进行操作:https://www.postgresql.org/docs/9.6/plpgsql-control-structures.html

【问题讨论】:

  • 你不需要循环或函数
  • 您还需要更具体地说明您要完成的工作。代码只会告诉我们您实现了什么,而不是您的意图。

标签: sql postgresql plpgsql


【解决方案1】:

因为 SQL 是一种基于集合的语言,用于直接、逻辑的操作,所以您应该在集合中处理追加和更新,而不是像注释那样处理迭代循环调用。因此,将过程语言plpgsql 转换为纯sql。具体来说,考虑使用UNION 选择插入并结合更新语句。

CREATE OR REPLACE FUNCTION public.close(input text)
 RETURNS void
 LANGUAGE sql
AS $function$

   -- COMMENTS INSERT
   INSERT INTO public.comments (created_date, content, alert_id, user_id) 
   SELECT current_timestamp, 'text1 text', a.id, 1
   FROM public.alerts a
   WHERE a.data ->> 'field_name' = input

   UNION ALL

   SELECT current_timestamp, 'text2 text.', a.id, 1
   FROM public.alerts a
   WHERE a.data ->> 'field_name' = input;

   -- ANALYSIS INSERT
   INSERT INTO public.analysis (alert_id, created_date, last_updated, notes) 
   SELECT a.id, current_timestamp, current_timestamp, 'text3 text'
   FROM public.alerts a
   WHERE a.data ->> 'field_name' = input;

   -- ALERTS UPDATE
   UPDATE public.alerts a
   SET status='DONE', 
       outcome='completed', 
       last_updated=current_timestamp, 
       assigned_user_id=1,
       data = jsonb_set(data, '{other_field}'::text[], input::jsonb) 
   WHERE a.data ->> 'field_name' = input;

$function$;

Online demo (使用随机mydata表中的40行'postgres')

【讨论】:

  • 是的!谢谢!您的解决方案非常完美,我只更改了 data = jsonb_set(data, '{other_field}'::text[], to_json(input::text)::jsonb) 中 data 列的最后一次更新,因为它需要一个 json 字符串。
  • 很高兴听到并乐于提供帮助!编码愉快!
猜你喜欢
  • 1970-01-01
  • 2014-12-04
  • 1970-01-01
  • 1970-01-01
  • 2015-04-05
  • 2020-02-04
  • 2017-12-11
  • 1970-01-01
  • 2015-07-22
相关资源
最近更新 更多