2

私はこのようなデータベーススキームを持っています。

create table Photographer(
id int primary key references Person(id) on update cascade on delete cascade,
livesIn int not null references Location(id) on update cascade on delete no action
);
create table Specialty(
photographer int references Photographer(id) on update cascade on delete cascade,
type enum('portrait','landscape','sport'),
primary key(photographer, type)
);
create table Photo(
id int primary key,
takenAt timestamp not null,
takenBy int references Photographer(id) on update cascade on delete no action,
photographedAt int references Location(id) on update cascade on delete no action,
type enum('portrait','landscape','sport')
);

写真家が写真家の専門分野の1つとしてtを持っている場合、写真家がタイプtの写真を撮る資格があるように、データベースを制約する必要があります。

私の試みはうまくいきませんでした。

/*Attempt 1*/
ALTER TABLE Photo ADD CONSTRAINT constraint_1      
CHECK (Photo.type in (SELECT Specialty.type FROM Specialty,Photo,Photographer 
WHERE Photo.takenBy = Photographer.id 
AND Photographer.id = Specialty.photographer 
AND Specialty.type = Photo.type));
/*Attempt 2 using exists instead of 'in'*/
ALTER TABLE Photo ADD CONSTRAINT constraint_1      
CHECK (exists (SELECT * FROM Specialty,Photo,Photographer 
WHERE Photo.takenBy = Photographer.id 
AND Photographer.id = Specialty.photographer 
AND Specialty.type = Photo.type));

私がここで間違っていることは特にありますか?

4

1 に答える 1

1

ALTER TABLE構文で説明されているように:

句は解析されますが、CHECKすべてのストレージエンジンで無視されます。13.1.17項「<code>CREATETABLE構文」</a>を参照してください。構文句を受け入れるが無視する理由は、互換性、他のSQLサーバーからのコードの移植を容易にするため、および参照を使用してテーブルを作成するアプリケーションを実行するためです。セクション1.8.5「MySQLと標準SQLの違い」</a>を参照してください。

いくつかのオプションがあります。

  1. FOREIGN KEY制約を使用します。これにより、すべてのテーブルでInnoDBストレージエンジンを使用する必要があります。

    ALTER TABLE Specialty
      ADD FOREIGN KEY (photographer) REFERENCES Photographer (id);
    
    ALTER TABLE Photo
      ADD FOREIGN KEY (takenBy, type) REFERENCES Specialty (photographer, type);
    
  2. トリガーを使用する:

    CREATE TRIGGER foo1 BEFORE INSERT ON Photo FOR EACH ROW
    IF NOT EXISTS (
      SELECT *
      FROM   Specialty s JOIN Photographer p ON s.photographer = p.id
      WHERE  p.id = NEW.takenBy AND s.type = NEW.type
    ) THEN CALL raise.error;
    
    CREATE TRIGGER foo2 BEFORE UPDATE ON Photo FOR EACH ROW
    IF NOT EXISTS (
      SELECT *
      FROM   Specialty s JOIN Photographer p ON s.photographer = p.id
      WHERE  p.id = NEW.takenBy AND s.type = NEW.type
    ) THEN CALL raise.error;
    
于 2012-10-21T07:11:16.157 に答える