☰
SQL基础教程:建表语法与完整性约束全解析
2026/10/14 11:10:55 网站建设 项目流程

简介:数据库系统概论第4章“关系数据库标准语言——SQL语言”讲稿的前半部分,适合高校数据库课程学习者、备考研究生及需要夯实SQL基础的开发者。整个压缩包仅含1个PPT文件,容量约428KB,轻量便携,兼顾移动端预览与课堂投影展示。课件从SQL概述切入,先解释SQL作为结构化查询语言的含义,再梳理Oracle、SQL Server、DB2等主流数据库对它的支持情况,并系统归纳SQL一体化、简捷易学、面向集合操作、高度非过程化、两种使用方式五大特点,逐一列出CREATE、DROP、ALTER、INSERT、UPDATE、DELETE、SELECT、GRANT、REVOKE这9个核心动词。随后进入数据定义部分,重点讲解CREATE TABLE建表语法、INTEGER、CHAR、VARCHAR、DATE等常见数据类型,以及主键、外键、非空、唯一、CHECK等完整性约束条件,并辅以职工表、部门表两个建表实例,直观展示关系模式从定义到约束的完整设计过程。目前已有100人学习下载,适合用于课前预习、课堂同步或考前系统复习。

1. 数据库系统概论里的关键一章:SQL语言学什么、怎么学

不少学数据库课程的人都有同一种感受:教材翻到第四章“关系数据库标准语言——SQL”,突然从理论开始上代码,节奏变了。这一章恰恰是整个数据库系统概论里最“保命”的内容,后面的事务管理、查询优化、数据库设计,全都建立在“你能否写出一张正确的表”之上。这份PPT正是把这一章的前半部分拆开了:SQL是什么、核心动词有哪些、CREATE TABLE怎么写、数据类型怎么选、五种完整性约束怎么用。适合三类人:正在跟教材走的学生,刚转做数据开发想补基础的从业者,以及准备面试前想快速过一遍SQL基础的人。

2. SQL语言是什么:九个动词、两种使用方式与面向集合的操作逻辑

2.1 从“结构化查询语言”到关系数据库的标准语言

SQL全称Structured Query Language,结构化查询语言,名字里有“查询”,但实际功能远不止查询。PPT里说得明确:SQL集数据定义、查询、更新和控制功能于一体,一个语言搞定数据库生命周期里的全部主要活动。这不是夸张,你建表、改表、删表、插数据、查数据、授权、回滚,全在SQL的范畴内。

从应用覆盖面看,Oracle、Sybase、Informix、Ingres、DB2、SQL Server这些大型数据库管理系统都完整实现了SQL语言;Dbase、Foxpro、Access这类PC端数据库则是部分实现。后者当年受限于文件型数据库架构,很多SQL标准功能支持不完整,这也是为什么你在Access里写SQL和Oracle里写SQL,体感差异很大。

还有一个容易被忽略的点:SQL可以嵌入HTML中,通过WWW访问数据库;也可以在VC、VB、Delphi、PB这类开发工具中嵌入SQL语句。这解释了为什么SQL这么多年没被淘汰——它不是某个数据库产品的私有语言,而是关系数据库的公共接口。Oracle搞的PL/SQL(Procedure Language and SQL)就是对SQL的过程化扩展,本质上还是在SQL内核外面包了一层编程能力。

对学习者的启示:你学的不是“Oracle的SQL”或“SQL Server的SQL”,而是关系数据库通用语言。换数据库时,80%的SQL知识能直接迁移,剩下20%是各家的方言差异和数据类型差异。

2.2 九个核心动词:一张表把SQL功能边界划清楚

PPT里给了一个很实用的记忆框架:SQL核心功能只用了9个动词。这是个很反直觉的事实——一门能完成数据库全生命周期操作的语言,核心关键词居然一只手数得过来。

SQL功能命令动词
数据定义CREATE、DROP、ALTER
数据操纵INSERT、UPDATE、DELETE
数据查询SELECT
数据控制GRANT、REVOKE

对照这个表,能看清自己处在学习的哪个阶段。数据定义对应建表、删表、改表结构;数据操纵对应增删改;数据查询只有SELECT一个词,但它的复杂度上限极高,嵌套查询、连接查询、分组聚合全挂在它名下;数据控制则是权限相关。

注意PPT后面的分类表里,数据控制一行写的是GRANT、REVOKE、COMMIT、ROLLBACK四个动词,与前文“九个动词”的说法略有出入。这个细节其实是教材口径差异:严格说COMMIT和ROLLBACK属于事务控制,不算SQL核心动词,但很多教材把它们归类在“数据控制”大范畴下。考试如果问到九大动词,以CREATE、DROP、ALTER、INSERT、UPDATE、DELETE、SELECT、GRANT、REVOKE为准;如果问SQL功能分类,则按四大类来。

2.3 五大特点:每一个都直接决定你写SQL的方式

SQL的五个特点,不是考试填空那么简单,它们直接解释了你写SQL时的每一个习惯。

一体化的语言:数据定义、查询、更新、控制集于一身,还要能完成合并、求差、相交、乘积、投影、选择、连接等所有关系运算。这意味着你不需要学第二门语言去操作同一个数据库。

语言简捷易学:接近英语口语或自然语言。这点新手体会最深——“SELECT name FROM emp WHERE sal > 5000”读起来就是一句英文句子,不需要额外的语法转换。

面向集合的操作方式:这条最反直觉,也最重要。SQL的增删改查操作对象是集合,一次INSERT可以插入多行,一次UPDATE可能改动多行,一次DELETE可能删掉一批记录。新手最容易在这里翻车:以为UPDATE只改一行,结果忘了加WHERE,整张表的数据全被改了。这种事故我从没见过哪本教材会当重点警告,但它就是SQL新手最常见的生产事故。

高度非过程化:你只需指明“做什么”,不需要告诉数据库“怎么做”。SELECT怎么写、表怎么连接、走哪个索引,由数据库优化器决定。好处是入门门槛低,坏处是排查性能问题时感觉像对着黑匣子——同样的SQL,数据量小的时候秒回,数据量大了就慢得离谱,因为执行计划变了。

同一种语法结构,两种使用方式:既可以作为交互式语言独立使用,也可以作为子语言嵌入宿主语言。而且两种方式语法结构一致。这意味着你在命令行里写的SQL,粘到Python或Java代码里,语义基本不变,这对工程实践是个巨大的友好设计。

3. 建表语法与数据类型:CHAR、VARCHAR2、NUMBER到底怎么选

3.1 CREATE TABLE的三段式结构:先看懂语法骨架

PPT里建表部分从基本表开始,语法原型如下:

CREATE TABLE <基本表名> ( <列名> <数据类型> [列级完整性约束条件], <列名> <数据类型> [列级完整性约束条件], ... [, 表级完整性约束条件] );

这个语法的核心是三个组成部分:表名、列定义、约束条件。表名和括号是必须写的;每一列必须有列名和数据类型;约束条件可选。注意中括号里的内容是可选项,方括号不是要写进去的符号。

拆开看:表名是这张表在数据库里的唯一标识;每列定义由“列名+数据类型+可选约束”组成;列级约束写在列定义内部,只作用于这一列。如果一个约束条件涉及多个属性列,比如复合主键、复合外键,就必须写到表级。

这一点在考试里常考:判断某个约束该写在列级还是表级,依据就是“是否涉及多列”。涉及两列及以上的约束,列级写不下,必须表级。

3.2 建表的命名规则与注意事项:30个字符、保留字、大小写

PPT列出的建表注意事项,每一条都来自真实报错经验,提前记住能少踩很多坑。

  • 表名或列名不得超过30个字符。
  • 第一个字符必须是字母,后面可以跟字母、数字、_、$、#三个特殊符号。
  • 表名或列名中不能包含空格。
  • 一个用户中表名要唯一,一个表中列名要唯一。
  • 表名和列名不区分大小写,但显示出来都是大写。
  • 保留字不能用作表名或列名。

最后一条是新手重灾区。SELECT、ORDER、GROUP、WHERE这些词被当成列名或表名,数据库直接报语法错误。解决办法是改名,或者用双引号把保留字括起来转义。但我的习惯是:命名时从源头避开保留字,比如给订单表起名orders而不是order,因为order是排序关键字,任何数据库里碰它都容易出问题。

3.3 数据类型选型:一个表把五类数据说清楚

PPT把数据类型分成数值、字符、位串、时间、布尔五类,建表时最常打交道的其实就前三类加一个日期。

分类类型说明建表建议
数值型INTEGER / INT整数类型计数、序号用
数值型SMALLINT短整数取值范围小的整数用
数值型NUMERIC(p, s)定点数,p为总有效位,s为小数位金额、单价用,必须给精度
数值型FLOAT(p)浮点数,p为精度科学计算类场景
数值型REAL浮点数,精度由执行机构确定对精度要求不高的场景
数值型DOUBLE PRECISION双精度浮点,精度由执行机构确定大范围浮点计算
字符型CHAR(n)定长字符串,n为固定长度定长编码如身份证号
字符型VARCHAR(n)可变长字符串,最大长度n名字、地址等长度不固定的文本
位串型BIT(n)二进制位串,长度n按位存储的标志字段
位串型BIT VARYING(n)可变长二进制位串位可变标志集合
时间型DATE日期,YYYY-MM-DD生日、下单日期
时间型TIME时间,HH:MM:SS打卡时间、日志时间
布尔型BOOLEANTRUE或FALSE是否生效、是否删除

几个选型经验:

CHAR和VARCHAR的选择。CHAR(n)是定长的,存“abc”和存“abc ”占的空间一样;VARCHAR(n)是变长的,按实际长度存。名字、地址、备注这类长度不定的用VARCHAR;固定长度编号,比如身份证号、手机号、学号,用CHAR。不要无脑全部VARCHAR,定长字段用定长类型,查询匹配效率更高。

NUMERIC(p,s)用于金额:p是总有效位数,s是小数位。NUMERIC(8,2)表示最多6位整数加2位小数。金额字段绝不用FLOAT或DOUBLE,浮点精度误差在金额场景是不可接受的,这是血泪教训。

VARCHAR2是Oracle特有的,它是VARCHAR的方言变体。标准SQL里只有VARCHAR,但这个PPT是Oracle风格的教学例子,所以出现多次varchar2。你在MySQL、SQL Server里建表时写VARCHAR就好,VARCHAR2在这些数据库里是语法错误。

3.4 两个建表示例逐行拆解:emp与dept

PPT给了两张表的完整建表语句。第一张是职工表:

CREATE TABLE emp ( eno NUMBER(10), ename VARCHAR2(10), dno VARCHAR(6), sex VARCHAR(2), birthday DATE );

第二张是部门表:

CREATE TABLE dept ( dno VARCHAR2(6), dname VARCHAR(8), loc VARCHAR(10) );

这两张表连着看更有意思:emp表的dno列指向dept表的dno列,这是典型的外键参照关系雏形。注意细节——emp表里dno用的是VARCHAR(6),dept表里dno用的是VARCHAR2(6)。VARCHAR和VARCHAR2在Oracle里行为不完全相同,混着用做外键容易出现类型不一致问题,后面避坑章会专门展开。

另外注意emp表里eno用了NUMBER(10),这是Oracle风格的数值类型写法,等价于标准SQL里的NUMERIC(10,0)——整数部分10位有效数字。如果你用的是MySQL或SQLite,改成INT或BIGINT更顺手,细节以目标数据库为准。

3.5 理解了语法就能看懂别人建的表

看懂建表语句是数据库从业者的基本技能。面试考SQL、接手老项目、写数据字典,第一步都是“读得懂别人写的CREATE TABLE”。语法骨架就那三段:表名、列定义、约束位置。拿到一张建表语句,先看表名和列名含义,再看每个列的类型和约束,最后看表级约束里有没有复合主键或复合外键。这套流程走完,表结构的主干就清楚了。

4. 完整性约束:主键、外键、CHECK怎么用才不翻车

4.1 三类完整性:实体、参照、用户定义

完整性约束不是SQL的可选装饰,它是关系数据库保证数据不出错的最后一道闸门。PPT把约束对应到三类完整性上:

主键约束(PRIMARY KEY)体现实体完整性。实体完整性要求表中的每一行都能被唯一识别,所以主键列的值既不能为空,也不能重复。空值代表“未知”,一个未知的主键无法唯一标识一行,自然不能允许。

外键约束(FOREIGN KEY)体现参照完整性。外键的取值要么是NULL,要么引用父表的主键值。这个约束保证子表里的引用不会“悬空”——不会出现某个员工的部门编号在部门表里根本不存在的情况。

属性约束体现用户定义的完整性,包括NOT NULL非空约束、UNIQUE唯一约束、CHECK检查约束。这三类约束共同把某一列的取值范围限制在业务规则允许的区间内。

理解这个分类的意义在于:约束不是随便加的,每一类约束解决的是不同层面的数据一致性问题。没有主键,表里可能出现两行完全一样的数据,查询结果直接失真;没有外键,脏引用会悄悄混进业务数据;没有CHECK,工资可能是负数,年龄能写到200岁。

4.2 五种约束的写法与生效范围:一张表记住规则

约束类型作用能否列级能否表级
PRIMARY KEY列值唯一且非空能能
FOREIGN KEY取值参照父表主键能能
NOT NULL列值不允许为空能不能
UNIQUE列值不允许重复能能
CHECK限制列值范围能能

注意这个表里唯一不对称的一项:NOT NULL只能作为列级约束。逻辑也好理解——非空约束天然是针对某一列的属性,它没法描述“这一组列都不为空”这样的复合条件,所以语法上不允许它出现在表级位置。其他四种约束都可以升降级,而有没有“多列参与”是选择级别的判断依据。检查约束多用于数值范围,比如工资必须在1000到10000之间,就写CHECK(sal BETWEEN 1000 AND 10000)。

4.3 列级约束与表级约束:复合主键场景下的分水岭

先看列级约束的完整写法。PPT里的emp表带全约束是这样:

CREATE TABLE emp ( eno NUMBER(6) PRIMARY KEY, ename VARCHAR2(10) UNIQUE, sex VARCHAR2(3) NOT NULL, dno VARCHAR2(10) REFERENCES dept(dno), sal NUMBER(6) CHECK(sal > 1000 AND sal <= 10000) );

逐行拆:eno是主键,不能为空且不能重复;ename不允许重复,但允许NULL——注意UNIQUE和PRIMARY KEY的区别,前者允许空值,后者不允许;sex不能为空,性别字段必须填;dno参照dept表的dno列,这是列级外键;sal的取值被限制在1000到10000之间,用AND连接两个条件,闭区间。

再看表级写法:

CREATE TABLE emp ( eno NUMBER(6), ename VARCHAR2(10), sex VARCHAR2(3) NOT NULL, dno VARCHAR2(10), sal NUMBER(6), PRIMARY KEY(eno), UNIQUE(ename), FOREIGN KEY(dno) REFERENCES dept(dno), CHECK(sal BETWEEN 1000 AND 10000) );

功能上这张表和上一张等价,但写法上把约束集中到了表定义末尾。列级写法更紧凑直观,表级写法便于统一查看约束清单。实际项目里怎么选?我的习惯是:单列约束跟着列走,写列级,可读性好;涉及多列或习惯集中管理约束的表,统一写表级,维护起来一目了然。

什么时候必须表级?当主键或外键由多个列组成时。比如订单明细表,主键是“订单号+行号”复合主键,就必须写成PRIMARY KEY(order_no, line_no)放在表级,单个列都不满足唯一性。

4.4 Student表完整示例:五种约束一次写全

PPT最后给了一个综合示例,把五种约束全部放进一张表:

CREATE TABLE Student ( Sno CHAR(8) PRIMARY KEY, /* 主键约束 */ Sname CHAR(10) UNIQUE, /* 唯一约束 */ Sex CHAR(3) NOT NULL, /* 非空约束 */ Age INT CHECK(Age > 16), /* 检查约束 */ Dept VARCHAR(15) );

逐段解释:Sno是学号,定长8位,作主键,约束最严格;Sname是姓名,唯一约束保证不重名;Sex性别不能为空;Age年龄要求必须大于16;Dept院系列没有约束,允许为空也允许重复。这张表是典型的课堂示范,用最简单的场景覆盖全部五种约束,考试里类似题目出现的概率很高。

一个容易被忽略的点:UNIQUE约束和PRIMARY KEY的区别。主键隐含非空和唯一两个性质,唯一约束只保证不重复、不保证不为空。换句话说,UNIQUE列可以有多行NULL,主键列一行NULL都不能有。

5. 避坑记录:建表约束最常见的五个翻车现场

5.1 VARCHAR和VARCHAR2混用导致外键建不上

现象:照抄PPT里的emp和dept建表,发现emp表里的dno列建外键时直接报错,提示找不到父表列或数据类型不一致。

原因:PPT的emp表里dno写的是VARCHAR(6),dept表里dno写的是VARCHAR2(6)。这两个类型在Oracle里语义不同:VARCHAR是标准SQL类型,VARCHAR2是Oracle的私有类型,长度语义、存储行为都有差别。外键要求子表列和父表列的数据类型必须完全匹配,混用就是匹配不上。

解决:统一类型。以目标数据库为准,Oracle里统一用VARCHAR2,MySQL和SQLite里统一用VARCHAR。建表之前先把外键关联列的字段类型对着看一遍,别想当然以为“都是字符串就行”。

5.2 把NOT NULL写进表级约束,语法直接报错

现象:按表级约束的格式把NOT NULL挪到约束区,像PRIMARY KEY(eno)那样写NOT NULL(sex),数据库报语法错误。

原因:非空约束只能作为列级约束,不能作为表级约束。这不是某个数据库的差异,是标准SQL的语法限制。PPT里明确写了,“非空约束不可以作为表级完整性约束条件”,但实操中总有人犯这个错。

解决:NOT NULL必须紧跟列定义写,比如sex VARCHAR2(3) NOT NULL。它描述的是单列属性,语法上不属于表级约束的范畴。

5.3 CHECK约束在部分数据库里被静默忽略

现象:建表时写了CHECK(sal > 1000),插入一条sal为500的数据,竟然成功了,没有任何报错。

原因:MySQL在8.0版本之前,解析到CHECK约束直接忽略,不报错也不生效。SQLite在3.3.0之前对CHECK的支持也不完整。如果教学演示用的老版本数据库,CHECK约束就等于形同虚设。

解决:先确认目标数据库的版本和文档。MySQL 8.0及以上才真正执行CHECK约束;更早版本里要限制取值范围,只能靠应用层校验或使用触发器。写CHECK之前,先验证数据库确实支持并在执行,否则这个约束就是心理安慰。

5.4 删除父表时被外键卡住,一直报删除失败

现象:删dept部门表,数据库报错,提示有外键约束依赖,删不掉。

原因:emp表里有外键参照dept(dno),数据库为了保住参照完整性,不允许直接删除被引用的父表。

解决:先删子表再删父表;或者用DROP TABLE dept CASCADE CONSTRAINTS,把依赖该表的外键约束一并删掉再删表。生产环境里对CASCADE要谨慎,它会静默删掉多个相关联的约束,影响范围比想象中大。我一般会先查依赖关系,再决定怎么删。

5.5 表名用了保留字,建表语句反复报错

现象:建一张订单表,名字叫order,执行CREATE TABLE order(...),数据库报语法错误,检查了好几遍SQL都没发现问题。

原因:order是SQL的排序关键字,属于保留字,不能直接用作表名。类似的还有select、group、where、user这些高危词汇,单看都像正常的业务名词,但在SQL里全是保留字。

解决:改表名,比如orders、t_order、order_info;或者用双引号把保留字括起来,order变成“order”,数据库会把它当普通标识符处理。但我的经验是改名比转义省心——转义写法在后续每个引用点都要加引号,忘一次就报一次错,后患无穷。

6. 把讲义里的例子跑起来:从Student表开始的验证路线

6.1 用SQLite把Student表重建一遍

没有Oracle环境也能验证这张表。SQLite轻量免安装,语法上与标准SQL兼容度高,最适合做课堂练习:

CREATE TABLE Student ( Sno CHAR(8) PRIMARY KEY, Sname CHAR(10) UNIQUE, Sex CHAR(3) NOT NULL, Age INT CHECK(Age > 16), Dept VARCHAR(15) );

注意SQLite对INTEGER PRIMARY KEY有特殊行为,但这里Sno是CHAR类型主键,不受影响。建表成功后,用. schema Student命令能看到表结构,确认每条约束都已生效。

6.2 验证约束是否真的在拦截错误数据

表建好后,手动喂几条违反约束的数据,看数据库的报错反应:

INSERT INTO Student(Sno, Sname, Sex, Age, Dept) VALUES ('20230001', '张三', '男', 18, 'CS'); INSERT INTO Student(Sno, Sname, Sex, Age, Dept) VALUES ('20230001', '李四', '男', 20, 'CS');

第二条Sno重复,会触发主键冲突报错。再试一条年龄小于16的,CHECK约束会抛异常。有些数据库里主键冲突会回滚整个事务,插入前先确认表里没有同主键数据,这也是排查拿到奇怪错误时最先该怀疑的方向。

6.3 补上DML操作:把集合操作的体感练出来

建表之后,顺势验证数据操纵:

UPDATE Student SET Age = Age + 1 WHERE Sno = '20230001'; DELETE FROM Student WHERE Dept = 'CS'; INSERT INTO Student(Sno, Sname, Sex, Age, Dept) VALUES ('20230002', '王五', '女', 19, 'IS');

这三句分别对应UPDATE、DELETE、INSERT三个核心动词。执行时注意UPDATE没写WHERE会更新全表,DELETE没写WHERE会清空全表——集合操作的优势是一句话处理一批数据,风险也是一句话误伤整批数据。每条语句执行完,用SELECT确认影响行数,这是个值得坚持的好习惯。

这套验证走完,第四章前半部分的建表和约束内容就串起来了。后来我每次在新环境里建表都强制自己过一遍检查清单:主键有没有,外键类型是否完全一致,CHECK有没有被数据库静默忽略,保留字有没有混进命名。这套动作帮我少踩了很多坑,希望帮到你。

本文还有配套的精品资源,点击获取

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

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

立即咨询