MySQL:当" ON DELETE"时,如何将其中一个参数设置为null?

时间:2014-10-07 07:28:08

标签: mysql

我有一个数据库结构,其中一个菜单选项可能指向一个页面:

menu( 'en', 'anypage') => page( 'en', 'anypage')
menu( 'en', NULL) => Nothing

底层MySQL代码可以正常用于创建和更新,但不能用于删除:我希望在删除页面时,menu.Link设置为NULL并且menu.Language保持不变。

FOREIGN KEY (Language, Link) REFERENCES page(Language, Link) 
    ON UPDATE CASCADE ON DELETE SET Link=NULL

但那当然不起作用。

所以我的问题是:如何在删除页面时将menu.Link更新为NULL?

-- DROP TABLE FOR MULTIPLE TESTS
DROP TABLE IF EXISTS menu;
DROP TABLE IF EXISTS page;
DROP TABLE IF EXISTS language;


-- CREATE TABLES
CREATE TABLE language(
    Id CHAR(2) PRIMARY KEY,
    Name VARCHAR(20)
) ENGINE=innoDB;

CREATE TABLE page(
    Language CHAR(2) NOT NULL,
    Link VARCHAR(30) NOT NULL,
    PRIMARY KEY (Language, Link),
    FOREIGN KEY (Language) REFERENCES language(Id) 
        ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE = InnoDB;

CREATE TABLE menu(
    Id INT PRIMARY KEY AUTO_INCREMENT,
    Language CHAR(2) NOT NULL,
    Link VARCHAR(30) DEFAULT NULL,
    FOREIGN KEY (Language) REFERENCES language(Id) 
        ON UPDATE CASCADE ON DELETE CASCADE
    /*, FOREIGN KEY (Language, Link) REFERENCES page(Language, Link) 
        ON UPDATE CASCADE ON DELETE SET LINK=NULL*/
) ENGINE=InnoDB;


-- INSERT FOR TESTS
INSERT INTO language (Id, Name) VALUES('en','English');
INSERT INTO page (Link, Language)VALUES('test', 'en');
INSERT INTO menu (Language, Link)VALUES('en', 'test');

UPDATE page SET Link='test2' WHERE Link='test';
DELETE FROM page WHERE Link='test2';

EDITED,最终解决方案基于@Bohemian回答:

/* Page deletion*/
DELIMITER //
CREATE TRIGGER PAGE_DELETE
AFTER DELETE ON page
FOR EACH ROW
BEGIN
    UPDATE menu SET
    menu.Link = NULL
    WHERE menu.Link = OLD.Link AND menu.Language = OLD.Language;
END;//

/* Page update*/
CREATE TRIGGER PAGE_UPDATE
AFTER UPDATE ON page
FOR EACH ROW
BEGIN
    UPDATE menu SET
    menu.Link = NEW.Link
    WHERE menu.Link = OLD.Link AND menu.Language = OLD.Language;
END;//

/* Menu creation*/
CREATE TRIGGER MENU_INSERT
BEFORE INSERT ON menu
FOR EACH ROW
BEGIN
    declare rowCount int default 1;
    if (NEW.Link IS NOT NULL) then
        SELECT count(Id) into rowCount FROM page 
        WHERE NEW.Link=page.Link AND NEW.Language=page.Language;
    end if; 

    if (rowCount=0 ) then
        signal sqlstate '23000' set message_text = 'Error: menu.Link must point to an existant page.';
    end if;
END;//

/* Menu update*/
CREATE TRIGGER MENU_UPDATE
BEFORE UPDATE ON menu
FOR EACH ROW
BEGIN
    declare rowCount int default 1;
    if (NEW.Link IS NOT NULL) then
        SELECT count(Id) into rowCount FROM page 
        WHERE NEW.Link=page.Link AND NEW.Language=page.Language;
    end if; 

    if (rowCount=0 ) then
        signal sqlstate '23000' set message_text = 'Error: menu.Link must point to an existant page.';
    end if;
END;//
DELIMITER ;

2 个答案:

答案 0 :(得分:1)

创建一个触发器:

DELIMITER //
CREATE TRIGGER PAGE_DELETE
AFTER DELETE ON PAGE
FOR EACH ROW
BEGIN
    UPDATE MENU SET
    PAGE_ID = NULL
    WHERE PAGE_ID = OLD.ID;
END;//
DELIMITER ;

答案 1 :(得分:0)

以下是我设法做到的方法:

-- DROP TABLE FOR MULTIPLE TESTS
DROP TABLE IF EXISTS menu;
DROP TABLE IF EXISTS page;
DROP TABLE IF EXISTS language;


-- CREATE TABLES
CREATE TABLE language(
    Id CHAR(2) PRIMARY KEY,
    Name VARCHAR(20)
) ENGINE=innoDB;

CREATE TABLE page(
    Language CHAR(2) NOT NULL,
    Link VARCHAR(30) NOT NULL,
    PRIMARY KEY (Language, Link),
    FOREIGN KEY (Language) REFERENCES language(Id) 
        ON UPDATE CASCADE ON DELETE CASCADE,
    KEY page_link (Link)
) ENGINE = InnoDB;

CREATE TABLE menu(
    Id INT PRIMARY KEY AUTO_INCREMENT,
    Language CHAR(2) NOT NULL,
    Link VARCHAR(30) DEFAULT NULL,
    FOREIGN KEY (Language) REFERENCES language(Id) 
        ON UPDATE CASCADE ON DELETE CASCADE,
    FOREIGN KEY (Link) REFERENCES page(Link) 
        ON UPDATE CASCADE ON DELETE SET NULL
) ENGINE=InnoDB;


-- INSERT FOR TESTS
INSERT INTO language (Id, Name) VALUES('en','English');
INSERT INTO page (Link, Language)VALUES('test', 'en');
INSERT INTO menu (Language, Link)VALUES('en', 'test');

UPDATE page SET Link='test2' WHERE Link='test';
DELETE FROM page WHERE Link='test2';
SELECT * FROM menu;