1

データベース テーブルで 2 つの同じタグを使用しないようにする方法を教えてください。ある人は、テーブルで 2 つの秘密鍵を使用すると言いました。ただし、W3Schools の Web サイトによると、それは不可能です。

私のリレーショナル テーブル

代替テキスト http://files.getdropbox.com/u/175564/db/db7.png

私の論理テーブル

代替テキスト http://files.getdropbox.com/u/175564/db/db77.png

テーブルのコンテキスト

代替テキスト http://files.getdropbox.com/u/175564/db/db777.png

質問で重複したタグを使用しないようにするにはどうすればよいですか?

4

5 に答える 5

2

NORMAモデルを更新して、図にさらに一致させました。あなたがいくつかの間違いを犯した場所はわかりますが、それらのいくつかは私の以前のモデルが原因であった可能性があります。

タグの重複を防ぐために、このモデルを更新しました。以前はそれほど重要ではありませんでした。しかし、あなたはそれが欲しいので、ここにあります(Postgres用):

START TRANSACTION ISOLATION LEVEL SERIALIZABLE, READ WRITE;

CREATE SCHEMA so;

SET search_path TO SO,"$user",public;

CREATE DOMAIN so.HashedPassword AS 
    BIGINT CONSTRAINT HashedPassword_Unsigned_Chk CHECK (VALUE >= 0);

CREATE TABLE so."User"
(
    USER_ID SERIAL NOT NULL,
    USER_NAME CHARACTER VARYING(50) NOT NULL,
    EMAIL_ADDRESS CHARACTER VARYING(256) NOT NULL,
    HASHED_PASSWORD so.HashedPassword NOT NULL,
    OPEN_ID CHARACTER VARYING(512),
    A_MODERATOR BOOLEAN,
    LOGGED_IN BOOLEAN,
    HAS_BEEN_SENT_A_MODERATOR_MESSAGE BOOLEAN,
    CONSTRAINT User_PK PRIMARY KEY(USER_ID)
);

CREATE TABLE so.Question
(
    QUESTION_ID SERIAL NOT NULL,
    TITLE CHARACTER VARYING(256) NOT NULL,
    WAS_SENT_AT_TIME TIMESTAMP NOT NULL,
    BODY CHARACTER VARYING NOT NULL,
    USER_ID INTEGER NOT NULL,
    FLAGGED_FOR_MODERATOR_REMOVAL BOOLEAN,
    WAS_LAST_CHECKED_BY_MODERATOR_AT_TIME TIMESTAMP,
    CONSTRAINT Question_PK PRIMARY KEY(QUESTION_ID)
);

CREATE TABLE so.Tag
(
    TAG_ID SERIAL NOT NULL,
    TAG_NAME CHARACTER VARYING(20) NOT NULL,
    CONSTRAINT Tag_PK PRIMARY KEY(TAG_ID),
    CONSTRAINT Tag_UC UNIQUE(TAG_NAME)
);

CREATE TABLE so.QuestionTaggedTag
(
    QUESTION_ID INTEGER NOT NULL,
    TAG_ID INTEGER NOT NULL,
    CONSTRAINT QuestionTaggedTag_PK PRIMARY KEY(QUESTION_ID, TAG_ID)
);

CREATE TABLE so.Answer
(
    ANSWER_ID SERIAL NOT NULL,
    BODY CHARACTER VARYING NOT NULL,
    USER_ID INTEGER NOT NULL,
    QUESTION_ID INTEGER NOT NULL,
    CONSTRAINT Answer_PK PRIMARY KEY(ANSWER_ID)
);

ALTER TABLE so.Question 
    ADD CONSTRAINT Question_FK FOREIGN KEY (USER_ID) 
    REFERENCES so."User" (USER_ID) ON DELETE RESTRICT ON UPDATE RESTRICT;

ALTER TABLE so.QuestionTaggedTag 
    ADD CONSTRAINT QuestionTaggedTag_FK1 FOREIGN KEY (QUESTION_ID) 
    REFERENCES so.Question (QUESTION_ID) ON DELETE RESTRICT ON UPDATE RESTRICT;

ALTER TABLE so.QuestionTaggedTag 
    ADD CONSTRAINT QuestionTaggedTag_FK2 FOREIGN KEY (TAG_ID) 
    REFERENCES so.Tag (TAG_ID) ON DELETE RESTRICT ON UPDATE RESTRICT;

ALTER TABLE so.Answer 
    ADD CONSTRAINT Answer_FK1 FOREIGN KEY (USER_ID) 
    REFERENCES so."User" (USER_ID) ON DELETE RESTRICT ON UPDATE RESTRICT;

ALTER TABLE so.Answer 
    ADD CONSTRAINT Answer_FK2 FOREIGN KEY (QUESTION_ID) 
    REFERENCES so.Question (QUESTION_ID) ON DELETE RESTRICT ON UPDATE RESTRICT;

COMMIT WORK;

TAG_ID主キーとして別のタグテーブルがあることに注意してください。TAG_NAMEは、一意性の制約がある別の列であり、タグの重複を防ぎます。これで、QuestionTaggedTagテーブルに(QUESTION_IDTAG_ID)が追加されました。これは、主キーでもあります。

これに答えるのに行き過ぎないことを願っていますが、もっと小さな答えを書こうとすると、以前の答えを解きほぐす必要があり、これを投稿するだけの方が簡単に思えました。

于 2009-07-28T22:56:09.620 に答える
2

タグ テーブルの (question_id, tag_name) に一意の制約を作成して、ペアが一意であることを確認できます。これは、同じ質問に同じタグが複数回付けられていない可能性があることを意味します。ただし、同じタグが異なる質問に適用される可能性があります。

于 2009-07-28T21:39:15.687 に答える
1

2 つの主キーを作成することはできませんが、インデックスに一意性制約を設定できます。

于 2009-07-28T21:39:48.820 に答える
1

主キーは 1 つしか持てませんが (「秘密」キーとはそういう意味だと思います)、そのキーは質問 ID とタグ名で構成される複合キーにすることができます。SQL では、次のようになります (SQL ダイアレクトによって異なります)。

CREATE TABLE Tags
(
  question_id int,
  tag_name varchar(xxx),
  PRIMARY KEY (question_id, tag_name)
);

これにより、同じ質問に対して同じタグを付けることができなくなります。

于 2009-07-28T21:40:27.820 に答える
0

PostgreSQL または Oracle を使用します。

以下はMySQL用のKenさんのコードに対応していると思います。

CREATE TABLE Tags 
     (
         QUESTION_ID integer FOREIGN KEY REFERENCES Questions(QUESTION_ID) 
                             CHECK (QUESTION_ID>0), 
         TAG_NAME nvarchar(20) NOT NULL,
         CONSTRAINT no_duplicate_tag UNIQUE (QUESTION_ID,TAG_NAME)
     )

クエリに追加の対策を追加しました。たとえばCHECK (USER_ID>0)、データベースに破損したデータがないことを確認することです。

1 つの質問に意図的に選択された 2 つのタグを含めることはできないため、システムが壊れる可能性があるため、AUTO_INCREMENTここからを削除しました。QUESTION_ID他の場合は、タグが混同されます。

制約に名前を付ける必要があることがわかりました。その名前はno_duplicate_tagコマンドにあります。

于 2009-07-28T21:59:42.087 に答える