【问题标题】:Is it possible to pass a built in function as an argument to a trigger?是否可以将内置函数作为参数传递给触发器?
【发布时间】:2020-02-13 09:55:38
【问题描述】:

我问这个问题是因为下面的触发器产生了这个错误:

ERROR: syntax error at or near "("
LINE 5: ...cessBlogPostApproval"('Blog Post Approval', concat('Your blo...
^

有问题的触发器:

CREATE TRIGGER "processBlogPostApproval_AFTER_INSERT"
    AFTER INSERT
    ON public."ApprovedBlogPosts"
    FOR EACH ROW
    EXECUTE PROCEDURE public."processBlogPostApproval"('Blog Post Approval', concat('Your blog post, "', SELECT "Title" FROM public."BlogPosts" WHERE "PostID" == NEW."PostID", '"has been approved.'));

问题似乎是由于我传递了一个连接函数作为我的第二个参数,或者更确切地说,我没有正确传递它。希望您能协助确定这两者中的哪一个是问题的原因。

【问题讨论】:

    标签: sql database postgresql database-trigger


    【解决方案1】:

    有时事实证明,做某事最简单/最干净的方法是 --- 不去做。这似乎是这里的情况。您正在处理将消息传递到触发函数的问题,即正确格式化。好吧,因为 trigger function 必须在没有参数的情况下定义。

    使用 CREATE FUNCTION 命令创建触发器过程, 将其声明为没有参数且返回类型为的函数 扳机。

    不要这样做。在触发函数中构建消息。它实际上使那里的代码更容易(IMO)。你没有提供太多细节,所以只是一个最小的例子:

    -- setup
    create table approved_blog_posts( id integer ) ;
    create table blog_posts(id integer, title text) ;
    
    insert into blog_posts( id, title) 
    values (1 ,'Blog Rant') 
         , (2 ,'Still Rant again')
         , (3 ,'Rambling about nut''en!');
    
    -- trigger function 
    create or replace function blog_post_approved()
      returns  trigger
      language plpgsql
    as $$
    declare
        l_title text; 
    begin 
         select title
           into l_title
           from blog_posts
          where id = new.id;
    
        raise notice 'Your blog post "%" has been approved.',l_title;
        return new;
    end; 
    $$;  
    
    -- attach trigger to table    
    create trigger approved_blog_posts_air
        after insert
        on approved_blog_posts
        for each row
        execute procedure blog_post_approved();
    
     -- demo/test
     insert into approved_blog_posts(id) values (1),(3);
    

    【讨论】:

    • 非常感谢您的(宝贵的)反馈,我可能会选择此作为最佳答案,因为鉴于自发布此问题以来我收集的evidence,它似乎是唯一可行的答案。我设计带参数的触发函数的原因实际上是为了尝试抽象函数以实现可重用性。如果有一种方法可以实现它而不是为我的每个表创建触发器函数,那就太好了。
    【解决方案2】:

    这个问题实际上来自于“在连接机制中以及对象命名中的使用。

    我认为你可以完全避免使用 " there as so:

    EXECUTE PROCEDURE public.processBlogPostApproval('Blog Post Approval', concat('Your blog post, "', (SELECT Title FROM public.BlogPosts WHERE PostID == NEW.PostID), '" has been approved.'));
    

    【讨论】:

    • 感谢反馈,但这似乎不是这里的主要问题。一方面,我使用的 DBMS 工具(pgAdmin 4)自动在触发器函数名称周围插入引号,并禁止我手动调整最终 SQL 代码,除非在文本框中指定参数。其次,当我输入“正常”参数时(例如:'Blog Post Approval'、'You have a new notification'、'blah blah blah'),尽管@ 987654322@ 用引号括起来。
    猜你喜欢
    • 1970-01-01
    • 2011-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-29
    • 2021-11-11
    • 1970-01-01
    • 2014-05-26
    相关资源
    最近更新 更多