I have a Database structure in which a menu option may point to a page or not:
menu( 'en', 'anypage') => page( 'en', 'anypage')
menu( 'en', NULL) => Nothing
The bottom MySQL code work correctly for creation and update, but not for deletion: I would like when a page is deleted, menu.Link is set to NULL and menu.Language stay unchanged.
FOREIGN KEY (Language, Link) REFERENCES page(Language, Link)
ON UPDATE CASCADE ON DELETE SET Link=NULL
But that of course does not work.
So my question is: How to update just the menu.Link to NULL on page deletion?
-- 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, final solution based on @Bohemian answer:
/* 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 ;