1

私はQuestionsそのように見えるテーブルを持っています

ここに画像の説明を入力

ご覧のとおり、ほぼ同じ 2 つの id 行があります: id, question_id. id- は自動インクリメントされ、各質問の一意の ID であり、question_id- は、たとえば、コース 1 のレッスン 1 には質問 1、2、3、4、5 のような 5 つの質問があります。コース 1 のレッスン 2 には 3 つの質問があります: 1、2、 3 など。つまり、一意course_idlesson_id組み合わせごとに自動インクリメント フィールドのようなものです。データベース構造の読みやすさを維持し、データベースを台無しにしないために、値間の関連テーブルの束を使用して、にquestion_id基づいて手動で追加することにしました。course_idlesson_idcourse-lesson-question unique id

最初の質問は

あなたはどう思いますか、それは良い解決策ですか?このデータベースをどのように設計しますか?


問題は、指定された新しい質問を挿入したいときにcourse_id、フィールドが自動インクリメントされることですが、lesson_idid

2 番目の質問

一意の組み合わせquestion_idに基づいて最後の列の値を取得するにはどうすればよいですか。たとえば、コース 1 のレッスン 2 に 1、2、3 の 3 つの質問があり、4 番目の質問を追加したい場合 (私が言ったように、現在のデータベース設計では手動で値を挿入しています)、どうすればそれを知ることができますか?もちろん 1 レッスン 2 は 3 番目で、新しい質問を (last_number=3)++=4? で挿入します。course_idlesson_idquestion_id

アップデート

状況は少し複雑ですが、説明しようと思います。

オンラインのチュートリアル Web サイトです。さまざまなコースがあり、各コースにはたくさんのレッスンがあります。現在、教師が質問を投稿し、ユーザーが専用の質問を取得する、質問と回答の部分を設計しています。

フルサイズ画像はこちら

ここに画像の説明を入力

現在、テーブルquestionsはコース>レッスンベースの質問専用です。

question_from_to_assoc- 質問の作成者と受信者のユーザーの間の関連付けを作成するためのものです。たとえば、admin (id=.) は、id=5 のユーザーに質問を送信します。

qa_assoc- 質問と回答の関連付けテーブル。

4

5 に答える 5

3

まず第一に、これは最適なデータベース設計ではありません。スキーマが非正規化されていますが、これはあまり良くありません。

あなたの最初の質問に答えるために。レッスン、コース、質問、作成者を別々のテーブルに分割します。次に、コースレッスン質問の主キーの横に数字フィールドを追加します。PKは行の一意性を保証するだけですが、番号フィールドはコース番号、質問番号などになります。たとえば、PKを使用して質問番号を表すことは、変更しないでおく必要があるため、私の意見ではお勧めできません。 。たとえば、質問が数字ではなく文字に変更された場合、PKを変更する必要があり、これにより参照整合性が損なわれる可能性があります。

その後、[question_no、lesson_id]のような質問番号とFKに一意の制約を追加して、同じレッスンで2つの質問1を使用できないようにします。レッスンも同じです。コースには、course_noに一意の制約があります。

最後に、レッスンに応じて質問番号を自動的に増やすために、次のようなトリガーを使用します。

CREATE TRIGGER tr_question_number BEFORE INSERT ON questions
FOR EACH ROW BEGIN
   SET NEW.question_no = (SELECT MAX(question_no)+1 FROM questions WHERE lesson_id = NEW.lesson_id FOR UPDATE)
END;

このトリガーは、質問番号フィールドに最新の値+ 1を設定します。FORUPDATE句は、同じ番号を取得するための同時挿入を回避するために行をロックするため、非常に重要です。

トリガーは単なるドラフトですが、それは私が何をしたかについての一般的な考えです。

これがお役に立てば幸いです。

于 2012-07-24T22:13:34.093 に答える
2

質問 1:いいえ。質問テーブルの ID 列を一意の識別子として使用し、その question_id フィールドを削除します。私のデザイン:

 create table author (
   id int(11) NOT NULL auto_increment,
   name varchar(256)
 ) engine=innodb;

 create table course (
   id int(11) not null auto_increment,
   primary key(id),
   name varchar(256)
 ) engine=innodb;

create table lesson (
  id int(11) not null auto_increment,
  primary key(id),
  name varchar(256),
  course_id int(11) NOT NULL,
  FOREIGN KEY(course_id) references course(id)
) engine=innodb;

create table question(
   id int(11) not null auto_increment,
   primary key(id),
   question_text text,
   correct_answer text,
   lesson_id int(11) NOT NULL,
   foreign key(lesson_id) references lesson(id),
   author_id int(11) not null,
   FOREIGN KEY(author_id) REFERENCES author(id)
) engine=innodb;

質問 2:そうしないでください。course_id 1、レッスン 2、および質問 11 がある場合はどうなりますか? その ID 列は、course_id 1、レッスン 21、質問 1 と同じになります。

余談ですが、外部キーを使用していることを本当に願っています。mysql を使用していると表示されているため、外部キーを使用して参照整合性を確保できるように、必ずこれらのテーブルで Innodb ストレージ エンジンを使用してください。

このデータベースを効率的にクエリし、一意であると思われる値の競合を回避し、将来の深刻なパフォーマンスの問題を回避し、データの重複を回避するための鍵は、データベースを正規化された方法で設計することです。上記の例は正規化されており、データの重複や、上で定義した一意のキーにならない複合キー スキームを回避しています。車輪の再発明を試みるよりも、MySQL に組み込まれている機能を使用することをお勧めします。

于 2012-07-24T21:25:56.103 に答える
2

私は個人的にこれを別の方法で設定します:

Question table:
id int, -- PK auto-increment
content varchar(50),
answer varchar(50),
authorid int

Course table:
id int, -- PK auto-increment
name varchar(50)

Lesson Table: 
id int, -- PK auto-increment
name varchar(50)

Question_Course_Lesson join table: 
questionid int, -- PK
courseid int,  -- PK
lessonid int   -- PK
于 2012-07-24T21:26:49.283 に答える
0

1. 自動インクリメントを取り除き、主キーとしてquestion_idのみ残すようにしてください。idそうしないと、挿入が面倒になります。

問題は、指定された course_id、lesson_id で新しい質問を挿入したいときに、id フィールドが自動インクリメントされることです。

私は問題を理解していません-auto_incrementフィールドは通常それを行います:)。

2.使用できます

SELECT MAX(question_id) WHERE course_id = <something> AND lesson_id = <some_other_thing>

特定の course_id および lesson_id の現在の最大 ID を取得します。ただし、新しいレコードを挿入した後、テーブルをロックし (または、テーブルが InnoDB の場合は FOR UPDATE とトランザクションを使用)、ロックを解除して一貫性を保つ必要があります。

于 2012-07-24T21:26:17.643 に答える
0

最初の質問。 実際、「冗長な」ID が必要な理由がわかります。たとえば、受験者に質問を提示するプロセスで役割を果たす場合があります。ただし、行内の他の列の値に関連付ける必要はありません。自動生成された ID により一意性が保証されます。

2 番目の質問です。 onInsert トリガーを使用します。衝突を防ぐ最善の方法です。

于 2012-07-24T21:37:48.143 に答える