基础规范
- 数据表、数据字段添加中文注释。如果字段中不同的数字代表不同的状态,需在注释中写明。
- 使用UTF8字符集。万国码,无需转码,无乱码风险,节省空间。
- 表中必须有主键。
- 表中必须有字段
create_time
和update_time
,类型均为datetime
。
CREATE TABLE tc_role (
id varchar(22) NOT NULL DEFAULT '' COMMENT '主键_id',
role_name varchar(32) DEFAULT NULL COMMENT '角色名称',
is_delete tinyint(2) DEFAULT NULL COMMENT '是否删除( 0=未删除,1=已删除)',
create_time datetime DEFAULT NULL COMMENT '创建时间',
update_time datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='角色表';
SQL 命名规范
- 小写。数据库、表和字段名称应全部用小写字母来书写。
- 数据类型不是名称。避免使用仅为数据类型的名字(如
text
或timestamp
)。 - 多个单词组成的名称,应该用下划线分隔。如:应使用
word_count
,而不是wordCount
。 - 使用完整的单词,而不是缩写。例如使用
middle_name
,不是inf_nm
。 - 使用共识的缩写。对于几个长词而言,缩写词比词本身更为常见,比如
i18n
和l10n
,这时使用缩写。
SQL规约
- 尽量不用
select *
,只获取必要的字段。
原因:读取不需要的列会增加CPU、IO、NET消耗;在增加或删除字段后出现程序bug。 - 不可用
INSERT INTO 表名 VALUES(xxxxx)
,必须显式指定插入的列属性。
原因:容易在增加或者删除字段后出现程序BUG。 - 不可在WHERE条件的属性上使用函数或者表达式。
原因:SELECT uid FROM t_user WHERE from_unixtime(day)>='2017-02-15'
会导致全表扫描
正确的写法是:SELECT uid FROM t_user WHERE day>= unix_timestamp('2017-02-15 00:00:00')
- 禁止负向查询,以及%开头的模糊查询。
原因:负向查询条件:NOT、!=、<>、!<、!>、NOT IN、NOT LIKE等,会导致全表扫描。
%开头的模糊查询,会导致全表扫描。 - 禁止大表使用join查询,禁止大表使用子查询。
原因:会产生临时表,消耗较多内存与CPU,极大影响数据库性能。 - 使用表的别名,并把别名前缀于每个column上。
原因:减少解析的时间;减少由column歧义引起的语法错误。 - 禁止使用OR条件,必须改为IN查询。
- 减少访问数据库的次数。
- 在代码中写分页查询逻辑时,若count为0则直接返回,避免执行后面的分页语句。
- 应用程序必须捕获SQL异常,并有相应处理。
易错点
count(*)
与count(列名)
的区别:count(*)
统计表中的所有行,count(列名)
不统计该列值为null的行。- 当某一列的值全为null时,
count(col)
的返回结果为0,但sum(col)
的返回结果为null。 - sql语句中,使用ISNULL()来判断是否为null值。任何值与null的直接比较结果都为null。
NULL<>NULL 的返回结果是 NULL,不是 false。
NULL=NULL 的返回结果是 NULL,不是 true。
NULL<>1 的返回结果是 NULL,不是 true。
扩展
I18N,Internationalization的缩写,国际化,I和N中间有18个字母。
L10N,Localization的缩写,本地化,l和N中间有10个字母。
国际化是指在设计软件时,将软件与特定语言及地区脱钩的过程。当软件被移植到不同的语言地区时,软件本身不用做内部工程上的改变或修正。
本地化则是指当移植软件时,加上与特定区域设置有关的资讯和翻译文件的过程。
假设我们写了一个 app,在国内市场获得了巨大成功,准备走出国门,需要做的工作就是 i18n。
假设我们要在国内代理营运一个外国的 app,所做的工作就叫 l10n。