我为每个学生准备了一份名为interests
学校科目的表格。
学生必须至少有3个科目兴趣,最多7个。
可能的主题兴趣是:
然而,在我的两个表格设计中,我都无法弄清楚如何规范表格。
第一张表:interests
(8列)
student_id(pk) | interest_1 | interest_2 | ... | interest_7
在此设计中,interests_1
到interest_7
是列。如果学生选择科学,数学和英语作为他的兴趣,那么
interest_1
设置为science
interest_2
设置为math
interest_3
设置为english
interest_4
至interest_7
设置为null
第二张表:interests
(8列)
student_id(pk) | science | math | english | ... | foreign_lanaguage
在这个设计中,学校科目现在是专栏。如果学生的兴趣是科学,数学和英语,则这些列设置为true
,其余列设置为false
。
science
设置为true
math
设置为true
english
设置为true
history
设置为false
art
设置为false
physical_education
设置为false
foreign_language
设置为false
我还能如何设计这张表?
而且,我如何只选择特定学生感兴趣的科目?
答案 0 :(得分:3)
这实际上取决于您希望的扩展程度。一方面你的设计有效。
另一方面,如果要添加新类,则必须进入并修改表。
另一种方法是拥有3个表:
学生 ID,姓名
类 ID,名称
StudentInterrests ID,StudentID,ClassID
如果学生班级组合未出现在学生兴趣表中,则他们不会对课程感兴趣
您选择的学生兴趣看起来像这样:
SELECT StudentName, CourseName
FROM Student
LEFT JOIN StudentInterrests ON Student.ID = StudentInterrests.StudentID
LEFT JOIN Class ON StudentInterrests.ClassID = Class.ID
你的结果是:
John,Math
约翰,英语
John,SocialStudies
满足您的最低和最高要求:我建议将需求放在应用程序级别,因为它看起来比应用程序逻辑更多,而不是对数据库的约束。
答案 1 :(得分:0)
规范化时,识别正在创建的每个表的正确主键非常重要。将字段分解为最基本的形式。你有什么?你有student_id和兴趣。由于兴趣可以是真或假,您可以将兴趣名称存储在与其他兴趣相同的列中,因此如果它们不存在于student_id中,那么该学生对它们不感兴趣。
这接近一个家庭作业问题,所以为你解决这个问题似乎很愚蠢。相反,我会让你走上正确的轨道。 student_id不是您要查找的主键,但它是一个索引。您希望获得一个3列表,以获得最理想的数据结构。
答案 2 :(得分:0)
好的,为了满足您的要求,您的设计将起作用。我看到另外两个易于实现的选项,可以满足给定的规范。
1。)具有7个利益的学生表以外键密钥到兴趣表;使用一组独特的约束来确保没有学生有两个相同的兴趣。使用可为空的外键并允许第4-7项使用空值。
2。)打破利益表。虽然强制性利益只会在选择利益后触发约束(因此学生可以拥有0 OR 3-8利益),因此该规则的工作效率为99%。这是一种稍微合理的方法,因此您可以将学生表与兴趣分开填充。这可以保持可扩展性。
这两种方法都是第三种常规形式,可以使用ANSI-92兼容的数据库。 SQL Server中#2的示例实现如下。
USE [DB]
GO
/****** Object: Table [dbo].[Interests] Script Date: 11/9/2012 8:32:39 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Interests](
[interestID] [int] IDENTITY(1,1) NOT NULL,
[interestText] [varchar](255) NOT NULL,
[interestDescription] [varchar](max) NULL,
CONSTRAINT [PK_Interests] PRIMARY KEY CLUSTERED
(
[interestID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
/****** Object: Table [dbo].[StudentInterests] Script Date: 11/9/2012 8:32:39 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[StudentInterests](
[studentInterestID] [int] IDENTITY(1,1) NOT NULL,
[studentID] [int] NOT NULL,
[interestID_1] [int] NOT NULL,
[interestID_2] [int] NOT NULL,
[interestID_3] [int] NOT NULL,
[interestID_4] [int] NULL,
[interestID_5] [int] NULL,
[interestID_6] [int] NULL,
[interestID_7] [int] NULL,
[interestID_8] [int] NULL,
CONSTRAINT [PK_StudentInterests] PRIMARY KEY CLUSTERED
(
[studentInterestID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
CONSTRAINT [IX_StudentInterests] UNIQUE NONCLUSTERED
(
[studentInterestID] ASC,
[interestID_1] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
CONSTRAINT [IX_StudentInterests_1] UNIQUE NONCLUSTERED
(
[studentInterestID] ASC,
[interestID_2] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
CONSTRAINT [IX_StudentInterests_2] UNIQUE NONCLUSTERED
(
[studentInterestID] ASC,
[interestID_3] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
CONSTRAINT [IX_StudentInterests_3] UNIQUE NONCLUSTERED
(
[studentInterestID] ASC,
[interestID_4] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
CONSTRAINT [IX_StudentInterests_4] UNIQUE NONCLUSTERED
(
[studentInterestID] ASC,
[interestID_4] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
CONSTRAINT [IX_StudentInterests_5] UNIQUE NONCLUSTERED
(
[studentInterestID] ASC,
[interestID_5] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
CONSTRAINT [IX_StudentInterests_6] UNIQUE NONCLUSTERED
(
[studentInterestID] ASC,
[interestID_6] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
CONSTRAINT [IX_StudentInterests_7] UNIQUE NONCLUSTERED
(
[studentInterestID] ASC,
[interestID_7] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
CONSTRAINT [IX_StudentInterests_8] UNIQUE NONCLUSTERED
(
[studentInterestID] ASC,
[interestID_8] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
CONSTRAINT [IX_StudentInterests_9] UNIQUE NONCLUSTERED
(
[studentID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[Students] Script Date: 11/9/2012 8:32:39 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Students](
[studentID] [int] IDENTITY(1,1) NOT NULL,
[firstName] [varchar](255) NOT NULL,
[lastName] [varchar](255) NOT NULL,
CONSTRAINT [PK_Students] PRIMARY KEY CLUSTERED
(
[studentID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[StudentInterests] WITH CHECK ADD CONSTRAINT [FK_StudentInterests_Interests] FOREIGN KEY([interestID_1])
REFERENCES [dbo].[Interests] ([interestID])
GO
ALTER TABLE [dbo].[StudentInterests] CHECK CONSTRAINT [FK_StudentInterests_Interests]
GO
ALTER TABLE [dbo].[StudentInterests] WITH CHECK ADD CONSTRAINT [FK_StudentInterests_Interests1] FOREIGN KEY([interestID_2])
REFERENCES [dbo].[Interests] ([interestID])
GO
ALTER TABLE [dbo].[StudentInterests] CHECK CONSTRAINT [FK_StudentInterests_Interests1]
GO
ALTER TABLE [dbo].[StudentInterests] WITH CHECK ADD CONSTRAINT [FK_StudentInterests_Interests2] FOREIGN KEY([interestID_3])
REFERENCES [dbo].[Interests] ([interestID])
GO
ALTER TABLE [dbo].[StudentInterests] CHECK CONSTRAINT [FK_StudentInterests_Interests2]
GO
ALTER TABLE [dbo].[StudentInterests] WITH CHECK ADD CONSTRAINT [FK_StudentInterests_Interests3] FOREIGN KEY([interestID_4])
REFERENCES [dbo].[Interests] ([interestID])
GO
ALTER TABLE [dbo].[StudentInterests] CHECK CONSTRAINT [FK_StudentInterests_Interests3]
GO
ALTER TABLE [dbo].[StudentInterests] WITH CHECK ADD CONSTRAINT [FK_StudentInterests_Interests4] FOREIGN KEY([interestID_5])
REFERENCES [dbo].[Interests] ([interestID])
GO
ALTER TABLE [dbo].[StudentInterests] CHECK CONSTRAINT [FK_StudentInterests_Interests4]
GO
ALTER TABLE [dbo].[StudentInterests] WITH CHECK ADD CONSTRAINT [FK_StudentInterests_Interests5] FOREIGN KEY([interestID_6])
REFERENCES [dbo].[Interests] ([interestID])
GO
ALTER TABLE [dbo].[StudentInterests] CHECK CONSTRAINT [FK_StudentInterests_Interests5]
GO
ALTER TABLE [dbo].[StudentInterests] WITH CHECK ADD CONSTRAINT [FK_StudentInterests_Interests6] FOREIGN KEY([interestID_7])
REFERENCES [dbo].[Interests] ([interestID])
GO
ALTER TABLE [dbo].[StudentInterests] CHECK CONSTRAINT [FK_StudentInterests_Interests6]
GO
ALTER TABLE [dbo].[StudentInterests] WITH CHECK ADD CONSTRAINT [FK_StudentInterests_Interests7] FOREIGN KEY([interestID_8])
REFERENCES [dbo].[Interests] ([interestID])
GO
ALTER TABLE [dbo].[StudentInterests] CHECK CONSTRAINT [FK_StudentInterests_Interests7]
GO
ALTER TABLE [dbo].[StudentInterests] WITH CHECK ADD CONSTRAINT [FK_StudentInterests_Students] FOREIGN KEY([studentID])
REFERENCES [dbo].[Students] ([studentID])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[StudentInterests] CHECK CONSTRAINT [FK_StudentInterests_Students]
GO