0

私は3つのテーブルを持っています:

住所

CREATE  TABLE IF NOT EXISTS `main`.`address` (  
  `id` BIGINT NOT NULL AUTO_INCREMENT ,  
  `street_number` VARCHAR(5) NOT NULL ,  
  `street_name` VARCHAR(255) NOT NULL ,  
  `town_village` VARCHAR(50) NOT NULL ,  
  `county` VARCHAR(50) NOT NULL ,  
  `country` VARCHAR(45) NOT NULL ,  
  `postcode` VARCHAR(10) NOT NULL ,  
  PRIMARY KEY (`id`) ,  
  UNIQUE INDEX `street_number_UNIQUE` (`street_number` ASC, `street_name` ASC, `town_village` ASC,   `county` ASC, `country` ASC, `postcode` ASC) )  
ENGINE = InnoDB  

**Geolocation**  
CREATE  TABLE IF NOT EXISTS `warrington_main`.`address` (  
  `id` BIGINT NOT NULL AUTO_INCREMENT ,  
  `street_number` VARCHAR(5) NOT NULL ,  
  `street_name` VARCHAR(255) NOT NULL ,  
  `town_village` VARCHAR(50) NOT NULL ,  
  `county` VARCHAR(50) NOT NULL ,  
  `country` VARCHAR(45) NOT NULL ,  
  `postcode` VARCHAR(10) NOT NULL ,  
  PRIMARY KEY (`id`) ,  
  UNIQUE INDEX `street_number_UNIQUE` (`street_number` ASC, `street_name` ASC, `town_village` ASC,   `county` ASC, `country` ASC, `postcode` ASC) )  
ENGINE = InnoDB

**Image**  
CREATE  TABLE IF NOT EXISTS `warrington_main`.`image` (  
  `id` MEDIUMINT(8) UNSIGNED NOT NULL AUTO_INCREMENT ,  
  `alias_title` VARCHAR(255) NOT NULL ,  
  `title` VARCHAR(100) NOT NULL ,  
  `description` VARCHAR(2000) NOT NULL ,  
  `main_image` VARCHAR(50) NOT NULL ,  
  `thumbnail_image` VARCHAR(50) NOT NULL ,  
  `thumbnail_image_medium` VARCHAR(50) NOT NULL ,  
  `thumbnail_image_small` VARCHAR(50) NOT NULL ,  
  `thumbnail_image_gallery` VARCHAR(50) NOT NULL ,    
  `hits` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0' ,  
  `show_comment` ENUM('0','1') NOT NULL ,  
  `section` TINYINT(2) UNSIGNED NOT NULL ,  
  `flickr_youtube_id` VARCHAR(20) NOT NULL ,  
  `feature_in_gallery` ENUM('0','1') NOT NULL ,  
  `created_on` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' ,  
  `date_taken` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' ,  
  `updated_on` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' ,  
  `updated_by` MEDIUMINT(8) UNSIGNED NOT NULL ,  
  `approved` ENUM('Inprocess','Yes','No') NOT NULL DEFAULT 'Inprocess' ,  
  `visible` ENUM('0','1') NOT NULL DEFAULT '0' ,  
  PRIMARY KEY (`id`) ,  
  UNIQUE INDEX `alias_title` (`alias_title` ASC) ,  
  UNIQUE INDEX `flickr_youtube_id`   (`flickr_youtube_id` ASC) ,  
  INDEX `title` (`title` ASC) ,  
  INDEX `approved` (`approved` ASC) ,  
  INDEX `visible` (`visible` ASC) ,  
  INDEX `feature_in_gallery` (`feature_in_gallery` ASC) )  
ENGINE = InnoDB  
AUTO_INCREMENT = 23162  
DEFAULT CHARACTER SET = utf8  

これで、各画像に地理位置情報と住所を含めることができます。location という別のテーブルを作成するつもりでした。

地理位置情報と住所のオプションの関係を使用して場所を作成するつもりでした。つまり、場所は地理位置情報または住所、またはその両方である可能性があります。ただし、null/null を保存したくありません。最初の質問は、このインスタンスで 2 つのオプションの関係を持つテーブルを作成し、null/null を取得しないようにする方法です。

次に、ロケーション テーブルをイメージ テーブルに関連付ける必要があります。将来、場所または住所/またはジオコードに対して別のテーブル、つまりイベントに対してクエリを実行したい場合があります。

そのため、イベントには、画像テーブルに格納されている場所と同じ場所がある場合があります。これが最良の構造であるかどうか誰かが知っていますか。画像テーブル/住所/地理位置情報、そして場所と画像テーブル。

言い換えれば、地理位置情報と住所に対する 2 つのオプションの関係で構成されるテーブルがあります。ただし、両方がnullではなく、どちらかがテーブルに含まれる必要があります。この制約を強制するにはどうすればよいですか

4

2 に答える 2

0

これを構成する方法は2つあります。どちらの画像にも、アドレスとジオロケーションへの外部キーがあります。または、画像に新しいロケーションテーブルの外部キーのみを含めることもできます。このテーブルには、アドレスとジオロケーションに対する外部キーの関係があります。どちらを実行するかは、将来的に他の種類のロケーションタイプを使用する予定があるかどうかによって異なります。別の場所に配置したいジオロケーションと住所の他の一般的なプロパティがない限り、または前述のように将来別の場所タイプになると思われる場合を除いて、私は個人的に最初のものを選びます。

いずれの場合も、アドレスとジオロケーションの外部キーが含まれているフィールドは、両方のフィールドにまたがる一意のインデックスを持つこともできます。これにより、(ほとんどの場合)フィールドにNULL値を保持できるようになり、そのテーブルに最大で1つのNULL-NULLレコードを持つことができるという点で、望ましい関係が強制されます。

それか、住所とジオロケーションテーブルを非正規化し、両方のテーブルのデータ構造が同じであるように見えるため、どちらのタイプ(住所、ジオロケーション、またはその両方)であるかを示す列タイプを追加するだけで、関係を厳密に適用できます。次に、イメージ内のこのテーブルへの外部キーをnullにしないようにし、innodbを使用する場合は、オプションで参照整合性を適用します。もちろん、これにより、実際の住所が1つに制限されます(つまり、異なる住所と地理的位置の住所ではありません)。

于 2012-09-04T21:29:04.953 に答える
0

ロケーションテーブルの行に少なくとも1つのロケーションフィールドがnullでないことを確認したい場合はON INSERT、対応するON UPDATEトリガーを作成してこれを確認することをお勧めします。

秘訣は、トリガーがフィールドをNEW挿入不可能な応答に変更するようにすることです。値を更新できないため、INSERTまたはをUPDATE失敗させます。1つの可能性は、重複キーエラーを強制することであり、もう1つは、無効な値を強制することです。何かのようなもの

CREATE TRIGGER needs_some BEFORE UPDATE ON location
FOR EACH ROW
BEGIN
     IF (NEW.Geolocation IS NULL AND NEW.Address IS NULL) THEN
         SET NEW.Geolocation = 'ABC';
     END IF;
END;

location.Geolocationが数値タイプであると仮定すると、これは挿入に失敗します。

MySQL 5.5以降では、単純に

CREATE TRIGGER needs_some BEFORE UPDATE ON location
FOR EACH ROW
BEGIN
     IF (NEW.Geolocation IS NULL AND NEW.Address IS NULL) THEN
         SIGNAL SQLSTATE '99999' SET MESSAGE_TEXT='Must not be a double NULL';
     END IF;
END;

または以前のMySQLバージョン

CREATE TRIGGER needs_some BEFORE UPDATE ON location
FOR EACH ROW
BEGIN
     IF (NEW.Geolocation IS NULL AND NEW.Address IS NULL) THEN
         CALL inexistant_stored_procedure;
     END IF;
END;

回避策として。

于 2012-09-04T21:32:51.953 に答える