我想知道如何防止在数据库表中使用两个相同的标记。 有人说我在表中使用两个私钥。然而,W3Schools -website表示这是不可能的。
我的关系表
alt text http://files.getdropbox.com/u/175564/db/db7.png
我的逻辑表格
alt text http://files.getdropbox.com/u/175564/db/db77.png
表格的上下文
alt text http://files.getdropbox.com/u/175564/db/db777.png
如何防止在问题中使用重复的标签?
答案 0 :(得分:2)
您可以在tags表中的(question_id,tag_name)上创建唯一约束,这将确保对是唯一的。这意味着同一个问题可能不会多次连接相同的标签。但是,相同的标签仍然适用于不同的问题。
答案 1 :(得分: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表,其中TAG_ID
为主键。 TAG_NAME
是一个单独的列,其上有唯一性约束,可防止重复标记。 QuestionTaggedTag
表现在有(QUESTION_ID
,TAG_ID
),这也是它的主键。
我希望我在回答这个问题时没有走得太远,但是当我试着写出较小的答案时,我不得不解开我之前的答案,发布这个答案似乎更简单。
答案 2 :(得分:1)
您不能创建两个主键,但可以在索引上放置唯一性约束。
答案 3 :(得分:1)
您只能拥有一个主键(我假设您的意思是“私钥”),但该键可以是由
CREATE TABLE Tags
(
question_id int,
tag_name varchar(xxx),
PRIMARY KEY (question_id, tag_name)
);
这将确保您不能对同一问题使用相同的标记。
答案 4 :(得分:0)
我将使用PostgreSQL或Oracle。
我觉得以下内容与Ken的MySQL代码相对应。
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)
是为了确保数据库中没有损坏的数据。
我从AUTO_INCREMENT
中删除了QUESTION_ID
因为我发现它会破坏我们的系统,因为一个问题不能有两个故意选择的标签。在其他情况下,标签会混淆。
我看到我们需要为约束命名。它的名称在命令中为no_duplicate_tag
。