☰
SQL Server入门:从表、约束、索引到范式与事务日志
2026/10/27 11:38:13 网站建设 项目流程

简介:这份 SQL Server 学习笔记以单份 doc 文档呈现,面向数据库初学者、运维与开发人员,也适合备考或查漏补缺的技术人员,用于快速建立关系型数据库的整体知识框架。内容围绕建库建表、数据库对象、关系模型、授权管理与 T-SQL 语句展开,覆盖 Create/Drop/Alter、主键外键与默认值约束、系统数据库作用、数据文件与日志文件存储、视图创建等知识点,并整理数据类型、实体属性码域等概念,便于按条目复习和对照实践。压缩包共 1 个文件,为 doc 格式,体积约 499KB,轻量易携带,可直接检索关键词做速查。相关页面显示已有 440 人学习,说明其在入门梳理场景中具有一定参考价值。读者可借笔记快速串联 SQL Server 的核心术语、对象限制与建表约束,形成可复用的学习提纲,并为后续实验和面试复习提供索引。

1. 从一张越改越乱的表格说起:SQL Server 到底是什么

几乎每个做过小项目的人都经历过这样的场面:一份记录订单的表格文件,两三个人轮流打开、改完再发回来,文件名从「订单」变成「订单-最终」再变成「订单-最终-真的最终」。几百行的时候它很听话,几千行开始卡顿,两个人同时打开就互相覆盖,某次不小心点了「不保存」,一下午的东西全没了。

走到这一步,你才会真正需要 SQL Server。

说得直白一点,SQL Server 是一套关系型数据库管理系统:数据按「表」来组织,用一套叫 SQL 的语言来存取,由一个常驻后台的服务统一管理谁能看、谁能改、断电之后怎么恢复。那份流传的 SQL Server 学习笔记,把建库建表、约束、视图、索引、存储过程这些零散知识点串成了一条线。值得花时间搞懂,是因为它决定了你写出来的 SQL 是「碰巧能跑」,还是「换一批数据也不出事」——这两件事在练手时看不出差别,上线之后差别巨大。

2. 为什么不用文件存数据:三个人同时改表引发的三个问题

先别急着背语法。搞清楚「为什么需要数据库」,比背下CREATE TABLE的十个参数更有用,因为后面所有设计上的讲究——约束、日志、锁、权限——都不是凭空发明出来的规则,而是三个具体麻烦逼出来的答案:多人同时改、改到一半出事、有人不该看却看到了。

2.1 并发:32767 个连接不是给你一个人用的

共享文件夹里的表格,本质上是「整份文件」级别的读写。A 打开、B 打开,A 改完保存、B 改完保存,后保存的那个把前一个人的改动整体盖掉了。数据库把这套逻辑拆开了:它不是一个文件,而是一个常驻的服务进程,客户端只发请求、拿结果,真正的读写由服务端统一排队执行。这就是笔记里记的 C/S 体系——客户端/服务器架构。

拆开之后的好处是「粒度」变细了。改一行只锁一行,别人改别的行不受影响。笔记里记了两个数字:一个实例最多支持 32767 个用户连接,可同时管理的锁定及打开对象上限到 20 亿个。这两个数字不是让你去接近它,而是说明它的设计前提从一开始就是「很多人同时用」,不是「一个人独占」。

提示:连接数不是越多越好。每个连接都占内存,几百个连接常年挂着不释放,服务器会先被自己拖垮,而不是被业务量拖垮。

2.2 断电:没有日志文件,前面三小时白干

第二个麻烦更常见。假设一次操作要改两处:商品表里的库存减 1,拍卖记录表里新增一条出价。如果第一句执行完、第二句还没执行,机器断电了,数据就变成「库存少了,但没人出价」——账对不上。

数据库的解法是「日志先行」。任何一次修改,先把「我要改什么」写进日志文件(扩展名.ldf),再动真正的数据文件。中途出事,重启时按日志把没做完的操作回滚、做完但没落盘的操作重放,数据回到一个确定的状态。笔记里那句「事务日志就是一个不可分割的数据库操作的日志记录」,说的就是这件事:一组操作要么全成,要么全不成。

用记账打比方会更清楚。数据文件像账本上最终写下的余额,日志文件像流水账。余额可以算错、可以被人误改,但只要流水账还在,就能一笔一笔倒推回正确的余额。所以日志文件通常比数据文件还重要,删数据文件是事故,删日志文件往往也是事故。

2.3 谁能改哪一行:授权、角色与四种完整性

第三个麻烦是「权限」。表格文件发给谁,谁就能改全部,包括把表头删掉。数据库把权限拆成了三层:登录(能不能进这个服务器)、用户(进服务器后对应哪个库的身份)、角色(这个身份能干什么)。笔记里记的三条命令正好对应这三层。

-- 建登录:登录名、密码、默认库、默认语言 EXEC sp_addlogin 'clerk_a', 'P@ssw0rd', 'shopdb', '简体中文'; -- 建用户:登录名、库内用户名、所属角色 EXEC sp_adduser 'clerk_a', 'user_a', 'sales_role'; -- 建角色:角色名、角色拥有者 EXEC sp_addrole 'sales_role', 'dbo'; -- 回收与授予 REVOKE UPDATE ON goods FROM user_a; GRANT SELECT ON goods TO user_a;

逐行看:sp_addlogin的第一个参数是登录名,第二个是密码,第三个是登录后默认进的库,第四个是默认语言;sp_adduser把某个登录映射成库里的用户,第三个参数让它自动成为某个角色的成员;sp_addrole建一个角色,第二个参数是角色的拥有者。最后两句GRANT和REVOKE才是真正决定「能读还是能改」的开关。

权限之外还有一层「数据本身对不对」,笔记里归成四类完整性:

完整性类型管的是谁典型手段通俗解释
域完整性一列的值default、check性别这一列不能填「香蕉」
实体完整性一行是否唯一主键、唯一约束同一笔订单不能出现两次
参照完整性两张表的关系外键出价记录里的商品,商品表里必须真有
用户自定义完整性业务规则check、规则、触发器出价必须大于 0,且不能低于起拍价

这四类里,前两类是「自己管好自己」,第三类是「表和表之间别打架」,第四类是「业务上的规矩」。初学者最容易只做第一类,把「不能为空」写上就觉得万事大吉,结果外键没建,删商品的时候留下一堆指向空气的出价记录。

2.4 那些看起来像天书的规格数字,其实在划定边界

笔记里有一串数字,第一次看像天书:20 亿个表、8060 个字符、1024 列、1 个簇索引、249 个非簇索引、每个存储过程 1024 个参数和 32 级嵌套。这些数字的正确用法不是背下来,而是理解它们在说什么——它们是「天花板」,告诉你设计时大概的量级在哪,而不是让你去顶到天花板。

项目笔记里的上限实际含义
每个库的表数量20 亿表多到这个量级,问题早就不是数据库,而是命名和管理
一行总宽度8060 字符单行装不下太多长文本,超长内容要拆表或换类型
每表列数1024列数过百就该怀疑表设计,而不是继续加列
每表索引1 个簇索引 + 249 个非簇索引索引不是免费午餐,每个都拖慢写入
每表触发器笔记记的是 3 个(INSERT/UPDATE/DELETE)这是它所在版本的规则,实际以手头版本为准
存储过程1024 个参数、32 级嵌套参数上百个说明该拆成多个过程了
用户连接32767上限,不是目标值
单库大小1MB 到 1TB旧版本的限制,现在早已放开,但规划思路一样

同一份笔记里还记了它能对接什么:ODBC、VB、VC、Access 这些编程接口,对 Web 分析的支持,数据仓库功能,XML 支持,以及分布式分区视图和分布式管理框架。这串清单的意义在于——它说明数据库很少单独存在,它总是被别的程序调用。你写的每一条 SQL,最终都是被某个客户端程序发过来的,所以「表怎么设计」和「程序怎么查」必须一起考虑。

3. 一个数据库里到底装了什么:从磁盘文件到视图的四层结构

理解了「为什么」,接下来要建立一张空间地图:一个数据库在磁盘上长什么样、里面有哪些系统自带的库、表之上还能不能再套一层、以及为什么加了索引就变快。这四件事搞不清,写 SQL 就永远是在猜。

3.1 一个数据库在磁盘上是三个文件:.mdf、.ndf、.ldf

笔记里写得很清楚:数据库的存储被映射成几个操作系统文件,分三类。

主数据文件,扩展名.mdf,一个数据库有且只有一个。它除了存数据,还存这个数据库的启动信息——换句话说,它没了,这个库就打不开了。次要数据文件,扩展名.ndf,可以有零个也可以有很多个,作用是「主文件装不下的部分接着装」,典型场景是数据要分散到多块磁盘上,靠多个文件分摊读写压力。日志文件,扩展名.ldf,存的是事务日志,前面讲过,它是恢复的依据。

再往上一层是文件组。文件组不是文件,是「一组文件的集合」,用来做分配和管理的单元。打个比方:文件是抽屉,文件组是柜子,建表的时候你指定「这张表放哪个柜子」,而不是「放哪个抽屉」。这样做的好处是备份、迁移、扩容时可以整组操作,不用一个个文件去点名。

注意:主数据文件和日志文件尽量不要放在同一块物理盘上。日志是顺序写、数据是随机写,混在一起互相拖累,而且盘一坏两个一起没。

3.2 系统数据库:master 挂了,整个实例都起不来

每个实例建好之后,都自带几个系统库。它们不是你建的,但你必须知道它们是干什么的,因为出问题时最先要看的就是它们。

master存的是「主数据」:登录账号、其他数据库的清单、服务器级别的全部配置。这个库的特殊之处在于——它要是坏了,整个实例都启动不了,其他库再好也白搭。model是一个模板库,每次你执行CREATE DATABASE,新库都是照着它的样子复制出来的,所以想让所有新库天生带某张表、某个排序规则,改model就行。tempdb存临时表和临时结果,连接一断、实例一重启就清空,它是整个实例共享的,所以特别容易被某个写得很烂的查询拖慢,进而拖慢所有人。msdb存的是调度作业、警报、以及接收警报的操作员信息,笔记里记它默认 12MB——这个数字在不同版本里会变,但它装的东西没变。

此外还有两个样例库,是给初学者练手用的,里面预置了表和数据。它们的价值在于:你可以在不破坏任何真实数据的前提下,把SELECT、JOIN、视图、存储过程全试一遍。

3.3 视图:给数据加一层滤镜,但这层滤镜会漏

视图的本质是「一条被存下来的查询」。它不存数据,只存 SQL,你查视图的时候,数据库把这条 SQL 展开去查底下的基本表。所以视图看起来像表,实际上是一层滤镜。

-- 只暴露两列,并强制后续的插入/修改必须满足“电子产品”这个条件 CREATE VIEW goods_elec_view AS SELECT goods_name, goods_type_name FROM goods WHERE goods_type_name = '电子产品' WITH CHECK OPTION;

这条语句里,CREATE VIEW后面跟的是视图名,AS后面是查询表达式,WITH CHECK OPTION是关键:它规定通过这个视图做插入或修改时,改完的结果必须仍然满足WHERE goods_type_name = '电子产品',否则直接拒绝。没有这句,你完全可能通过这个「只看电子产品」的视图,插进去一条「办公用品」,然后这条数据在视图里再也查不到——像往抽屉里塞了东西,但抽屉的入口写着「只放 A 类」,塞进去的 B 类从此消失。

笔记里还记了另外三个选项:WITH ENCRYPTION把视图的定义文本加密,别人看不到你写了什么;WITH SCHEMABINDING把视图绑到基本表的结构上,防止有人把视图依赖的列删掉;WITH VIEW_METADATA让客户端在浏览元数据时看到的是视图名而不是底层的基表名。

定义视图的查询本身也有约束:不能含INTO、ORDER BY、COMPUTE、COMPUTE BY这些关键字,不能引用临时表或表变量。而「可更新视图」的条件更严——FROM子句至少要引用一个真实的表,选择列表里不能有派生列,不能有聚合函数,也不能出现TOP、GROUP BY、UNION、DISTINCT。满足不了这些条件,视图就只能查、不能改。

3.4 索引:为什么簇索引一个表只能有一个

索引是一棵由关键字组成的树状结构,建立它的唯一目的是加速检索。笔记里对两种索引的区分讲得很到位,值得展开。

簇索引决定的是「表里数据的物理排列顺序」。你按goods_id建了簇索引,那这张表在磁盘上就真的按goods_id从小到大排。既然一份数据只能有一种物理顺序,一个表自然只能有一个簇索引——这是物理定律,不是产品限制。好处是范围查询极快,因为相邻的值就存在相邻的位置。非簇索引是另一套完全独立的结构:它自己排好序,每个条目里存一个「指针」,指向数据真正所在的位置。查的时候先在索引里找到位置,再跳过去取数据。它不改变表的物理顺序,所以可以建很多个,笔记里记的是每表 249 个、每个最多 16 列。

-- 唯一簇索引:整张表按 goods_id 的物理顺序排,一表只能有一个 CREATE UNIQUE CLUSTERED INDEX idx_goods_id ON goods_1 (goods_id ASC); -- 复合非簇索引:先按 goods_id 排,再按 goods_type_id 排 CREATE INDEX idx_goods_type ON goods_1 (goods_id ASC, goods_type_id DESC);

第一句里,UNIQUE表示索引值不允许重复,CLUSTERED表示这是簇索引,ON后面是表名和列名,ASC是升序。第二句省掉了UNIQUE和CLUSTERED,默认就是非簇索引,两列的顺序很关键:先goods_id后goods_type_id,意味着只按goods_id查也能用上这个索引,但只按goods_type_id查就用不上——这叫最左前缀,是最容易踩的坑之一。

至于什么时候该建索引,笔记列了四条,基本覆盖了九成场景:经常出现在搜索条件里的列、经常用来排序的列、主键和外键所在的列、经常出现在WHERE里的列。反过来说,如果一个表几乎只做批量导入、极少查询,那索引反而是负担,因为每次插入都要维护这棵树。

4. 关系的骨架:码、约束与范式到底在管什么

前面三章讲的是「有什么」,这一章讲「怎么才算设计对了」。数据库这门学问里最抽象的一批词——实体、属性、码、域、范式——其实都在回答同一个问题:一张表里到底应该放哪些列,凭什么这么放。

4.1 实体、属性、码、域:五个词撑起概念模型

先从一组具体的例子切入。要描述「学生」这件事,你会想到:一个具体的学生(实体)、他有姓名性别(属性)、他的学号能唯一确定他(码)、性别只能取男或女(域)。这四个词就是概念模型的基本砖块。

再往下细分:把「学生」这个类别抽象出来,写成「学生(学号、姓名、性别、年龄)」,这叫实体型——用实体名加属性集合来描述一类事物;全体学生这个集合,叫实体集;学生和课程之间的关系,叫联系。这一整套东西是给人看的,不涉及任何具体数据库产品,所以叫概念模型。

落到实际建表时,词汇会换一套皮:

概念模型里的说法关系模型里的说法具体到一张表
实体型关系模式表结构(表名 + 列定义)
实体集关系整张表
一个实体元组一行
属性属性一列
码主码唯一标识一行的那一列或几列
域域这一列允许取值的范围
属性值分量一行里某一格的值

两套词说的是同一件事,只是抽象层级不同。面试或考试爱考这组对应,实际工作里没人这么说,但你只要记住「关系 = 表、元组 = 行、属性 = 列、分量 = 一格」,看文档就不会卡住。

这里还有个容易忽略的定义:候选码是「能唯一标识一行」的属性组,可以有多个;主码是从候选码里挑出来的那一个;不包含在任何候选码里的属性叫非主属性。这几个词后面讲范式时还要用。

4.2 五种约束:把脏数据挡在表门口

约束是数据库层面强制执行的规定。它的价值在于:不管数据是从程序进来的、从 Excel 导进来的、还是有人直接敲 SQL 塞进来的,只要不满足约束,一律拒绝。把校验写在程序里,换个入口就漏了;写在数据库里,谁也绕不过去。

CREATE TABLE bid_record ( bid_user VARCHAR(10) NOT NULL, -- 出价人编号 bid_goods VARCHAR(10) NOT NULL, -- 商品编号 bid_number INT DEFAULT 1, -- 没填时默认为 1 件 bid_price MONEY CHECK (bid_price > 0), -- 出价必须为正数 bid_date DATETIME NOT NULL, CONSTRAINT pk_bid PRIMARY KEY (bid_user, bid_goods), -- 主键:两列联合 CONSTRAINT uk_bid UNIQUE (bid_user, bid_goods, bid_date), -- 唯一:防重复出价 CONSTRAINT fk_bid FOREIGN KEY (bid_goods) REFERENCES goods_1(goods_id) );

五种约束在这段里全用上了。主键约束PRIMARY KEY保证每行可区分,且主键列不能为空;唯一约束UNIQUE保证这一列(或组合)不重复,和主键的区别是它允许一个空值、且一个表可以有多个;外键约束FOREIGN KEY ... REFERENCES保证bid_goods里出现的值,在goods_1里必须存在;默认值约束DEFAULT在插入时没给这一列就自动填上;检查约束CHECK限定取值范围,超出就拒绝。

除了约束,笔记里还记了两种「老办法」:默认对象和规则。默认对象用CREATE DEFAULT建一个独立对象,再用sp_bindefault绑到某列上;规则也是独立的、可复用的校验逻辑,绑到列上生效。它们和约束的效果类似,但管理方式不同——约束跟着表走,删表就没了;默认对象和规则是独立对象,可以绑到多张表多列上。新项目一律用约束,老代码里看到sp_bindefault不用慌,它就是「给这一列挂个默认值」。

4.3 三大范式:拆表拆到什么程度算够

范式是「一张表该拆到什么程度」的参考答案。它一共分几层,每一层都在解决上一层的某个具体毛病。

第一范式要求每个分量不可再分。反例很好懂:商品表里有一列叫「所属类别」,里面塞着「生活用品,电子产品,办公用品」。你想查「生活用品」的商品编号,用等号查不到,用LIKE又慢又容易误伤——因为这一列不是原子值。解决办法有两个:拆成多列(goods_type_1、goods_type_2……),或者拆成多行,一行一个类别。

-- 违反第一范式:一列里塞了多个值 CREATE TABLE goods_bad ( goods_id VARCHAR(10), goods_type VARCHAR(50) -- 值是 '生活用品,电子产品,办公用品' ); -- 违反第二范式:联合主键 (user_id, goods_id),但商品名只依赖 goods_id CREATE TABLE buy_info_bad ( user_id VARCHAR(10), goods_id VARCHAR(10), goods_name VARCHAR(50), -- 只跟 goods_id 走,属于部分依赖 PRIMARY KEY (user_id, goods_id) );

第二范式要求:在满足第一范式的前提下,每个非主属性必须完全依赖于码,不能只依赖码的一部分。上面第二张表就是典型:主键是「用户 + 商品」的组合,但goods_name只跟goods_id有关,跟user_id没关系。后果是同一个商品被一千个人买,商品名就要存一千遍,改一次名字要改一千行——漏改一行,数据就自相矛盾。解法是把商品名挪回商品表,这张表只留「谁买了哪个」。

第三范式再上一层:非主属性不能传递依赖于码。比如订单表里有「商品编号」和「商品类别」,而商品类别其实是由商品编号决定的,这就是订单号 → 商品编号 → 商品类别的传递链。它同样导致冗余,同样该拆。BCNF 是第三范式的一个更严格的修正版,处理的是「码本身由多个属性组成、且其中有函数依赖」的少数特殊情况,实际建表时按前三层走,九成场景已经够了。

注意:范式是「减少冗余」的参考答案,不是法律。为了查询性能,实际项目里经常故意违反第三范式,把一些字段冗余存一份,避免每次查询都去连好几张表。这种「反范式」是有意识的取舍,而不是不懂范式。

5. 常见误区与易混概念:五组差之毫厘的说法

学到这里,名词已经攒了一堆,真正让人翻车的往往不是不会写,而是把两个长得很像的东西当成了一回事。下面五组是初学者最容易混的,每一组都按「哪里像、为什么混、怎么分」来说。

5.1 主码、候选码、外码:三个「码」不是一回事

易混点:三个词都带「码」,都跟「唯一标识」沾边。

为什么混:候选码和主码确实是一回事的两个阶段——候选码是「有资格当主码的」,主码是「被选中的那个」。而外码压根不是用来标识自己的,它是用来指向别人的。

怎么区分:候选码是「能唯一确定一行」的属性组,一个表可以有多个,比如学号能定,身份证号也能定;主码是从中挑一个当门面,一个表只能有一个;外码是「这一列的值,必须是另一张表的主码值」,它的作用是建立两张表之间的引用关系。一句话记:主码和候选码管自己,外码管别人。

5.2 簇索引和非簇索引:一个改物理顺序,一个只加目录

易混点:都叫索引,都能加速查询,语法只差一个CLUSTERED关键字。

为什么混:因为建完之后查数据都变快了,肉眼看不出区别。

怎么区分:簇索引改变表的物理存储顺序,数据本身就是按索引键排好的,所以一个表只能有一个;非簇索引不改物理顺序,它是另建的一套目录,条目里存指向真实位置的指针,所以可以有多个。查簇索引像查一本按学号排好的花名册,翻到那一页就是;查非簇索引像查书后面的索引页,先找到页码,再翻过去。推论是:簇索引适合范围查询和排序,非簇索引适合精确查找,而且非簇索引查完还要「翻过去」一次,代价更高。

5.3 视图、存储过程、触发器:都存了 SQL,但触发方式完全不同

易混点:三者都是「把一段 SQL 存起来」,都要CREATE。

为什么混:因为它们确实都保存在数据库里,也确实都包含 SQL 语句。

怎么区分:视图是「存下来的查询」,你主动去SELECT它,它才展开执行,本质是一层滤镜;存储过程是「存下来的操作流程」,可以带参数、可以有分支、可以增删改,你主动EXECUTE它才跑;触发器是「挂在表上的自动响应」,你不主动调它,是在对表做INSERT、UPDATE、DELETE时被自动触发。一句话记:视图要你查它,存储过程要你叫它,触发器你根本没叫它,它自己来。

5.4 delete、drop、alter:删数据、删对象、改结构

易混点:都跟「删除或修改」有关,命令都短。

为什么混:很多教程把它们放在同一章「表的操作」里,一口气讲完。

怎么区分:DELETE删的是表里的行,表还在,结构还在,可以加WHERE只删一部分,删了还能靠日志恢复;DROP删的是整个对象,表、视图、索引、约束都能DROP,删完对象就没了,结构也没了;ALTER不删东西,它改结构,加列、删列、改数据类型、加约束、开闭约束都靠它。有个细节值得记:想删一列时,如果这列上挂着约束,得先ALTER TABLE ... DROP CONSTRAINT把约束摘掉,再DROP COLUMN,直接删会报错。

5.5 域完整性、实体完整性、参照完整性:管的东西根本不是一个层级

易混点:三个词都叫「完整性」,都跟「保证数据正确」有关。

为什么混:它们并列出现在同一节里,看起来是同一件事的三种说法。

怎么区分:域完整性管「一列的值合不合法」,对应DEFAULT和CHECK;实体完整性管「这一行有没有唯一身份」,对应主键和唯一约束;参照完整性管「两张表之间的引用对不对得上」,对应外键。它们不是三选一,而是三层,一张设计良好的表通常三个都要满足。还有第四类「用户自定义完整性」,是业务规矩(比如出价不能低于起拍价),可以用CHECK、规则或触发器实现。

6. 什么时候该用、什么时候别用:一份判断清单

把上面这些串起来,其实可以归纳成一个非常实用的判断流程。拿到一个需求,先问三个问题:数据会不会被多人同时改?改错或改一半出事要不要能恢复?不同的人要不要看到不同的数据?三个里有一个答「是」,就该上数据库;三个都答「否」,一个几万行的本地表格文件反而更省事。

具体一点,可以对照这张表:

场景建议原因
两三个人以上共同维护同一批数据用行级锁和权限能避免互相覆盖
数据修改不能出错,出错要能倒回去用事务加日志,能回滚到确定状态
需要按不同角色限制可见范围用登录、用户、角色三层权限
数据结构会反复变,且要保证历史数据不脏用约束在库层面强制执行,改程序绕不过去
一个人离线记几百条笔记别用装服务、配权限、写备份的工夫远超收益
纯做批量统计,数据一次性导入后不再变谨慎建索引反而拖慢导入,可考虑先导入后建索引
数据量在几万行以内、只有一个写入方谨慎文件或轻量方案够用,迁移成本不必提前付

需要「谨慎」的那两种,不是说数据库不好,而是说引入它要为运维付代价:备份策略、日志空间、磁盘规划、版本升级,这些是持续成本,不会因为你只建了两张表就消失。给人推荐数据库之前,先想清楚对方有没有人负责这摊事。

还有个更细的边界:同一个库里,不是所有表都值得上全套约束和索引。日志表、临时中间表这类「写完就很少查」的表,索引越少越好;而主数据表、被外键频繁引用的表,约束一个都不能省。我在一个模拟项目里就吃过这个亏——为了图快,把一张配置表的唯一约束去掉了,结果同一个配置项被插了两条,程序读的时候随机命中其中一条,表现成「有时候对有时候错」,查了整整两天才定位到。从那以后我每建一张表,都强制自己先回答三个问题:这张表的码是什么、这张表允许出现重复行吗、删掉一行会不会让别的表指向空气。三个问题答不上来的表,先别急着CREATE。

数据库这门东西,语法查手册十分钟就能会,难的是「这张表为什么这么设计」的判断力。那份 SQL Server 学习笔记的价值,不在于它列了多少条命令,而在于它把从建库、建表、约束、视图、索引到存储过程这条线完整走了一遍——走完一遍,你再看任何一个业务系统的表结构,都能大致猜出它当初在防什么。希望帮到你。

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

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

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

立即咨询