我做了一个相当大的函数,有很多选择/更新来用数据填充所有表。刚刚尝试填写表格,但在调用函数时收到 #1452 错误
SELECT insert_tune("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S")
错误的样子
#1452 - Cannot add or update a child row: a foreign key constraint fails (`rbase`.`tunes`, CONSTRAINT `tunes_ibfk_1` FOREIGN KEY (`riddim_fk`) REFERENCES `riddims` (`riddim_id`) ON DELETE SET NULL ON UPDATE CASCADE)
数据库布局如下所示:
CREATE TABLE artists (
artist_id INT AUTO_INCREMENT PRIMARY KEY,
artist_name varchar(100) UNIQUE,
artist_aka varchar(255) UNIQUE
) ENGINE = 'InnoDB';
CREATE TABLE labels (
label_id SMALLINT AUTO_INCREMENT PRIMARY KEY,
label_name varchar(100) UNIQUE,
label_aka varchar(255) UNIQUE
) ENGINE = 'InnoDB';
CREATE TABLE producers (
producer_id SMALLINT AUTO_INCREMENT PRIMARY KEY,
producer_forename varchar(100),
producer_nickname varchar(100) UNIQUE,
producer_lastname varchar(100)
) ENGINE = 'InnoDB';
CREATE TABLE years (
year_id TINYINT AUTO_INCREMENT PRIMARY KEY,
year_value varchar(4) UNIQUE
) ENGINE = 'InnoDB';
CREATE TABLE genres (
genre_id TINYINT AUTO_INCREMENT PRIMARY KEY,
genre_name varchar(10) UNIQUE
) ENGINE = 'InnoDB';
CREATE TABLE flags (
flag_id TINYINT AUTO_INCREMENT PRIMARY KEY,
flag_name varchar(12) UNIQUE
) ENGINE = 'InnoDB';
CREATE TABLE tags (
tag_id SMALLINT AUTO_INCREMENT PRIMARY KEY,
tag_name varchar(16) UNIQUE
) ENGINE = 'InnoDB';
CREATE TABLE sources (
source_id TINYINT AUTO_INCREMENT PRIMARY KEY,
source_name varchar(30) UNIQUE
) ENGINE = 'InnoDB';
CREATE TABLE riddims (
riddim_id INT AUTO_INCREMENT PRIMARY KEY,
riddim_name varchar(40) UNIQUE,
riddim_aka varchar(255) UNIQUE,
genre_fk TINYINT,
youtube varchar(11) UNIQUE,
image varchar(11) UNIQUE,
FOREIGN KEY (genre_fk) REFERENCES genres(genre_id) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE = 'InnoDB';
CREATE TABLE tunes (
tune_id INT AUTO_INCREMENT PRIMARY KEY,
riddim_fk INT DEFAULT NULL,
artist_fk INT DEFAULT NULL,
tune_name varchar(60) DEFAULT NULL,
tune_aka varchar(255) DEFAULT NULL,
label_fk SMALLINT DEFAULT NULL,
producer_fk SMALLINT DEFAULT NULL,
year_fk TINYINT DEFAULT NULL,
lyrics TEXT DEFAULT NULL,
flag_fk TINYINT,
tag_fk SMALLINT,
source_fk TINYINT,
last_modified TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (riddim_fk) REFERENCES riddims(riddim_id) ON DELETE SET NULL ON UPDATE CASCADE,
FOREIGN KEY (artist_fk) REFERENCES artists(artist_id) ON DELETE SET NULL ON UPDATE CASCADE,
FOREIGN KEY (producer_fk) REFERENCES producers(producer_id) ON DELETE SET NULL ON UPDATE CASCADE,
FOREIGN KEY (year_fk) REFERENCES years(year_id) ON DELETE SET NULL ON UPDATE CASCADE,
FOREIGN KEY (flag_fk) REFERENCES flags(flag_id) ON DELETE SET NULL ON UPDATE CASCADE,
FOREIGN KEY (tag_fk) REFERENCES tags(tag_id) ON DELETE SET NULL ON UPDATE CASCADE,
FOREIGN KEY (source_fk) REFERENCES sources(source_id) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE = 'InnoDB';
我用来填充表格的函数看起来像
CREATE FUNCTION insert_tune(
riddim varchar(40),
riddim_a varchar(255),
yt varchar(11),
img varchar(11),
artist varchar(100),
artist_a varchar(255),
tune varchar(60),
tune_a varchar(255),
genre varchar(10),
label varchar(100),
label_a varchar(255),
producer_fn varchar(100),
producer_nn varchar(100),
producer_ln varchar(100),
year varchar(4),
lrx TEXT,
flag varchar(12),
tag varchar(16),
source varchar(30)
)
RETURNS INT
DETERMINISTIC
BEGIN
DECLARE cRiddim, cArtist, cLabel, cProducer, cRiddimArtist, cRiddimTune, cArtistTune, cRiddimArtistTune INT;
/* Testing if the tables already contain certain records/entries */
SELECT COUNT(*) FROM riddims WHERE riddim_name = riddim INTO cRiddim;
SELECT COUNT(*) FROM artists WHERE artist_name = artist INTO cArtist;
SELECT COUNT(*) FROM labels WHERE label_name = label INTO cLabel;
SELECT COUNT(*) FROM producers WHERE producer_nickname = producer_nn INTO cProducer;
SELECT COUNT(*) FROM tunes WHERE artist_fk = (SELECT artist_id FROM artists WHERE artist_name = artist) AND tune_name = tune AND ISNULL(riddim_fk) INTO cArtistTune;
SELECT COUNT(*) FROM tunes WHERE riddim_fk = (SELECT riddim_id FROM riddims WHERE riddim_name = riddim) AND tune_name = tune AND ISNULL(artist_fk) INTO cRiddimTune;
SELECT COUNT(*) FROM tunes WHERE riddim_fk = (SELECT riddim_id FROM riddims WHERE riddim_name = riddim) AND artist_fk = (SELECT artist_id FROM artists WHERE artist_name = artist) AND ISNULL(tune_name) INTO cRiddimArtist;
SELECT COUNT(*) FROM tunes WHERE riddim_fk = (SELECT riddim_id FROM riddims WHERE riddim_name = riddim) AND artist_fk = (SELECT artist_id FROM artists WHERE artist_name = artist) AND tune_name = tune INTO cRiddimArtistTune;
/*
##########
# GENRES #
##########
*/
IF genre NOT IN ('') AND NOT ISNULL(genre) THEN
INSERT IGNORE INTO genres (genre_name) VALUES (genre);
END IF;
/*
###########
# RIDDIMS #
###########
*/
IF cRiddim < 1 AND riddim NOT IN ('') AND NOT ISNULL(riddim) THEN
INSERT INTO riddims (
riddim_name,
riddim_aka,
youtube,
image
)
VALUES (
riddim,
IF(riddim_a NOT IN (''), riddim_a, NULL),
IF(yt NOT IN (''), yt, NULL),
IF(img NOT IN (''), img, NULL)
);
ELSE
UPDATE riddims SET
riddim_aka = IFNULL(riddim_aka, IF(NOT ISNULL(riddim_a) AND riddim_a NOT IN (''), riddim_a, NULL)),
genre_fk = IFNULL(genre_fk, IF(NOT ISNULL(genre) AND genre NOT IN (''), (SELECT genre_id FROM genres WHERE genre_name = genre), NULL)),
youtube = IFNULL(youtube, IF(NOT ISNULL(youtube) AND youtube NOT IN (''), youtube, NULL)),
image = IFNULL(img, IF(NOT ISNULL(img) AND img NOT IN (''), img, NULL))
WHERE
riddim_name = riddim;
END IF;
/*
###########
# ARTISTS #
###########
*/
IF cArtist < 1 AND artist NOT IN ('') AND NOT ISNULL(artist) THEN
INSERT INTO artists (
artist_name,
artist_aka
)
VALUES (
artist,
IF(artist_a NOT IN (''), artist_a, NULL)
);
ELSE
UPDATE artists SET
artist_aka = IFNULL(artist_aka, IF(NOT ISNULL(artist_a) AND artist_a NOT IN (''), artist_a, NULL))
WHERE
artist_name = artist;
END IF;
/*
##########
# LABELS #
##########
*/
IF cLabel < 1 AND label NOT IN ('') AND NOT ISNULL(label) THEN
INSERT INTO labels (
label_name,
label_aka
)
VALUES (
label,
IF(label_a NOT IN (''), label_a, NULL)
);
ELSE
UPDATE labels SET
label_aka = IFNULL(label_aka, IF(NOT ISNULL(label_a) AND label_a NOT IN (''), label_a, NULL))
WHERE label_name = label;
END IF;
/*
#############
# PRODUCERS #
#############
*/
IF cProducer < 1 AND producer_nn NOT IN ('') AND NOT ISNULL(producer_nn) THEN
INSERT INTO producers (
producer_forename,
producer_nickname,
producer_lastname
)
VALUES (
IF(producer_fn NOT IN (''), producer_fn, NULL),
producer_nn,
IF(producer_ln NOT IN (''), producer_ln, NULL)
);
ELSE
UPDATE producers SET
producer_forename = IFNULL(producer_forename, IF(NOT ISNULL(producer_fn) AND producer_fn NOT IN (''), producer_fn, NULL)),
producer_lastname = IFNULL(producer_lastname, IF(NOT ISNULL(producer_ln) AND producer_ln NOT IN (''), producer_ln, NULL))
WHERE
producer_nickname = producer_nn;
END IF;
/*
#########
# YEARS #
#########
*/
IF year NOT IN ('') AND NOT ISNULL(year) THEN
INSERT IGNORE INTO years (year_value) VALUES (year);
END IF;
/*
#########
# FLAGS #
#########
*/
IF flag NOT IN ('') AND NOT ISNULL(flag) THEN
INSERT IGNORE INTO flags (flag_name) VALUES (flag);
END IF;
/*
########
# TAGS #
########
*/
IF tag NOT IN ('') AND NOT ISNULL(tag) THEN
INSERT IGNORE INTO tags (tag_name) VALUES (tag);
END IF;
/*
###########
# SOURCES #
###########
*/
IF source NOT IN ('') AND NOT ISNULL(source) THEN
INSERT IGNORE INTO sources (source_name) VALUES (source);
END IF;
/*
#########
# TUNES #
#########
*/
IF cArtistTune > 0 THEN
UPDATE tunes SET
riddim_fk = IFNULL(riddim_fk, IF(NOT ISNULL(riddim) AND riddim NOT IN (''), (SELECT riddim_id FROM riddims WHERE riddim_name = riddim), NULL)),
tune_aka = IFNULL(tune_aka, IF(NOT ISNULL(tune_a) AND tune_a NOT IN (''), tune_a, NULL)),
label_fk = IFNULL(label_fk, IF(NOT ISNULL(label) AND label NOT IN (''), (SELECT label_id FROM labels WHERE label_name = label), NULL)),
producer_fk = IFNULL(producer_fk, IF(NOT ISNULL(producer_nn) AND producer_nn NOT IN (''), (SELECT producer_id FROM producers WHERE producer_nickname = producer_nn), NULL)),
year_fk = IFNULL(year_fk, IF(NOT ISNULL(year) AND year NOT IN (''), (SELECT year_id FROM years WHERE year_value = year), NULL)),
lyrics = IFNULL(lyrics, IF(NOT ISNULL(lrx) AND lrx NOT IN (''), lrx, NULL)),
flag_fk = IFNULL(flag_fk, IF(NOT ISNULL(flag) AND flag NOT IN (''), (SELECT flag_id FROM flags WHERE flag_name = flag), NULL)),
tag_fk = IFNULL(tag_fk, IF(NOT ISNULL(tag) AND tag NOT IN (''), (SELECT tag_id FROM tags WHERE tag_name = tag), NULL)),
source_fk = IFNULL(source_fk, IF(NOT ISNULL(source) AND source NOT IN (''), (SELECT source_id FROM sources WHERE source_name = source), NULL))
WHERE
tune_name = tune AND artist_fk = (SELECT artist_id FROM artists WHERE artist_name = artist);
ELSEIF cRiddimTune > 0 THEN
UPDATE tunes SET
artist_fk = IFNULL(artist_fk, IF(NOT ISNULL(artist) AND artist NOT IN (''), (SELECT artist_id FROM artists WHERE artist_name = artist), NULL)),
tune_aka = IFNULL(tune_aka, IF(NOT ISNULL(tune_a) AND tune_a NOT IN (''), tune_a, NULL)),
label_fk = IFNULL(label_fk, IF(NOT ISNULL(label) AND label NOT IN (''), (SELECT label_id FROM labels WHERE label_name = label), NULL)),
producer_fk = IFNULL(producer_fk, IF(NOT ISNULL(producer_nn) AND producer_nn NOT IN (''), (SELECT producer_id FROM producers WHERE producer_nickname = producer_nn), NULL)),
year_fk = IFNULL(year_fk, IF(NOT ISNULL(year) AND year NOT IN (''), (SELECT year_id FROM years WHERE year_value = year), NULL)),
lyrics = IFNULL(lyrics, IF(NOT ISNULL(lrx) AND lrx NOT IN (''), lrx, NULL)),
flag_fk = IFNULL(flag_fk, IF(NOT ISNULL(flag) AND flag NOT IN (''), (SELECT flag_id FROM flags WHERE flag_name = flag), NULL)),
tag_fk = IFNULL(tag_fk, IF(NOT ISNULL(tag) AND tag NOT IN (''), (SELECT tag_id FROM tags WHERE tag_name = tag), NULL)),
source_fk = IFNULL(source_fk, IF(NOT ISNULL(source) AND source NOT IN (''), (SELECT source_id FROM sources WHERE source_name = source), NULL))
WHERE
tune_name = tune AND riddim_fk = (SELECT riddim_id FROM riddims WHERE riddim_name = riddim);
ELSEIF cRiddimArtist > 0 THEN
UPDATE tunes SET
tune_name = IFNULL(tune_name, IF(NOT ISNULL(tune) AND tune NOT IN (''), tune, NULL)),
tune_aka = IFNULL(tune_aka, IF(NOT ISNULL(tune_a) AND tune_a NOT IN (''), tune_a, NULL)),
label_fk = IFNULL(label_fk, IF(NOT ISNULL(label) AND label NOT IN (''), (SELECT label_id FROM labels WHERE label_name = label), NULL)),
producer_fk = IFNULL(producer_fk, IF(NOT ISNULL(producer_nn) AND producer_nn NOT IN (''), (SELECT producer_id FROM producers WHERE producer_nickname = producer_nn), NULL)),
year_fk = IFNULL(year_fk, IF(NOT ISNULL(year) AND year NOT IN (''), (SELECT year_id FROM years WHERE year_value = year), NULL)),
lyrics = IFNULL(lyrics, IF(NOT ISNULL(lrx) AND lrx NOT IN (''), lrx, NULL)),
flag_fk = IFNULL(flag_fk, IF(NOT ISNULL(flag) AND flag NOT IN (''), (SELECT flag_id FROM flags WHERE flag_name = flag), NULL)),
tag_fk = IFNULL(tag_fk, IF(NOT ISNULL(tag) AND tag NOT IN (''), (SELECT tag_id FROM tags WHERE tag_name = tag), NULL)),
source_fk = IFNULL(source_fk, IF(NOT ISNULL(source) AND source NOT IN (''), (SELECT source_id FROM sources WHERE source_name = source), NULL))
WHERE
artist_fk = (SELECT artist_id FROM artists WHERE artist_name = artist) AND riddim_fk = (SELECT riddim_id FROM riddims WHERE riddim_name = riddim);
ELSEIF cRiddimArtistTune < 1 THEN
IF tune NOT IN ('') AND NOT ISNULL(tune) AND artist NOT IN ('') AND NOT ISNULL(artist) THEN
INSERT INTO tunes (
riddim_fk,
artist_fk,
tune_name,
tune_aka,
label_fk,
producer_fk,
year_fk,
lyrics,
flag_fk,
tag_fk,
source_fk
)
VALUES (
IF(NOT ISNULL(riddim) AND riddim NOT IN (''), riddim, NULL),
(SELECT artist_id FROM artists WHERE artist_name = artist),
tune,
IF(NOT ISNULL(tune_a) AND tune_a NOT IN (''), tune_a, NULL),
IF(NOT ISNULL(label) AND label NOT IN (''), (SELECT label_id FROM labels WHERE label_name = label), NULL),
IF(NOT ISNULL(producer_nn) AND producer_nn NOT IN (''), (SELECT producer_id FROM producers WHERE producer_nickname = producer_nn), NULL),
IF(NOT ISNULL(year) AND year NOT IN (''), (SELECT year_id FROM years WHERE year_value = year), NULL),
IF(NOT ISNULL(lrx) AND lrx NOT IN (''), lrx, NULL),
IF(NOT ISNULL(flag) AND flag NOT IN (''), (SELECT flag_id FROM flags WHERE flag_name = flag), NULL),
IF(NOT ISNULL(tag) AND tag NOT IN (''), (SELECT tag_id FROM tags WHERE tag_name = tag), NULL),
IF(NOT ISNULL(source) AND source NOT IN (''), (SELECT source_id FROM sources WHERE source_name = source), NULL)
);
END IF;
IF tune NOT IN ('') AND NOT ISNULL(tune) AND riddim NOT IN ('') AND NOT ISNULL(riddim) THEN
INSERT INTO tunes (
riddim_fk,
artist_fk,
tune_name,
tune_aka,
label_fk,
producer_fk,
year_fk,
lyrics,
flag_fk,
tag_fk,
source_fk
)
VALUES (
(SELECT riddim_id FROM riddims WHERE riddim_name = riddim),
IF(NOT ISNULL(artist) AND artist NOT IN (''), (SELECT artist_id FROM artists WHERE artist_name = artist), NULL),
tune,
IF(NOT ISNULL(tune_a) AND tune_a NOT IN (''), tune_a, NULL),
IF(NOT ISNULL(label) AND label NOT IN (''), (SELECT label_id FROM labels WHERE label_name = label), NULL),
IF(NOT ISNULL(producer_nn) AND producer_nn NOT IN (''), (SELECT producer_id FROM producers WHERE producer_nickname = producer_nn), NULL),
IF(NOT ISNULL(year) AND year NOT IN (''), (SELECT year_id FROM years WHERE year_value = year), NULL),
IF(NOT ISNULL(lrx) AND lrx NOT IN (''), lrx, NULL),
IF(NOT ISNULL(flag) AND flag NOT IN (''), (SELECT flag_id FROM flags WHERE flag_name = flag), NULL),
IF(NOT ISNULL(tag) AND tag NOT IN (''), (SELECT tag_id FROM tags WHERE tag_name = tag), NULL),
IF(NOT ISNULL(source) AND source NOT IN (''), (SELECT source_id FROM sources WHERE source_name = source), NULL)
);
END IF;
IF artist NOT IN ('') AND NOT ISNULL(artist) AND riddim NOT IN ('') AND NOT ISNULL(riddim) THEN
INSERT INTO tunes (
riddim_fk,
artist_fk,
tune_name,
tune_aka,
label_fk,
producer_fk,
year_fk,
lyrics,
flag_fk,
tag_fk,
source_fk
)
VALUES (
(SELECT riddim_id FROM riddims WHERE riddim_name = riddim),
(SELECT artist_id FROM artists WHERE artist_name = artist),
IF(NOT ISNULL(tune) AND tune NOT IN (''), tune, NULL),
IF(NOT ISNULL(tune_a) AND tune_a NOT IN (''), tune_a, NULL),
IF(NOT ISNULL(label) AND label NOT IN (''), (SELECT label_id FROM labels WHERE label_name = label), NULL),
IF(NOT ISNULL(producer_nn) AND producer_nn NOT IN (''), (SELECT producer_id FROM producers WHERE producer_nickname = producer_nn), NULL),
IF(NOT ISNULL(year) AND year NOT IN (''), (SELECT year_id FROM years WHERE year_value = year), NULL),
IF(NOT ISNULL(lrx) AND lrx NOT IN (''), lrx, NULL),
IF(NOT ISNULL(flag) AND flag NOT IN (''), (SELECT flag_id FROM flags WHERE flag_name = flag), NULL),
IF(NOT ISNULL(tag) AND tag NOT IN (''), (SELECT tag_id FROM tags WHERE tag_name = tag), NULL),
IF(NOT ISNULL(source) AND source NOT IN (''), (SELECT source_id FROM sources WHERE source_name = source), NULL)
);
END IF;
ELSEIF cRiddimArtistTune > 0 THEN
UPDATE tunes SET
tune_aka = IFNULL(tune_aka, IF(NOT ISNULL(tune_a) AND tune_a NOT IN (''), tune_a, NULL)),
label_fk = IFNULL(label_fk, IF(NOT ISNULL(label) AND label NOT IN (''), (SELECT label_id FROM labels WHERE label_name = label), NULL)),
producer_fk = IFNULL(producer_fk, IF(NOT ISNULL(producer_nn) AND producer_nn NOT IN (''), (SELECT producer_id FROM producers WHERE producer_nickname = producer_nn), NULL)),
year_fk = IFNULL(year_fk, IF(NOT ISNULL(year) AND year NOT IN (''), (SELECT year_id FROM years WHERE year_value = year), NULL)),
lyrics = IFNULL(lyrics, IF(NOT ISNULL(lrx) AND lrx NOT IN (''), lrx, NULL)),
flag_fk = IFNULL(flag_fk, IF(NOT ISNULL(flag) AND flag NOT IN (''), (SELECT flag_id FROM flags WHERE flag_name = flag), NULL)),
tag_fk = IFNULL(tag_fk, IF(NOT ISNULL(tag) AND tag NOT IN (''), (SELECT tag_id FROM tags WHERE tag_name = tag), NULL)),
source_fk = IFNULL(source_fk, IF(NOT ISNULL(source) AND source NOT IN (''), (SELECT source_id FROM sources WHERE source_name = source), NULL))
WHERE
artist_fk = (SELECT artist_id FROM artists WHERE artist_name = artist) AND riddim_fk = (SELECT riddim_id FROM riddims WHERE riddim_name = riddim) AND tune_name = tune;
END IF;
RETURN 0; /** add more/better returns & values to determine what data was inserted **/
END
对于那里的所有数据库向导,请多多包涵,我是这个东西的新手,所以这个功能可能有点臃肿。
无论如何,一些研究表明,当有一个外键列指向父表中不存在的行时,就会发生上述错误。奇怪的是我的桌子都是空的。当外键列 - 错误地 - 指向它自己的表时,也可能发生这种情况 - 但这里也不是这种情况(据我了解我阅读的类似问题)。
很烦人的是,我不允许在函数范围内使用 SELECT CONCAT() (用于调试目的),所以我并没有真正了解错误发生的原因/位置,但我认为它会在处理将数据插入到 tunes.riddim_fk 的函数。
我还将riddim_id、genre_id 等(父表的ID)设置为PRIMARY KEY 和AUTO_INCREMENT,现在phpMyAdmin 向我显示这些列的“NULL:否”,即使我没有指定“NOT NULL”。我假设其中一个键是自动将列设置为 NOT NULL。
可能这会导致错误,因为我将 NULL 添加到 ie。riddim_fk 列,如果函数参数“riddim”设置为“”(空字符串)?我假设不像我的实际函数测试调用(如上)我没有将空字符串作为参数传递给函数。
帮助表示赞赏!
编辑:错别字。