用SQL的DDL语句创建名为“图书管理”的数据库。在该数据库中用SQL的DDL语句创建三张基表,关系模式如下 (下划线处为主键,两个斜体处为两个外键): 图书(图书编号、分类号、书名、作者、出版单位、单价) 读者(借书证号、姓名、单位、职称) 借阅(借书证号、图书编号、借阅日期、备注) 要求:定义实体完整性、参照完整性、用户定义的完整性(图书表的分类号不能为空值、读者表的姓名不能为空值、借阅表的借阅日期不能为空值)
时间: 2025-04-18 13:23:32 浏览: 79
<think>好的,用户现在想用SQL的DDL语句创建一个名为“图书管理”的数据库,并在其中创建三张基表:图书、读者、借阅。同时需要定义实体完整性、参照完整性和用户定义的完整性约束。用户还特别提到要设置主键、外键以及非空约束,具体涉及分类号、姓名、借阅日期这些字段。
首先,我需要回忆一下用户之前的提问历史。之前用户遇到了“No database selected”的错误,这是因为在创建表之前没有选择数据库或者没有在表名前指定数据库名。所以这次在回答时,我需要确保在创建表之前先创建并选择正确的数据库,或者显式指定数据库名,避免同样的错误再次发生。
接下来,用户的需求是创建三个表,每个表都有不同的约束。根据引用[1]中的示例,创建表的基本结构是CREATE TABLE语句,后面跟列名、数据类型和约束。比如主键用PRIMARY KEY,外键用FOREIGN KEY REFERENCES,非空约束用NOT NULL。同时用户定义的完整性可能包括CHECK约束,比如价格必须大于零,借阅日期不能早于某个日期等。
需要确定每个表的结构:
1. 图书表(Book):需要主键BookId,分类号Class非空,书名BookName,作者Author,出版社Publish,价格Price,可能还有CHECK约束比如价格大于0。
2. 读者表(Reader):主键ReaderId,姓名Name非空,可能还有联系方式Contact,性别Gender,年龄Age等,这里用户只提到姓名需要非空,所以其他字段是否需要非空要看用户需求,但根据问题描述,可能只需要姓名非空。
3. 借阅表(Borrow):主键可能是组合主键(BookId, ReaderId, BorrowDate),但根据引用[1]中的例子,外键做主码时约束类型要一致,所以需要确认借阅表的主键是否由BookId和ReaderId组成,或者是否包括借阅日期。用户问题中提到了借阅日期需要非空,所以可能主键是(BookId, ReaderId, BorrowDate),或者单独的主键字段,需要进一步分析。
根据用户提供的引用[1]中的例子,BORROW表的主键是BOOK_ID和READER_ID的组合,外键分别引用BOOK和READER表的主键。所以在当前问题中,借阅表的主键可能也是由BookId和ReaderId组成,或者加上BorrowDate组成三列的主键。但用户提到需要设置非空约束在借阅日期,所以BorrowDate需要非空,但不一定作为主键的一部分。可能借阅表的主键是单独的一个字段,比如BorrowId,或者组合主键,比如BookId、ReaderId和BorrowDate的组合,但具体情况需要看用户的需求。不过根据常规设计,借阅记录通常使用组合主键来唯一标识一次借阅,比如同一本书被同一个读者在同一天借阅的情况可能重复,所以可能需要BorrowId作为主键,或者使用组合主键。
但根据用户问题中的要求,可能更倾向于使用组合主键。例如,在引用[1]的例子中,BORROW表的主键是BOOK_ID和READER_ID的组合,并且外键分别引用BOOK和READER表的主键。所以这里可能需要类似的结构:借阅表的主键由BookId和ReaderId组成,同时BorrowDate非空。或者可能主键是BookId、ReaderId和BorrowDate的组合,但用户没有明确说明,需要根据常规做法推断。
另外,用户定义的完整性可能包括CHECK约束,比如借阅日期不能早于某个日期,或者价格必须为正数,分类号必须符合某种格式等。例如,在引用[1]的例子中,价格使用了CHECK(PRICE>0),所以在当前问题中,可能也需要类似的约束。
接下来需要考虑的是各个表的字段:
图书表:
- BookId (主键)
- Class (分类号,非空)
- BookName
- Author
- Publish
- Price (CHECK约束>0)
读者表:
- ReaderId (主键)
- Name (非空)
- 其他字段如联系方式、性别等,但用户问题中未提及,可能不需要,或者可以自行添加。
借阅表:
- BookId (外键,引用图书表的BookId)
- ReaderId (外键,引用读者表的ReaderId)
- BorrowDate (非空)
可能的其他字段如ReturnDate,但用户问题中未提及,所以可能只需要这三个字段。主键可能需要BookId和ReaderId的组合,或者加上BorrowDate的组合。或者主键是单独的一个字段,比如BorrowId,但用户问题中没有提到,所以可能使用复合主键。
根据用户的问题,需要定义主键、外键以及非空约束。所以借阅表的主键应该是BookId和ReaderId的组合,或者包括BorrowDate,但需要确认。不过用户问题中要求借阅日期非空,所以BorrowDate需要NOT NULL,但可能不作为主键的一部分。可能主键由BookId和ReaderId组成,但这样同一读者多次借同一本书可能会有问题,所以可能需要BorrowDate作为主键的一部分。或者主键为(BookId, ReaderId, BorrowDate),但用户可能希望每次借阅记录是唯一的,所以这样比较合理。
现在需要综合这些分析来编写SQL语句。
首先创建数据库:
CREATE DATABASE IF NOT EXISTS 图书管理
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
然后使用数据库:
USE 图书管理;
或者,在创建表时显式指定数据库名,如CREATE TABLE 图书管理.Book (...),但USE语句更简洁。
接下来创建三个表:
图书表:
CREATE TABLE Book (
BookId CHAR(4) PRIMARY KEY,
Class CHAR(10) NOT NULL,
BookName VARCHAR(50),
Author VARCHAR(25),
Publish VARCHAR(25),
Price DECIMAL(6,2) CHECK (Price > 0)
);
这里主键是BookId,分类号Class非空,Price使用CHECK约束确保大于0。
读者表:
CREATE TABLE Reader (
ReaderId CHAR(10) PRIMARY KEY,
Name VARCHAR(30) NOT NULL,
Contact VARCHAR(50),
Gender CHAR(2),
Age INT
);
这里主键是ReaderId,Name非空。
借阅表:
CREATE TABLE Borrow (
BookId CHAR(4),
ReaderId CHAR(10),
BorrowDate DATE NOT NULL,
PRIMARY KEY (BookId, ReaderId, BorrowDate),
FOREIGN KEY (BookId) REFERENCES Book(BookId),
FOREIGN KEY (ReaderId) REFERENCES Reader(ReaderId)
);
这里主键是BookId、ReaderId和BorrowDate的组合,BorrowDate非空,外键分别引用Book和Reader表的主键。
但这里可能需要考虑同一本书同一读者多次借阅的情况,比如同一读者在不同时间借同一本书,所以主键包括BorrowDate是合理的,确保唯一性。但用户问题中是否允许同一读者多次借同一本书呢?如果允许,那么主键必须包含BorrowDate;否则,如果同一读者只能借同一本书一次,那么主键可以是(BookId, ReaderId)。但根据实际情况,通常允许同一读者多次借同一本书,所以主键应包括BorrowDate。
不过用户问题中并没有明确说明这一点,但根据常规设计,可能需要包含BorrowDate在主键中。或者可能用户希望每次借阅记录是唯一的,所以主键为(BookId, ReaderId, BorrowDate)。
另外,可能还需要外键约束,比如在借阅表中,BookId和ReaderId必须存在于对应的表中,所以FOREIGN KEY约束是正确的。
此外,用户定义的完整性可能还包括其他CHECK约束,比如BorrowDate不能是未来日期,或者必须大于某个日期,但用户没有明确要求,所以可能不需要。但如果有的话,可以添加CHECK (BorrowDate <= CURRENT_DATE)之类的约束,不过这可能因数据库系统而异,例如MySQL中CHECK约束可能不被支持,或者需要特定版本。
但根据问题描述,用户可能只需要确保必要的约束,即主键、外键和非空约束,其他CHECK约束可能根据具体情况添加。
现在总结以上思考,编写完整的SQL语句:
首先创建数据库:
CREATE DATABASE IF NOT EXISTS 图书管理
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
USE 图书管理;
然后创建三个表:
CREATE TABLE Book (
BookId CHAR(4) PRIMARY KEY,
Class CHAR(10) NOT NULL,
BookName VARCHAR(50),
Author VARCHAR(25),
Publish VARCHAR(25),
Price DECIMAL(6,2) CHECK (Price > 0)
);
CREATE TABLE Reader (
ReaderId CHAR(10) PRIMARY KEY,
Name VARCHAR(30) NOT NULL,
Contact VARCHAR(50),
Gender CHAR(2),
Age INT
);
CREATE TABLE Borrow (
BookId CHAR(4),
ReaderId CHAR(10),
BorrowDate DATE NOT NULL,
PRIMARY KEY (BookId, ReaderId, BorrowDate),
FOREIGN KEY (BookId) REFERENCES Book(BookId),
FOREIGN KEY (ReaderId) REFERENCES Reader(ReaderId)
);
这样满足用户的需求:
- 创建了“图书管理”数据库
- 创建了三个基表:Book、Reader、Borrow
- 主键约束:每个表的主键定义正确
- 外键约束:Borrow表的BookId和ReaderId外键引用对应表的主键
- 非空约束:分类号(Class)、姓名(Name)、借阅日期(BorrowDate)设为NOT NULL
- 用户定义的完整性:Price的CHECK约束确保价格大于0
此外,需要注意字符集和校对规则,使用utf8mb4以支持中文,如用户之前的示例中提到的。同时,字段长度可能需要根据实际情况调整,比如ReaderId长度是否为CHAR(10),但用户之前的示例中BookId是CHAR(4),所以可能用户有特定需求,这里保留原样。
最后,验证是否解决了用户之前遇到的“No database selected”错误。在创建表之前使用了USE 图书管理;,或者在CREATE TABLE语句中显式指定数据库名,如CREATE TABLE 图书管理.Book (...),但使用USE语句更简洁,避免错误。
另外,用户可能使用的数据库系统是MySQL,因为之前的问题涉及MySQL的语法和错误。因此,上述SQL语句应符合MySQL的语法要求。例如,在MySQL中,CHECK约束在8.0.16及以上版本才被完全支持,如果用户使用的是较旧版本,可能需要使用触发器来实现约束,但用户的问题可能假设支持CHECK约束。
总结,上述SQL语句应该满足用户的需求,正确创建数据库和表,并设置所需的约束。</think>### 分步骤解决方案:创建图书管理数据库及三张基表
---
#### **1. 创建数据库并指定字符集**
```sql
-- 创建数据库(支持中文存储)
CREATE DATABASE IF NOT EXISTS 图书管理
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
-- 显式选择数据库
USE 图书管理;
```
---
#### **2. 创建图书表(Book)**
**实体完整性**:`BookId` 为主键
**用户定义完整性**:`Class` 非空,`Price` 需大于0
```sql
CREATE TABLE Book (
BookId CHAR(4) PRIMARY KEY, -- 主键约束
Class CHAR(10) NOT NULL, -- 分类号非空
BookName VARCHAR(50) NOT NULL, -- 书名非空
Author VARCHAR(25),
Publish VARCHAR(25),
Price DECIMAL(6,2) CHECK (Price > 0) -- 价格必须大于0
);
```
---
#### **3. 创建读者表(Reader)**
**实体完整性**:`ReaderId` 为主键
**用户定义完整性**:`Name` 非空
```sql
CREATE TABLE Reader (
ReaderId CHAR(10) PRIMARY KEY, -- 主键约束
Name VARCHAR(30) NOT NULL, -- 姓名非空
Contact VARCHAR(50),
Gender CHAR(2),
Age INT
);
```
---
#### **4. 创建借阅表(Borrow)**
**实体完整性**:`(BookId, ReaderId, BorrowDate)` 为复合主键
**参照完整性**:外键关联图书表和读者表
**用户定义完整性**:`BorrowDate` 非空
```sql
CREATE TABLE Borrow (
BookId CHAR(4),
ReaderId CHAR(10),
BorrowDate DATE NOT NULL, -- 借阅日期非空
PRIMARY KEY (BookId, ReaderId, BorrowDate),-- 复合主键
FOREIGN KEY (BookId) REFERENCES Book(BookId) ON DELETE CASCADE,
FOREIGN KEY (ReaderId) REFERENCES Reader(ReaderId) ON UPDATE CASCADE
);
```
---
#### **5. 关键约束说明**
| **约束类型** | **实现方式** | **示例字段** |
|----------------------|---------------------------------------|--------------------|
| 实体完整性(主键) | `PRIMARY KEY` | `BookId` |
| 参照完整性(外键) | `FOREIGN KEY REFERENCES` | `Borrow.BookId` |
| 用户定义完整性 | `CHECK`、`NOT NULL` | `Price > 0` |
| 级联操作 | `ON DELETE CASCADE`、`ON UPDATE CASCADE` | 外键关联时自动同步 |
---
### **注意事项**
1. **字符集一致性**
使用 `utf8mb4` 字符集和 `utf8mb4_unicode_ci` 校对规则,确保支持中文存储和检索[^1]。
2. **外键级联操作**
- `ON DELETE CASCADE`:删除图书或读者时,自动删除关联的借阅记录
- `ON UPDATE CASCADE`:更新读者ID时,自动同步借阅表中的关联记录
3. **复合主键设计**
借阅表使用 `(BookId, ReaderId, BorrowDate)` 作为主键,防止同一读者重复借阅同一图书的同日记录。
---
### **相关问题**
1. 如何添加图书库存数量的约束?
2. 读者联系方式如何设置唯一性约束?
3. 如何优化借阅表的历史查询性能?
4. 不同数据库(如Oracle、SQL Server)的DDL语法差异有哪些?
---
### **引用说明**
: 通过 `CHARACTER SET utf8mb4` 配置可完整支持四字节字符(如Emoji),避免数据截断问题[^1]。
[^2]: 级联操作需谨慎使用,可能引发连锁数据变更,建议根据业务需求选择 `RESTRICT` 或 `NO ACTION`[^2]。
阅读全文
相关推荐

















