在从实际表中删除行之前触发从相关表中删除行

时间:2013-11-17 19:29:19

标签: sql postgresql triggers plpgsql sql-delete

我有以下表格:

CREATE TABLE QUESTION(
id varchar(10) NOT NULL PRIMARY KEY,
que_type numeric(1));

CREATE TABLE ESSAY(
que_id varchar(10) NOT NULL PRIMARY KEY,
ans varchar(2000),
FOREIGN KEY (que_id) REFERENCES QUESTION (id));

CREATE TABLE TFFB(
que_id varchar(10) NOT NULL PRIMARY KEY,
ans varchar(50),
FOREIGN KEY (que_id) REFERENCES QUESTION (id));

CREATE TABLE MCQ(
que_id varchar(10) NOT NULL PRIMARY KEY,
ans varchar(200),
FOREIGN KEY (que_id) REFERENCES QUESTION (id));

并尝试创建触发器,以便当我从主表中删除时,它将从其他表中删除相关的行:

CREATE OR REPLACE FUNCTION delete_question()
RETURNS trigger AS $delete_question$
DECLARE
    BEGIN
    IF ( (OLD).que_type = '1' ) THEN
       IF EXISTS (SELECT 1 FROM mcq WHERE person_id = (OLD).id) THEN
          DELETE FROM mcq WHERE que_id='(OLD).id';
       END IF;
    ELSIF ( (OLD).que_type = '2' OR OLD.que_type = '3' ) THEN
       IF EXISTS (SELECT 1 FROM tffb WHERE person_id = (OLD).id) THEN
          DELETE FROM tffb WHERE que_id='(OLD).id';
       END IF;
    ELSIF ( (OLD).que_type = '4' ) THEN
       IF EXISTS (SELECT 1 FROM essay WHERE person_id = (OLD).id) THEN
          DELETE FROM essay WHERE que_id='(OLD).id';
       END IF;
    END IF;
    RETURN NULL;
    END;
    $delete_question$ LANGUAGE plpgsql;

    CREATE TRIGGER delete_question
    BEFORE DELETE ON question
        FOR EACH ROW EXECUTE PROCEDURE delete_question();

当我从question删除数据时,该行会消失一段时间。但是当我刷新时,它仍然在那里 我试图放RETURN OLD;但由于约束关系而失败了。 这有什么问题?

2 个答案:

答案 0 :(得分:2)

关于触发功能的更多建议:

CREATE OR REPLACE FUNCTION delete_question()
  RETURNS trigger AS
$func$
BEGIN

CASE OLD.que_type
WHEN 1 THEN
    DELETE FROM mcq   WHERE que_id=OLD.id;
WHEN 2, 3 THEN
    DELETE FROM tffb  WHERE que_id=OLD.id;
WHEN 4 THEN
    DELETE FROM essay WHERE que_id=OLD.id;
-- ELSE
--      Do something?
END CASE;

RETURN OLD;

END
$func$ LANGUAGE plpgsql;

重点

  • 使用SELECT语句检查是否存在会使费用增加一倍。只需运行DELETE,如果找不到匹配的行,则不删除任何内容。

  • 在此处使用CASE声明。更短,更快。请注意,plpgsql CASE与SQL CASE语句略有不同。例如,您可以一次列出几个案例。

  • 除非您实际声明变量,否则不需要DECLARE关键字。

替代设计

您可以cascading deletes via foreign key完全避免问题,@a_horse mentioned in the comment。我的架构布局如下所示:

CREATE TABLE question (
   question_id serial NOT NULL PRIMARY KEY
  ,que_type    int   -- this may be redundant as well
);

CREATE TABLE essay (
   que_id int NOT NULL PRIMARY KEY
              REFERNECES question(question_id) ON UPDATE CASCADE
                                               ON DELETE CASCADE
  ,ans    text
);

...

关于serial
Auto increment SQL function

答案 1 :(得分:1)

然后我再尝试解决它......它的工作完美无缺。 YEAY。

CREATE OR REPLACE FUNCTION delete_question()
RETURNS trigger AS $delete_question$
DECLARE
BEGIN
IF ( OLD.que_type=1 ) THEN
   IF EXISTS (SELECT 1 FROM mcq WHERE que_id=OLD.id) THEN
      DELETE FROM mcq WHERE que_id=OLD.id;
   END IF;
ELSIF ( OLD.que_type=2 OR OLD.que_type=3) THEN
   IF EXISTS (SELECT 1 FROM tffb WHERE que_id=OLD.id) THEN
      DELETE FROM tffb WHERE que_id=OLD.id;
   END IF;
ELSIF ( OLD.que_type=4 ) THEN
   IF EXISTS (SELECT 1 FROM essay WHERE que_id=OLD.id) THEN
      DELETE FROM essay WHERE que_id=OLD.id;
   END IF;
END IF;
RETURN OLD;
END;
$delete_question$ LANGUAGE plpgsql;

CREATE TRIGGER delete_question
BEFORE DELETE ON question
    FOR EACH ROW EXECUTE PROCEDURE delete_question();

' '甚至OLD.id上没有(OLD).id并使用RETURN OLD;