# SQL脚本规范

<p align="right">huangyongxing<br />2020-07-23</p>

<span style="color:red;">**特别注意：**</span>

* 一般SQL脚本，后续部署到正式服机器，会按顺序执行

* 为便于统一版本管理和对比差异，要求SQL内容提交到不同分支时，采用原始的日期文件名，不要重新命名。部分提交时，脚本内容应处于文件中相对应的位置（不要一边在文件头部，一边在文件尾部等）

## 规范要求

1. 通常新建用户数据表，不能在前面添加 DROP 表的语句，例如：

+ 错误用法：

```sql
DROP TABLE IF EXISTS `example`;
CREATA TABLE `example` (
  ...
) ...;
```

+ 正确用法：

```sql
CREATE TABLE `example` (
  ...
) ...;
```

**理由**：这是由于运维那边曾经发生过脚本错误或操作失误，会导入历史SQL。在这种情况下，如果有DROP表的语句，就会把正式服玩家数据清除掉，导致需要回档处理。

其实基于这一原因，通常对数据做更新的操作不应该出现在SQL脚本中，应只保留表结构相关语句。
但是事实上，有时候不得不更重建表结构或有一些重要的数据修正操作，这类则按实际需要添加。运维那边也加强了验证，尽可能避免此类问题发生。

2. 用户数据表使用InnoDB引擎和utf-8编码，一般应有主键，非必要尽量不使用联合主键，应有必要的字段注释和表注释

+ 示例：

```sql
CREATE TABLE `guild_war_guild_rank` (
  `rank` int(11) NOT NULL COMMENT '排名',
  `guild_id` int(11) NOT NULL COMMENT '帮派ID',
  `guild_name` varchar(50) NOT NULL COMMENT '帮派名字',
  `room` tinyint(3) NOT NULL COMMENT '战区',
  `score` int(11) NOT NULL COMMENT '积分',
  PRIMARY KEY (`rank`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='帮派积分榜';
```

3. 注意SQL应是完整可运行的SQL语句，不要遗漏最后的分号或书写不规范的SQL语句

正式服上会执行这些SQL语句，如果遗漏分号，会导致正式服更新失败
其他可能影响SQL正常执行的情况同样要避免

4. 注释应使用标准格式

```sql
-- 注释风格1 - 推荐风格（注意，行首两个-之后，有一个英文字符的空格）

# 注释风格2

SELECT `id` /* 注释风格3： 我是语句中间的注释 */ FROM `example` LIMIT 1;
```

其中，#号开头的注释以及SQL语句中间的注释/* */在项目中一般不使用

5. SQL文件应以“YY-MM-DD.sql”的形式命名，放在目录名为“YY-MM”的目录下，便于工具自动按序合并SQL脚本。其中，YY表示2位数字年份，MM表示2位数字月份，DD表示2位数字日期。

```shell
# 正确命名：
17-06/17-06-07.sql

# 错误命名:
17-6/17-6-7.sql
```

6. 文件统一使用UTF-8编码（不带BOM签名），换行符使用UNIX风格 (即\n换行)。

不要使用Windows的记事本直接编辑保存SQL脚本，记事本有几点问题：

+ 可能编码不对(一般是ANSI码直接保存，在中文系统即采用GBK编码)，换行符风格(\r\n)不对
+ 即使使用UTF-8编码，保存时仍会自动在文件头加BOM签名，在LINUX环境下，会引起问题
+ 如果一行过长，使用快捷键Ctrl+S保存会引起自动断行，可能导致SQL语句有误

使用其他编辑器的，注意设置工具使用正确的编码和换行符风格。

7. 文件以开发时提交的命名为准，合并提交到其他分支时不要重新命名，保持原来的文件名及内容在该文档中的对应位置，力求各版本使用相同的文件名、文件内容（更新到同一版本时）。

使用相同的文件名及文档中位置，便于对版本进行管理，检查和提取版本差异，排查错误操作等。
