第1章 引言 1
1.1谁需要这本书 2
1.2本书内容 2
1.2.1本书结构 3
1.2.2反模式分解 4
1.3本书未涉及的内容 4
1.4规约 5
1.5范例数据库 6
1.6致谢 8
第一部分 逻辑型数据库设计反模式 10
第2章 乱穿马路 10
2.1目标:存储多值属性 11
2.2反模式:格式化的逗号分隔列表 11
2.2.1查询指定账号的产品 11
2.2.2查询指定产品的账号 12
2.2.3执行聚合查询 12
2.2.4更新指定产品的账号 12
2.2.5验证产品ID 13
2.2.6选择合适的分隔符 13
2.2.7列表长度限制 13
2.3如何识别反模式 14
2.4合理使用反模式 14
2.5解决方案:创建一张交叉表 14
2.5.1通过账号查询产品和反过来查询 15
2.5.2执行聚合查询 16
2.5.3更新指定产品的相关联系人 16
2.5.4验证产品ID 16
2.5.5选择分隔符 17
2.5.6列表长度限制 17
2.5.7其他使用交叉表的好处 17
第3章 单纯的树 18
3.1目标:分层存储与查询 18
3.2反模式:总是依赖父节点 19
3.2.1使用邻接表查询树 20
3.2.2使用邻接表维护树 21
3.3如何识别反模式 22
3.4合理使用反模式 23
3.5解决方案:使用其他树模型 24
3.5.1路径枚举 24
3.5.2嵌套集 26
3.5.3闭包表 29
3.5.4你该使用哪种设计 33
第4章 需要ID 34
4.1目标:建立主键规范 35
4.2反模式:以不变应万变 36
4.2.1冗余键值 36
4.2.2允许重复项 37
4.2.3意义不明的关键字 38
4.2.4使用USING关键字 38
4.2.5使用组合键之难 39
4.3如何识别反模式 39
4.4合理使用反模式 40
4.5解决方案:裁剪设计 40
4.5.1直截了当地描述设计 40
4.5.2打破传统 41
4.5.3拥抱自然键和组合键 41
第5章 不用钥匙的入口 43
5.1目标:简化数据库架构 43
5.2反模式:无视约束 44
5.2.1假设无瑕代码 44
5.2.2检查错误 45
5.2.3“那不是我的错!” 45
5.2.4进退维谷 46
5.3如何识别反模式 46
5.4合理使用反模式 47
5.5解决方案:声明约束 47
5.5.1支持同步修改 48
5.5.2系统开销过度?不见得 48
第6章 实体-属性-值 50
6.1目标:支持可变的属性 50
6.2反模式:使用泛型属性表 51
6.2.1查询属性 53
6.2.2支持数据完整性 53
6.2.3无法声明强制属性 53
6.2.4无法使用SQL的数据类型 53
6.2.5无法确保引用完整性 54
6.2.6无法配置属性名 55
6.2.7重组列 55
6.3如何识别反模式 56
6.4合理使用反模式 56
6.5解决方案:模型化子类型 57
6.5.1单表继承 57
6.5.2实体表继承 58
6.5.3类表继承 60
6.5.4半结构化数据模型 61
6.5.5后处理 61
第7章 多态关联 64
7.1目标:引用多个父表 65
7.2反模式:使用双用途外键 65
7.2.1定义多态关联 65
7.2.2使用多态关联进行查询 66
7.2.3非面向对象范例 67
7.3如何识别反模式 68
7.4合理使用反模式 69
7.5解决方案:让关系变得简单 69
7.5.1反向引用 69
7.5.2创建交叉表 69
7.5.3设立交通灯 70
7.5.4双向查找 71
7.5.5合并跑道 71
7.5.6创建共用的超级表 72
第8章 多列属性 75
8.1目标:存储多值属性 75
8.2反模式:创建多个列 76
8.2.1查询数据 76
8.2.2添加及删除值 77
8.2.3确保唯一性 78
8.2.4处理不断增长的值集 78
8.3如何识别反模式 79
8.4合理使用反模式 79
8.5解决方案:创建从属表 80
第9章 元数据分裂 82
9.1目标:支持可扩展性 83
9.2反模式:克隆表与克隆列 83
9.2.1不断产生的新表 84
9.2.2管理数据完整性 84
9.2.3同步数据 85
9.2.4确保唯一性 85
9.2.5跨表查询 86
9.2.6同步元数据 86
9.2.7管理引用完整性 86
9.2.8标识元数据分裂列 87
9.3如何识别反模式 87
9.4合理使用反模式 88
9.5解决方案:分区及标准化 89
9.5.1使用水平分区 89
9.5.2使用垂直分区 89
9.5.3解决元数据分裂列 91
第二部分 物理数据库设计反模式 94
第10章 取整错误 94
10.1 目标:使用小数取代整数 94
10.2反模式:使用FLOAT类型 95
10.2.1舍入的必要性 95
10.2.2在SQL中使用FLOAT 96
10.3如何识别反模式 98
10.4合理使用反模式 98
10.5解决方案:使用NUMERIC类型 98
第11章 每日新花样 100
11.1目标:限定列的有效值 100
11.2反模式:在列定义上指定可选值 101
11.2.1中间的是哪个 102
11.2.2添加新口味 103
11.2.3老的口味永不消失 103
11.2.4可移植性低下 103
11.3如何识别反模式 104
11.4合理使用反模式 104
11.5解决方案:在数据中指定值 104
11.5.1查询候选值集合 105
11.5.2更新检查表中的值 105
11.5.3支持废弃数据 105
11.5.4良好的可移植性 106
第12章 幽灵文件 107
12.1目标:存储图片或其他多媒体大文件 107
12.2反模式:假设你必须使用文件系统 108
12.2.1文件不支持DELETE 109
12.2.2文件不支持事务隔离 109
12.2.3文件不支持回滚操作 109
12.2.4文件不支持数据库备份工具 110
12.2.5文件不支持SQL的访问权限设置 110
12.2.6文件不是SQL数据类型 110
12.3如何识别反模式 111
12.4合理使用反模式 111
12.5解决方案:在需要时使用BLOB类型 112
第13章 乱用索引 114
13.1目标:优化性能 115
13.2反模式:无规划地使用索引 115
13.2.1无索引 115
13.2.2索引过多 116
13.2.3索引也无能为力 117
13.3如何识别反模式 118
13.4合理使用反模式 119
13.5解决方案:MENTOR你的索引 119
13.5.1测量 120
13.5.2解释 121
13.5.3挑选 122
13.5.4测试 123
13.5.5优化 123
13.5.6重建 123
第三部分 查询反模式 126
第14章 对未知的恐惧 126
14.1 目标:辨别悬空值 127
14.2反模式:将NULL作为普通的值,反之亦然 127
14.2.1在表达式中使用NULL 127
14.2.2搜索允许为空的列 128
14.2.3在查询参数中使用NULL 128
14.2.4避免上述问题 128
14.3如何识别反模式 130
14.4合理使用反模式 130
14.5解决方案:将NULL视为特殊值 131
14.5.1在标量表达式中使用NULL 131
14.5.2在布尔表达式中使用NULL 132
14.5.3检索NULL值 132
14.5.4声明NOT NULL的列 133
14.5.5动态默认值 134
第15章 模棱两可的分组 135
15.1 目i标:获取每组的最大值 135
15.2反模式:引用非分组列 136
15.2.1单值规则 136
15.2.2我想要的查询 137
15.3如何识别反模式 138
15.4合理使用反模式 139
15.5解决方案:无歧义地使用列 140
15.5.1只查询功能依赖的列 140
15.5.2使用关联子查询 140
15.5.3使用衍生表 140
15.5.4使用J0IN 141
15.5.5对额外的列使用聚合函数 142
15.5.6连接同组所有值 142
第16章 随机选择 144
16.1目标:获取样本记录 144
16.2反模式:随机排序 145
16.3如何识别反模式 146
16.4合理使用反模式 146
16.5解决方案:没有具体的顺序 146
16.5.1从1到最大值之间随机选择 146
16.5.2选择下一个最大值 147
16.5.3获取所有的键值,随机选择一个 147
16.5.4使用偏移量选择随机行 148
16.5.5专有解决方案 149
第17章 可怜人的搜索引擎 150
17.1 目标:全文搜索 150
17.2反模式:模式匹配断言 151
17.3如何识别反模式 152
17.4合理使用反模式 152
17.5解决方案:使用正确的工具 152
17.5.1数据库扩展 153
17.5.2第三方搜索引擎 157
第18章 意大利面条式查询 162
18.1目标:减少SQL查询数量 162
18.2反模式:使用一步操作解决复杂问题 163
18.2.1副作用 163
18.2.2那好像还不够 164
18.3如何识别反模式 165
18.4合理使用反模式 165
18.5解决方案:分而治之 166
18.5.1一步一个脚印 166
18.5.2寻找UNION标记 167
18.5.3解决老板的问题 167
18.5.4使用SQL自动生成SQL 168
第19章 隐式的列 170
19.1目标:减少输入 171
19.2反模式:捷径会让你迷失方向 171
19.2.1破坏代码重构 171
19.2.2隐藏的开销 172
19.2.3你请求,你获得 172
19.3如何识别反模式 173
19.4合理使用反模式 173
19.5解决方案:明确列出列名 174
19.5.1预防错误 174
19.5.2你不需要它 175
19.5.3无论如何你都需要放弃使用通配符 175
第四部分 应用程序开发反模式 178
第20章 明文密码 178
20.1 目标:恢复或重置密码 178
20.2反模式:使用明文存储密码 179
20.2.1存储密码 179
20.2.2验证密码 180
20.2.3在E-mail中发送密码 180
20.3如何识别反模式 181
20.4合理使用反模式 181
20.5解决方案:先哈希,后存储 182
20.5.1理解哈希函数 182
20.5.2在SQL中使用哈希 183
20.5.3给哈希加料 183
20.5.4在SQL中隐藏密码 185
20.5.5重置密码,而非恢复密码 186
第21章SQL注入 188
21.1 目标:编写SQL动态查询 189
21.2反模式:将未经验证的输入作为代码执行 189
21.2.1意外无处不在 190
21.2.2对Web安全的严重威胁 190
21.2.3寻找治愈良方 191
21.3如何识别反模式 195
21.4合理使用反模式 196
21.5解决方案:不信任任何人 196
21.5.1过滤输入内容 196
21.5.2参数化动态内容 197
21.5.3给动态输入的值加引号 197
21.5.4将用户与代码隔离 198
21.5.5找个可靠的人来帮你审查代码 200
第22章 伪键洁癖 202
22.1 标:整理数据 202
22.2反模式:填充角落 203
22.2.1不按照顺序分配编号 203
22.2.2为现有行重新编号 204
22.2.3制造数据差异 204
22.3如何识别反模式 205
22.4合理使用反模式 205
22.5解决方案:克服心里障碍 205
22.5.1定义行号 205
22.5.2使用GUID 206
22.5.3最主要的问题 207
第23章 非礼勿视 209
23.1目标:写更少的代码 210
23.2反模式:无米之炊 210
23.2.1没有诊断的诊断 210
23.2.2字里行间 211
23.3如何识别反模式 212
23.4合理使用反模式 213
23.5解决方案:优雅地从错误中恢复 213
23.5.1保持节奏 213
23.5.2回溯你的脚步 214
第24章 外交豁免权 215
24.1目标:采用最佳实践 215
24.2反模式:将SQL视为二等公民 216
24.3如何识别反模式 216
24.4合理使用反模式 217
24.5解决方案:建立一个质量至上的文化 217
24.5.1陈列A:编写文档 218
24.5.2寻找证据:源代码版本控制 20
24.5.3举证:测试 222
24.5.4例证:同时处理多个分支 223
第25章 魔豆 225
25.1 目标:简化MVC的模型 226
25.2反模式:模型仅仅是活动记录 227
25.2.1活动记录模式连接程序模型和数据库结构 228
25.2.2活动记录模式暴露了CRUD系列函数 228
25.2.3活动记录模式支持弱域模型 229
25.2.4魔豆难以进行单元测试 231
25.3如何识别反模式 232
25.4合理使用反模式 232
25.5解决方案:模型包含活动记录 232
25.5.1领会模型的意义 233
25.5.2将领域模型应用到实际工作中 234
25.5.3测试简单对象 236
25.5.4回到地球 237
第五部分 附录 240
附录A规范化规则 240
附录B参考书目 252