☰
SQL语言-课内部分数据定义
2026/9/30 4:00:17 网站建设 项目流程

1. SQL 概述

SQL 的五个特点

⑴ 综合统一(DDL, DML, DCL);⑵ 高度非过程化;⑶ 面向集合的操作方式;⑷ 以同一种语法结构提供两种使用方式——既是自含式语言,又是嵌入式语言;⑸ 语言简捷,易学易用。

使用的动词

SQL 功能动词
数据定义 DDLCREATE、DROP、ALTER
数据查询 DQLSELECT
数据更新 DMLINSERT、UPDATE、DELETE
数据控制 DCLGRANT、REVOKE
  • 动词的类别决定了它改的是"结构"还是"数据"——DDL 三个动词动的是对象结构(库、表、视图、索引),DML 三个动词动的是表里的行。第一部分全是 DDL。
  • 要点:课件原文"通常 SQL 语言中不区分大小写,部分数据库提供参数可配置"——指的是关键字;库名/表名在 Linux 上的 MySQL 默认是区分大小写的。

2. 数据定义总览与库对象层次

操作对象创建删除修改
库CREATE DATABASEDROP DATABASEALTER DATABASE
表CREATE TABLEDROP TABLEALTER TABLE
视图CREATE VIEWDROP VIEWALTER VIEW
索引CREATE INDEXDROP INDEX—(索引没有修改,见 [[2 索引]])
名称MySQL(课件 16 页)PostgreSQL(课件 19 页)
数据库集群 cluster可包含 1 个或多个数据库可包含 1 个或多个数据库
数据库 database可包含 1 个或多个基本表可包含 1 个或多个模式
模式 schema等于 database(MySQL 中两者等价)包含表/视图/索引,默认public;另有系统模式pg_catalog(系统表、内置数据类型与函数)
表 table存放数据的基本表存放数据的基本表
表空间 tablespaceInnoDB:共享表空间(所有数据放一个表空间里,可跨多个文件)/ 独立表空间(默认,每个表独立,索引与数据分离)逻辑上分出的存储单元,可按快慢盘分别放置(频繁用的索引放快盘、归档表放慢盘)
  • MySQL 的库就是模式,PG 的库里还能再分模式。所以USE 库名只是 MySQL 的写法,PG 里没有。
  • 基本表(base table):本身独立存在的表,CREATE TABLE建出来的就是它——一个关系对应一个基本表,数据实际存在它里面;与之相对的是视图(虚表,只存定义不存数据)。
  • 模式(schema):本课这个词有两层意思——① 教材三级模式里的模式(概念模式),指"数据库中全体数据的逻辑结构和特征",是所有用户的公共数据视图;② DBMS 实现里的schema,指一组数据库对象(表、视图、索引)的命名容器,上表说的"MySQL 里 schema = database"是第二层意思。
  • DATABASE 和 TABLE 的区别:库是容器,表是容器里一张二维表。一个库能装多张表,一张表只能属于一个库(所以要先USE 库名再建表);CREATE DATABASE建容器,CREATE TABLE建容器里的表。

3. 建库:CREATE / 查看 / ALTER / DROP DATABASE(课件 22~23 页)

-- ① 建库(课件 22 页)CREATEDATABASEstudent;-- 课件原例:最简形态CREATEDATABASEstudent-- 把字符集和排序规则一次交代清楚DEFAULTCHARACTERSETutf8mb4-- 字符集 utf8mb4DEFAULTCOLLATEutf8mb4_0900_ai_ci;-- 排序规则 utf8mb4_0900_ai_ci(_ci = 不区分大小写)-- ② 查看(课件 23 页"查看数据库的信息")SHOWDATABASES;-- 列出服务器上所有库SHOWCREATEDATABASEstudent;-- 看这个库的建库语句(字符集、排序规则在这里)USEstudent;-- 切到该库:此后不带库名的表都建在它下面SELECTDATABASE();-- 确认当前在哪个库-- ③ 改库(课件 23 页原例)ALTERDATABASEmydbREADONLY=0-- 0 可读写 / 1 只读DEFAULTCOLLATEutf8mb4_bin;-- _bin = 按字节比较,区分大小写-- ④ 删库(课件 23 页原例)DROPDATABASEIFEXISTSstudent;-- IF EXISTS:库不存在时只警告不报错
  • 基础操作,比较简单
  • 要点:改库只能改库级选项(只读开关、排序规则等),改不了库名;DROP DATABASE连库里的表一起删,是不可回滚的 DDL。

4. 建表:CREATE TABLE

4.1 语法与两类约束

CREATETABLE<表名>(<列名><数据类型>[列级完整性约束],[<列名><数据类型>[列级完整性约束]]…,[<表级完整性约束>]);
  • 列级完整性约束条件:只涉及一个属性列的约束。
  • 表级完整性约束条件:涉及一个或多个属性列的约束(组合主码、组合外码只能写这里)。

4.2 数据类型

-- 整数类型 字节数 说明 范围smallint-- 2 小范围整数 -32768 ~ 32767int-- 4 常用的整数 -2^31 ~ 2^31-1bigint-- 8 大范围整数 -2^63 ~ 2^63-1-- 浮点与定点类型 字节数 说明decimal(m,n)-- 可变长 用户指定的精度,精确;总共 1~65 位,小数点后 0~30 位numeric(m,n)-- 可变长 MySQL 中等于 decimalfloat-- 4 可变精度,不精确;约 ±10^38,7 位有效数字-- 例:decimal(5,2) 的范围是 -999.99 ~ 999.99-- 字符类型 作用char(n)-- 定长字符数据,不足补空白varchar(n)-- 变长字符数据,有长度限制text-- 变长字符数据,无长度限制-- 日期类型date-- 日期 '2021-01-01',范围 '1000-01-01' ~ '9999-12-31'datetime-- 日期时间 '2021-01-01 10:10:29',范围 '1000-01-01 00:00:00.000000' ~ '9999-12-31 23:59:59.999999'

4.3 完整性约束

-- 课件列出的约束:Primary key, Foreign key, Unique, Null, default, CHECK, auto_incrementCREATETABLEperson(idINTNOTNULLAUTO_INCREMENTPRIMARYKEY,-- 主码 + 自动增长nameVARCHAR(8),-- [Null](不写 NOT NULL 就是允许空)INDEXix_person_name(name)-- 建表时顺带建索引);

这些完整性约束条件被存入系统的数据字典中。

约束含义列级表级
PRIMARY KEY主码:非空且唯一,每表一个✅✅(组合主码只能写这里)
FOREIGN KEY … REFERENCES外码:取值必须是被参照表里已有的值✅✅
NOT NULL不允许为空✅—
UNIQUE取值唯一(主码之外还想唯一的列)✅✅
DEFAULT 值不给值时用什么✅—
CHECK (条件)取值要满足条件✅✅
AUTO_INCREMENT整数列自动加一(MySQL)✅—
  • 总体:约束是写在建表语句里的规则,由 DBMS 存进数据字典并在每次增删改时自动检查。
  • 大思路:这些约束正对应教材里的三类完整性——主码=实体完整性,外码=参照完整性,其余(非空/唯一/CHECK/默认)=用户定义完整性。
  • 要点:PRIMARY KEY本身已经含NOT NULL,列上再写一遍NOT NULL(课件例一就是这么写的)不报错但多余。

4.4 建表例题

-- [例1](课件 28 页)建立"学生"表 StudentCREATETABLEStudent(SnoCHAR(8)NOTNULL,-- 学号:不能为空SnameCHAR(20)UNIQUE,-- 姓名:取值唯一(MySQL 会自动建一个名为 Sname 的唯一索引)SgenderCHAR(6),-- 性别SbirthdateDATE,-- 出生日期SmajorCHAR(40),-- 所在系PRIMARYKEY(Sno)-- 主码写成了表级约束);
-- [例2](课件 29 页)建立"学生选课"表 SCCREATETABLESC(SnoCHAR(8),-- 学号CnoCHAR(3),-- 课程号GradeINT,-- 成绩PRIMARYKEY(Sno,Cno),-- 组合主码:一个学生一门课只有一条记录FOREIGNKEY(Sno)REFERENCESS(Sno),-- 外码①:学号必须在 S 表中存在FOREIGNKEY(Cno)REFERENCESC(Cno)-- 外码②:课程号必须在 C 表中存在);
  • 语法上要求什么(能不能建成):被参照的表S必须已经存在,S里必须有Sno这一列,而且这一列要是S的主码或候选码(MySQL 里就是这一列上必须有主键或唯一索引,随便一个普通列不能被引用),两边类型也要相容;不满足的话建表时直接报错。
  • 数据上要求什么(插数据时的检查):SC里每一行的Sno取值,必须在S表里找得到对应的一行——插入或修改SC时 DBMS 会去S表核对,找不到就报错。反方向不要求:S里的学生可以一行选课记录都没有。
  • 所以不是"一一对应",是"多对一":SC.Sno可以重复(一个学生选多门课),S里同一个Sno也可以被引用多次、或者一次都不被引用。它保证的只有一件事——不会出现"选了不存在的学生的课"。
  • 外码列没写NOT NULL时允许为空,为空的行不检查(NULL不指向任何一行)。

5. 改表与删表

5.1 改表:ALTER TABLE

-- 课件(教材)给的语法格式ALTERTABLE<表名>[ADD<新列名><数据类型>[完整性约束]]-- 增加新列和新的完整性约束条件[ADD<完整性约束名><列名>][DROP<完整性约束名><列名>]-- 删除指定列或列的完整性约束条件[ALTERCOLUMN<列名><数据类型>];-- 修改列名和数据类型-- MySQL 8.0 上实际能执行的动作(一一对应)ALTERTABLEStudentADDCOLUMNSemailVARCHAR(30);-- 加列ALTERTABLEStudentMODIFYCOLUMNSbirthdateVARCHAR(20);-- 改列的数据类型ALTERTABLEStudent CHANGECOLUMNSbirthdate SbirthVARCHAR(20);-- 改列名 + 改数据类型ALTERTABLEStudentDROPCOLUMNSemail;-- 删列
  • 总体:四类动作——加列、改列、删列、改约束。

  • 注意:课件的ALTER COLUMN是教材/标准写法,MySQL 里要写成MODIFY COLUMN(改类型)或CHANGE COLUMN(改列名+类型),理论课按课件写,上机按 MySQL 写。

  • "整列重定义"的意思:MODIFY COLUMN 列 新定义是把这一列的定义整条换成你写的内容,不是只替换你写了的那几项;没写出来的属性一律回到默认值(可空、无默认值),而且不报错:

    CREATETABLEt(aVARCHAR(5)NOTNULLDEFAULT'x',bINT);ALTERTABLEtMODIFYCOLUMNaVARCHAR(10);-- 只想把长度改成 10DESCt;-- 结果 a 变成 Null=YES、Default=NULL:NOT NULL 和 DEFAULT 都丢了-- 要改就把完整定义重写一遍ALTERTABLEtMODIFYCOLUMNaVARCHAR(10)NOTNULLDEFAULT'x';
  • 类型转换不合法的情况确实有:执行ALTER时 DBMS 要把每一行的旧值按新类型重转一遍,转不过去的典型是——变长改短(VARCHAR(20)→VARCHAR(5),严格模式下报ERROR 1406 Data too long)、字符转数字('abc'转int,报ERROR 1265或被截成 0)、日期字符串格式不对,以及改被外码引用的列(外码两边类型必须一致,直接报错)。

  • 碰到了怎么办:① 先SELECT找出会被破坏的行(如WHERE CHAR_LENGTH(a) > 5);② 备份或先清理(CREATE TABLE t_bak AS SELECT * FROM t;);③ 再执行ALTER;④ 改完用DESC+SELECT复查。——课件例4 那句注"修改原有的列定义有可能会破坏已有数据"说的就是这件事。

5.2 例三

-- [例3] 向学生表增加"邮箱地址"列,数据类型为字符型ALTERTABLEStudentADDSemailVARCHAR(30);-- 课件注:不论基本表中原来是否已有数据,新增加的列一律为空值-- [例4] 将 student 表中出生日期的数据类型改为字符型ALTERTABLEStudentALTERCOLUMNSbirthdateVARCHAR(20);-- 课件注:修改原有的列定义有可能会破坏已有数据-- [例5] 增加学生名称必须取唯一值的约束条件ALTERTABLEStudentADDUNIQUE(Sname);-- [例6] 删除学生姓名必须取唯一值的约束ALTERTABLEStudentDROPCONSTRAINTIX_sname;

5.3 删表:DROP TABLE(课件 32 页)

DROPTABLEStudent;-- [例7] 删除 Student 表
  • 要点:表被别的表的外码引用时,直接删会报错,得先处理子表或外码;上机脚本里为可重复执行通常写DROP TABLE IF EXISTS Student;。
  • "被外码引用就删不掉"是什么意思:如果别的表(子表,如SC)上有外码指向Student,DROP TABLE Student;会被 DBMS 拒绝(MySQL 报ERROR 3730 Cannot drop table 'student' referenced by a foreign key constraint)——删了之后子表的外码就指向不存在的数据,参照完整性被破坏。
  • 想删就得先处理子表:先删子表DROP TABLE SC;,或先删子表上的外码ALTER TABLE SC DROP FOREIGN KEY 外码名;,再删父表。注意建表时写的ON DELETE CASCADE只管"删行"、管不了删表;标准 SQL 的DROP TABLE Student CASCADE;在 MySQL 里能写但不生效。除了被外码引用,删不掉的常见原因就只剩权限不够(当前用户没有这张表的DROP权限)。
  • IF EXISTS的作用:表不存在时直接DROP会报错(MySQL 报ERROR 1051 Unknown table),加了IF EXISTS就只给一条警告、脚本继续往下跑——让建表脚本能反复执行。另外DROP TABLE属于 DDL,删了不能回滚。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询