PostgreSQL在触发器函数内声明并使用串行变量

时间:2015-02-16 10:09:20

标签: sql postgresql triggers

CREATE OR REPLACE FUNCTION function_create_forum()
  RETURNS trigger AS
  $$
  BEGIN
    DECLARE  id_course   serial; 

    select id INTO id_course   FROM INSERTED;

    insert INTO Forum (course,name,type,staff_only) VALUES 
                      (id_course,"Staff lounge",1,true);
    --forum 2 creation
    --forum 3 creation

  END;
  $$
  LANGUAGE plpgsql VOLATILE;

触发器功能应该创建一个新的论坛,只要创建一个课程,该课程有一个“id”字段,它是串行的,这导致问题,因为在“DECLARE”区域内不被接受。

由于在评论中任何人继续指出上面的语法是不正确的(无论在所有其他不使用“serial”的触发器中工作正常)这里是另一个不起作用的代码变体。

CREATE OR REPLACE FUNCTION function_create_forum()
  RETURNS trigger AS
  $$
  DECLARE
    id_course int;
  BEGIN

    select id INTO id_course   FROM INSERTED; 

    insert INTO Forum (course,name,type,staff_only) VALUES 
                      (id_course,"Staff lounge",1,true);
    --forum 2 creation
    --forum 3 creation

  END;
  $$
  LANGUAGE plpgsql VOLATILE;

表创建:

CREATE TABLE Forum (
    course serial REFERENCES Course(id) ON DELETE CASCADE NOT NULL,
    --omitted details
);

CREATE TABLE Course (
    id   serial  UNIQUE NOT NULL, --the primary key is another column
    --omitted details
)

1 个答案:

答案 0 :(得分:5)

正如其他人已经评论过的那样,没有"数据类型"连载。

Quote from the manual

  

数据类型smallserial,serial和bigserial不是真正的类型,而只是符号方便用于创建唯一标识符列(类似于某些其他数据库支持的AUTO_INCREMENT属性)

强调我的

我能看到的一个基本问题是这一行:

select id INTO id_course   FROM INSERTED; 

没有"插入" Postgres中的虚拟表(例如在SQL Server中)如果创建行级触发器,则只需使用NEW变量which is implicitly defined in a trigger function访问新行的值。

另一个问题是"Staff lounge"。双引号用于表示列(或表)名称,而不是字符文字。 Character literals are enclosed in single quotes in SQL

所以你的触发器功能应该是这样的:

CREATE OR REPLACE FUNCTION function_create_forum()
  RETURNS trigger AS
  $$
  BEGIN

    insert INTO Forum (course,name,type,staff_only) VALUES 
                      (new.id,'Staff lounge',1,true);
    --forum 2 creation
    --forum 3 creation

  END;
  $$
  LANGUAGE plpgsql VOLATILE;

您没有向我们展示您的create trigger声明,但它应该是这样的,以确保您创建行级触发器:

CREATE TRIGGER course_insert_trg 
   AFTER INSERT ON course  --<< AFTER is important!
   FOR EACH ROW ---<<< this makes it a row level trigger
   EXECUTE PROCEDURE function_create_forum();