3

私は、O'Reilly から出版された「Learning MySQL」の本に取り組んでおり、本の Web サイトに掲載されている次の SQL コードを入手しようとしています。

DROP DATABASE IF EXISTS music;
CREATE DATABASE music;
USE music;

CREATE TABLE artist (
    artist_id SMALLINT(5) NOT NULL DEFAULT 0,
    artist_name CHAR(128) DEFAULT NULL,
    PRIMARY KEY  (artist_id)
);

CREATE TABLE album (
    artist_id SMALLINT(5) NOT NULL DEFAULT 0,
    album_id SMALLINT(4) NOT NULL DEFAULT 0,
    album_name CHAR(128) DEFAULT NULL,
    PRIMARY KEY  (artist_id,album_id),
    FOREIGN KEY (artist_id) REFERENCES artist(artist_id)
);

CREATE TABLE track (
    track_id SMALLINT(3) NOT NULL DEFAULT 0,
    track_name CHAR(128) DEFAULT NULL,
    artist_id SMALLINT(5) NOT NULL DEFAULT 0,
    album_id SMALLINT(4) NOT NULL DEFAULT 0,
    time DECIMAL(5,2) DEFAULT NULL,
    PRIMARY KEY  (artist_id,album_id,track_id),
    FOREIGN KEY (artist_id) REFERENCES artist(artist_id),
    FOREIGN KEY (album_id) REFERENCES album(album_id)
);

CREATE TABLE played (
    artist_id SMALLINT(5) NOT NULL DEFAULT 0,
    album_id SMALLINT(4) NOT NULL DEFAULT 0,
    track_id SMALLINT(3) NOT NULL DEFAULT 0,
    played TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
    PRIMARY KEY  (artist_id,album_id,track_id,played),
    FOREIGN KEY (artist_id) REFERENCES artist(artist_id),
    FOREIGN KEY (album_id) REFERENCES album(album_id),
    FOREIGN KEY (track_id) REFERENCES track(track_id)
);

-- And the whole bunch of data input into those tables. 
INSERT INTO played VALUES (1, 3, 0, "20060814102103");
INSERT INTO artist VALUES (1, "New Order");
INSERT INTO album VALUES (2, 1, "Let Love In");
INSERT INTO track VALUES (0,'Do You Love Me?',2,1,'5.95');

ただし、SOURCEMySQLを試してみるERROR 1215 (HY000): Cannot add foreign key constraint と、ERROR 1146 (42s02): Table 'music.track' doesn't exist. 私はしばらくこれについて熟考してきました。何が間違っているようですか?

4

2 に答える 2

1

コードが失敗する理由は、albumandtrackテーブルに複合主キーがあるためです。外部キーを正常に作成できるようにするには、複合キーの列ごとに各テーブルに別のインデックスを追加する必要があります。

次のように、各テーブルのコードを変更してインデックスを追加してみてください。albumテーブルの上:

INDEX (album_id),

trackテーブルの上:

INDEX (track_id),

したがって、完全なコードは次のようになります (データベースの作成と挿入を除く)。

CREATE TABLE artist (
    artist_id SMALLINT(5) NOT NULL DEFAULT 0,
    artist_name CHAR(128) DEFAULT NULL,
    PRIMARY KEY  (artist_id)
);

CREATE TABLE album (
    artist_id SMALLINT(5) NOT NULL DEFAULT 0,
    album_id SMALLINT(4) NOT NULL DEFAULT 0,
    album_name CHAR(128) DEFAULT NULL,
    PRIMARY KEY  (artist_id,album_id),
    INDEX (album_id),
    FOREIGN KEY (artist_id) REFERENCES artist(artist_id)
);

CREATE TABLE track (
    track_id SMALLINT(3) NOT NULL DEFAULT 0,
    track_name CHAR(128) DEFAULT NULL,
    artist_id SMALLINT(5) NOT NULL DEFAULT 0,
    album_id SMALLINT(4) NOT NULL DEFAULT 0,
    time DECIMAL(5,2) DEFAULT NULL,
    PRIMARY KEY  (artist_id,album_id,track_id),
    INDEX (track_id),
    FOREIGN KEY (artist_id) REFERENCES artist(artist_id),
    FOREIGN KEY (album_id) REFERENCES album(album_id)
);

CREATE TABLE played (
    artist_id SMALLINT(5) NOT NULL DEFAULT 0,
    album_id SMALLINT(4) NOT NULL DEFAULT 0,
    track_id SMALLINT(3) NOT NULL DEFAULT 0,
    played TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
    PRIMARY KEY  (artist_id,album_id,track_id,played),
    FOREIGN KEY (artist_id) REFERENCES artist(artist_id),
    FOREIGN KEY (album_id) REFERENCES album(album_id),
    FOREIGN KEY (track_id) REFERENCES track(track_id)
);
于 2013-04-04T19:37:36.260 に答える
1

外部キーは、候補キー全体を参照する必要があります。

CREATE TABLE track (
    track_id SMALLINT(3) NOT NULL DEFAULT 0,
    track_name CHAR(128) DEFAULT NULL,
    artist_id SMALLINT(5) NOT NULL DEFAULT 0,
    album_id SMALLINT(4) NOT NULL DEFAULT 0,
    time DECIMAL(5,2) DEFAULT NULL,
    PRIMARY KEY  (artist_id,album_id,track_id),
    FOREIGN KEY (artist_id) REFERENCES artist(artist_id),
    /* This won't work, not referencing an entire key: */
    /*FOREIGN KEY (album_id) REFERENCES album(album_id)*/
    /* This should work: */
    FOREIGN KEY (artist_id,album_id) REFERENCES album(artist_id,album_id)
);

プレイされたテーブルで同様の変更を行う必要があります。

これらの変更の SqlFiddleは、キーの既存の値を使用して正しい順序でデータを挿入することを含みます。

album_idそれが独自の候補キーである場合(一意である場合)、それを主キーにするという考えもありalbumます。artist_idで列を作成する必要はありませtrackん。これは、他の子テーブル ( ) に対しても実行できます。artisttrackalbumplayed

もちろん、track_idan の序数として使用している場合album(一意ではなく、albumおそらくすべてに a track_id= 1 があります)、複合キーに固執するか、他の一意の制約で代理キーを作成する必要があります。

最初の挿入でしか機能しないことを考えると、主キーにデフォルトを設定することも不可解です。

于 2013-04-04T19:37:40.040 に答える