Skip to content

Commit

Permalink
update sql design
Browse files Browse the repository at this point in the history
  • Loading branch information
fengzhao committed Oct 19, 2023
1 parent a3b5e6d commit 602bae8
Showing 1 changed file with 67 additions and 0 deletions.
67 changes: 67 additions & 0 deletions docs/dev/02.数据库设计.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,70 @@ UML图分为结构图和行为图:
SQL是一门声明式的编程语言,就像 Lisp、Haskell或者 XSLT。SQL使用集合(set)作为根本的数据结构,而面向对象的语言使用的是对象(object)。受过传统培训的软件开发人员被所谓的"阻抗失配"所阻碍,因此很多程序员转而使用现成的面向对象的库,以此来避免学习如何高效地使用SQL




反范式是一种试图解决问题的方法,但通常会同时引发别的问题。反范式


**逻辑数据库设计反模式**

在你开始编码之前,需要决定数据库里存储什么信息以及最佳的数据组织方式和内在关联方式。这包含了如何设计数据库的表、字段和关系。


**物理数据库设计反模式**

在知道了需要存储哪些数据之后,使用你所知的RDBMS技术特性尽可能高效地实现数据管理。这包含了定义表和索引,以及选择数据类型。你也要使用 SQL 的“数据定义语言”,比如CREATE TABLE 语句。

**查询反模式**

你需要向数据库中添加然后获取数据。SQL的查询是使用"数据操作语言"来完成,比如SELECT 、 UPDATE 和 DELETE 语句。

**应用程序开发反模式**

SQL应该会用在使用 C++、Java、Php、Python或者 Ruby等语言构建的应用程序中。在应用程序中使用SQL的方式有好有坏,该部分内容描述了一些常见错误。


### 多值属性

将数据库中原来存储单一用户标识的字段改成使用逗号分隔的用户标识列表,似乎是一个很简单且合理的解决方案。

程序员通常使用逗号分隔的列表来避免在多对多的关系中创建交叉表,我将这种设计方式定义为一种反模式,称为乱穿马路(Jaywalking),因为乱穿马路也是避免过十字路口的一种方式。

设计一个单值表列是非常简单的:你可以选择一个 SQL 的内置数据类型,以该类型来存储这个表项的数据,比如整型、日期类型或者字符串。但是如何才能做到在一列中存储一系列相关数据的集合呢?

很自然,使用VARCHAR类型字段,并用逗号分隔对应的数据。

**选择合适的分隔符**

如果存储一个字符串列表而不是数字列表,列表中的某些条目可能会包含分隔符。使用逗号作为分隔符可能会有问题。当然,你到时候可以再换一个字符,但你能确保这个新字符永远不会出现在条目中吗?

**列表长度限制**

你能在一个 VARCHAR(30) 的结构中存多少数据呢?这依赖于每个条目的长度。如果每个条目只有2个字符长,那你能存10个条目(包括逗号)。但如果每个条目的长度为6,你就只能存4个了。

你怎能确定 VARCHAR(30) 能够支持你未来所需的最长列表呢?多长才够长?

**合理使用反模式**

出于性能优化的考量,可能在数据库的结构中需要使用反规范化的设计。将列表存储为以逗号分隔的字符串就是反规范化的一个实例。

应用程序可能会需要逗号分隔的这种存储格式的数据,也可能没必要获取列表中的单独项。

同样,如果应用程序接收的源数据是有逗号分隔的格式,而你只需要存储和使用它们并且不对其做任何修改,完全没必要分开其中的值。



### 主键


每个了解数据库设计的人都知道,主键对于一张表来说是一个很重要,甚至必需的部分。这确实是事实,主键是好的数据库设计的一部分。主键是数据库确保数据行在整张表中唯一性的保障,它是定位到一条记录并且确保不会重复存储的逻辑机制。主键也同时可以被外键引用来建立表与表之间的关系。

难点是选择哪一列作为主键。大多数表中的每个属性的值都有可能被很多行使用。例如一个人的姓和名就一定会在表中重复出现,即使电子邮件地址或者美国社保编号或者税单编号也不能保证绝对不会重复。

在这样的表中,需要引入一个对于表的域模型无意义的新列来存储一个伪值。这一列被用作这张表的主键,从而通过它来确定表中的一条记录,即便其他的列允许出现适当的重复项。这种类型的主键列我们通常称其为伪主键或者代理键。

大多数的数据库提供一种和当前处理事务无关的底层方案,来确保每次都能生成全局唯一的一个整数作为伪主键,即使客户端此时正发起并发操作。

一张没有主键的表就好像你的 MP3 播放列表里没有歌名一样。你依然可以听歌,但无法找到想听的那首歌,也没办法确保播放列表中没有重复的歌曲。

伪主键直到 SQL:2003才成为一个标准,因而每个数据库都使用自己特有的 SQL扩展来实现伪主键,甚至不同数据库中对于伪主键都有不同的名称(不同的表述)

0 comments on commit 602bae8

Please sign in to comment.