diff --git a/advisor/rules.go b/advisor/rules.go index ddcd848c8197c443dfad7268873a7c7efb64b02e..dbc72e3009c68122abf5a1cb786ee657c2204376 100644 --- a/advisor/rules.go +++ b/advisor/rules.go @@ -501,7 +501,7 @@ func init() { Item: "COL.011", Severity: "L0", Summary: "当需要唯一约束时才使用NULL,仅当列不能有缺失值时才使用NOT NULL", - Content: `NULL和0是不同的,10乘以NULL还是NULL。NULL和空字符串是不一样的。将一个字符串和标准SQL中的NULL联合起来的结果还是NULL。NULL和FALSE也是不同的。AND、OR和NOT这三个布尔操作如果涉及NULL,其结果也让很多人感到困惑。当您将一列声明为NOT NULL时,也就是说这列中的每一个值都必须存在且是有意义的。使用NULL来表示任意类型不存在的空值。 当您将一列声明为NOT NULL时,也就是说这列中的每一个值都必须存在且是有意义的。`, + Content: `NULL和0是不同的,10乘以NULL还是NULL。NULL和空字符串是不一样的。将一个字符串和标准SQL中的NULL联合起来的结果还是NULL。NULL和FALSE也是不同的。AND、OR和NOT这三个布尔操作如果涉及NULL,其结果也让很多人感到困惑。当您将一列声明为NOT NULL时,也就是说这列中的每一个值都必须存在且是有意义的。使用NULL来表示任意类型不存在的空值。 `, Case: "select c1,c2,c3 from tbl where c4 is null or c4 <> 1", Func: (*Query4Audit).RuleNullUsage, }, @@ -785,7 +785,7 @@ func init() { Item: "KWR.002", Severity: "L2", Summary: "不建议使用MySQL关键字做列名或表名", - Content: `当使用关键字做为列名或表名时程序需要对列名和表名进行转义,如果疏忽被将导致请求无法执行。`, + Content: `当使用关键字做为列名或表名时程序需要对列名和表名进行转义,如果疏忽将导致请求无法执行。`, Case: "CREATE TABLE tbl ( `select` int )", Func: (*Query4Audit).RuleUseKeyWord, }, diff --git a/advisor/rules_english.go b/advisor/rules_english.go index ddb26a61d218f669e9951eb3dbe2aef4a93dd477..13eb40eadc3c12b01c061fa10945bd558932a214 100644 --- a/advisor/rules_english.go +++ b/advisor/rules_english.go @@ -43,23 +43,23 @@ func init() { }, "ALI.003": { Summary: "Alias shouldn't be the same with column name or table name.", - Content:`It will be hard to distinguish Alias of table or colomn when the alias is the same as it's real name.`, + Content: `It will be hard to distinguish Alias of table or column when the alias is the same as it's real name.`, }, "ALT.001": { Summary: "modify the default character set will not modify the character set of each field in the table.", - Content:`Many beginner would think that "ALTER TABLE tbl_name [DEFAULT] CHARACTER SET 'UTF8' " will modify character set of all fields,but actually it can only influence new fileds but not that already exits.You may use "ALTER TABLE tbl_name CONVERT TO CHARACTER SET charset_name;" if you want to modify character set of all fields.`, + Content: `Many beginner would think that "ALTER TABLE tbl_name [DEFAULT] CHARACTER SET 'UTF8' " will modify character set of all fields,but actually it can only influence new fileds but not that already exits.You may use "ALTER TABLE tbl_name CONVERT TO CHARACTER SET charset_name;" if you want to modify character set of all fields.`, }, "ALT.002": { Summary: "recommend to merge multiple ALTER request if it's in the same table.", - Content:`Once the structure of table changed,the online service will be influenced.Please merge requests of ALTER to reduce the number of operations even though you can adjust it by online tools.`, + Content: `Once the structure of table changed,the online service will be influenced.Please merge requests of ALTER to reduce the number of operations even though you can adjust it by online tools.`, }, "ALT.003": { Summary: "It's danger to delete column,please check if the business logic is still dependent before operation.", - Content:`If the business logic dosen't eliminated compeletly, you may can't write data or query the data of column begin deleted after column deleted,in which case you may lost data requested by users even by backup and recover.`, + Content: `If the business logic dosen't eliminated compeletly, you may can't write data or query the data of column begin deleted after column deleted,in which case you may lost data requested by users even by backup and recover.`, }, "ALT.004": { Summary: "It's danger to delete primary key and foreign key ,please check with DBA before operation.", - Content:`Primary key and foreign key are two important constraint in relational database,delete existing constraints may broken existing business logic,you may check the influence with DBA.` , + Content: `Primary key and foreign key are two important constraint in relational database,delete existing constraints may broken existing business logic,you may check the influence with DBA.`, }, "ARG.001": { Summary: "The use of the preceding wildcard query is not recommended.", @@ -83,7 +83,7 @@ func init() { }, "ARG.006": { Summary: "Try to avoid judge NULL values in WHERE clause.", - Content: `The engine may scan the whole table instead of use index when you use "IS NULL" or "IS NOT NULL",such as "select id from t where num is null".You can set num as 0 by default to make sure there is no null value in the colnumn of num,then you can use "select id from t where num=0"`, + Content: `The engine may scan the whole table instead of use index when you use "IS NULL" or "IS NOT NULL",such as "select id from t where num is null".You can set num as 0 by default to make sure there is no null value in the column of num,then you can use "select id from t where num=0"`, }, "ARG.007": { Summary: "Avoid string match", @@ -116,44 +116,43 @@ func init() { "CLA.003": { Summary: "The use of LIMIT query with OFFSET is not recommended.", - Content: `使用LIMIT和OFFSET对结果集分页的复杂度是O(n^2),并且会随着数据增大而导致性能问题。采用“书签”扫描的方法实现分页效率更高。`, - Content: ``, + Content: `The complexity is O(n^2) when using LIMIT and OFFSET to paginate to result set,which will cause performance probelm as data increases.Use "bookmark" to scan make it more efficiency to realize pagination.`, }, "CLA.004": { Summary: "GROUP BY is not recommended for constants.", - Content: `GROUP BY 1 表示按第一列进行GROUP BY。如果在GROUP BY子句中使用数字,而不是表达式或列名称,当查询列顺序改变时,可能会导致问题。`, + Content: `GROUP BY 1 means GROUP BY according to the 1st column.If use number clause in GROUP BY instead od expression or column name,it may cause problem when the query order changes.`, }, "CLA.005": { Summary: "ORDER BY constant column does not make any sense", - Content: `SQL逻辑上可能存在错误; 最多只是一个无用的操作,不会更改查询结果。`, + Content: `SQL may have logic error,which is an unuse operation at most and can't change query result.`, }, "CLA.006": { Summary: "Using GROUP BY or ORDER BY in different table.", - Content: `这将强制使用临时表和filesort,可能产生巨大性能隐患,并且可能消耗大量内存和磁盘上的临时空间。`, + Content: `This will use temporary table and filesort compulsively,cause huge performance hazard,and comsume plenty of memory and temporary space of disk.`, }, "CLA.007": { Summary: "Can't use index,because of ORDER BY different directions for multiple different conditions.", - Content: `ORDER BY子句中的所有表达式必须按统一的ASC或DESC方向排序,以便利用索引。`, + Content: `All expression in ORDER BY clause must sort by ASC or DESC uniformly to use index.`, }, "CLA.008": { Summary: "Please add ORDER BY condition explicitly for GROUP BY.", - Content: `默认MySQL会对'GROUP BY col1, col2, ...'请求按如下顺序排序'ORDER BY col1, col2, ...'。如果GROUP BY语句不指定ORDER BY条件会导致无谓的排序产生,如果不需要排序建议添加'ORDER BY NULL'。`, + Content: `By default,MySQL will sort 'GROUP BY col1, col2, ...' request in order of 'ORDER BY col1, col2, ...'.If the GROUP BY statement does not specify an ORDER BY condition,it will result in unnecessary sorting.It's recommended to add 'ORDER BY NULL' if you don't need sorting suggestions.`, }, "CLA.009": { Summary: "The condition of ORDER BY is an expression.", - Content: `当ORDER BY条件为表达式或函数时会使用到临时表,如果在未指定WHERE或WHERE条件返回的结果集较大时性能会很差。`, + Content: `Temporary tables are used when the ORDER BY condition is an expression or function, it will cause poor performance if not specifying a WHERE or WHERE condition when the result set is large.`, }, "CLA.010": { Summary: "The condition of GROUP BY is an expression.", - Content: `当GROUP BY条件为表达式或函数时会使用到临时表,如果在未指定WHERE或WHERE条件返回的结果集较大时性能会很差。`, + Content: `Temporary tables are used when the GROUP BY condition is an expression or function, it will cause poor performance if not specifying a WHERE or the return result set is large of WHERE condition .`, }, "CLA.011": { Summary: "Recommend add comments to the table", - Content: `为表添加注释能够使得表的意义更明确,从而为日后的维护带来极大的便利。`, + Content: `Adding comments to the table can make the it clearer to the meaning of the table, which will bring great convenience for future maintenance.`, }, "CLA.012": { Summary: "Decompose complex query into several simple queries", - Content: `SQL是一门极具表现力的语言,您可以在单个SQL查询或者单条语句中完成很多事情。但这并不意味着必须强制只使用一行代码,或者认为使用一行代码就搞定每个任务是个好主意。通过一个查询来获得所有结果的常见后果是得到了一个笛卡儿积。当查询中的两张表之间没有条件限制它们的关系时,就会发生这种情况。没有对应的限制而直接使用两张表进行联结查询,就会得到第一张表中的每一行和第二张表中的每一行的一个组合。每一个这样的组合就会成为结果集中的一行,最终您就会得到一个行数很多的结果集。重要的是要考虑这些查询很难编写、难以修改和难以调试。数据库查询请求的日益增加应该是预料之中的事。经理们想要更复杂的报告以及在用户界面上添加更多的字段。如果您的设计很复杂,并且是一个单一查询,要扩展它们就会很费时费力。不论对您还是项目来说,时间花在这些事情上面不值得。将复杂的意大利面条式查询分解成几个简单的查询。当您拆分一个复杂的SQL查询时,得到的结果可能是很多类似的查询,可能仅仅在数据类型上有所不同。编写所有的这些查询是很乏味的,因此,最好能够有个程序自动生成这些代码。SQL代码生成是一个很好的应用。尽管SQL支持用一行代码解决复杂的问题,但也别做不切实际的事情。`, + Content: `SQL is a very expressive language, and you can do a lot of things in a single SQL query or a single statement. But that doesn't mean you have to force a single line of code, or think it's a good idea to get each task with a single line of code.Generally,you get a Cartesian product though a single query.This happens when there is no condition between the two tables in the query to restrict their relationship.Without a corresponding restriction and directly using two tables for the join query,a combination of each row in the first table and each row in the second table is obtained.Each such combination becomes a row in the result set,and you will get a result set with a large number of rows.It is important to consider that these queries are difficult to write,difficult to modify,and difficult to debug.The increasing number of database query requests should be expected.Managers want more complex reports and add more fields to the user interface.If your design is complex and a single query, it can be time and labor consuming to extend them.It's not worth the time to spend on these things whether for you or the project.Break up complex spaghetti queries into a few simple queries.When you split a complex SQL query, the result may be a lot of similar queries, and may only differ in data type.It's uninteresting to write all of these queries,so it's best to have a program to generate the code automatically.SQL code generation is a good application.Although solving complex problems with a single line of code is supported by SQL,but don't do anything unrealistic.`, }, /* https://www.datacamp.com/community/tutorials/sql-tutorial-query @@ -180,252 +179,252 @@ func init() { */ "CLA.013": { Summary: "The use of HAVING clause is not recommended.", - Content: `将查询的HAVING子句改写为WHERE中的查询条件,可以在查询处理期间使用索引。`, + Content: `Rewrite the HAVING clause of the query to the query condition in WHERE, which can make index used during query processing.`, }, "CLA.014": { Summary: "Recommend to use TRUNCATE instead of DELETE.", - Content: `删除全表时建议使用TRUNCATE替代DELETE`, + Content: `It is recommended to use TRUNCATE instead of DELETE when deleting the whole table.`, }, "CLA.015": { Summary: "UPDATE without WHERE condition.", - Content: `UPDATE不指定WHERE条件一般是致命的,请您三思后行`, + Content: `UPDATE without specifying a WHERE condition is generally fatal, please think twice.`, }, "CLA.016": { Summary: "Don't UPDATE primary key.", - Content: `主键是数据表中记录的唯一标识符,不建议频繁更新主键列,这将影响元数据统计信息进而影响正常的查询。`, + Content: `The primary key is a unique identifier record in a data table. It is not recommended to update the primary key column frequently, which will affect statistics of the metadata and thus affect the normal query.`, }, "CLA.017": { Summary: "The use of stored procedure,view,trigger,temporary table is not recommended.", - Content: `这些功能的使用在一定程度上会使得程序难以调试和拓展,更没有移植性,且会极大的增加出现BUG的概率。`, + Content: `The use of these functions will make the program difficult to debug and expand,and have no portability,and will increase the probability of occurrence of BUG greatly.`, }, "COL.001": { Summary: "SELECT * is not good", - Content: `当表结构变更时,使用*通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。`, + Content: `When the table structure changes,selecting all the columns with the * wildcard will cause the meaning and behavior of the query to change,which may cause the query to return more data.`, }, "COL.002": { Summary: "INSERT without specify a column name.", - Content: `当表结构发生变更,如果INSERT或REPLACE请求不明确指定列名,请求的结果将会与预想的不同; 建议使用“INSERT INTO tbl(col1,col2)VALUES ...”代替。`, + Content: `When the table structure changes,if the INSERT or REPLACE request does not explicitly specify the column name,the result of the request will be different than expected; it is recommended to use "INSERT INTO tbl(col1,col2)VALUES ..." instead.`, }, "COL.003": { Summary: "Recommend to modify auto increment Id to unsigned type.", - Content: `建议修改自增ID为无符号类型`, + Content: `It is recommended to modify the auto_increment ID to be an unsigned type.`, }, "COL.004": { Summary: "Please set default values to the column.", - Content: `请为列添加默认值,如果是ALTER操作,请不要忘记将原字段的默认值写上。字段无默认值,当表较大时无法在线变更表结构。`, + Content: `Please add a default value for the column. If it is an ALTER operation, please don't forget to write the default value of the original field. , The table structure can't be changed online when the table is large if there is no default value for the field.`, }, "COL.005": { Summary: "column without comments.", - Content: `建议对表中每个列添加注释,来明确每个列在表中的含义及作用。`, + Content: `It is recommended to add a comment to each column in the table to clarify the meaning and role of each column in the table.`, }, "COL.006": { Summary: "table contains too many columns.", - Content: `表中包含有太多的列`, + Content: `The table contains too many columns.`, }, "COL.008": { Summary: "use VARCHAR instead of CHAR,VARBINARY instead of BINARY", - Content: `为首先变长字段存储空间小,可以节省存储空间。其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。`, + Content: `First, the variable-length field has a small storage space, which saves storage space. Secondly, the search efficiency is obviously higher in a relatively small field for queries.`, }, "COL.009": { Summary: "Precise data types are recommended.", - Content: `实际上,任何使用FLOAT、REAL或DOUBLE PRECISION数据类型的设计都有可能是反模式。大多数应用程序使用的浮点数的取值范围并不需要达到IEEE 754标准所定义的最大/最小区间。在计算总量时,非精确浮点数所积累的影响是严重的。使用SQL中的NUMERIC或DECIMAL类型来代替FLOAT及其类似的数据类型进行固定精度的小数存储。这些数据类型精确地根据您定义这一列时指定的精度来存储数据。尽可能不要使用浮点数。`, + Content: `Acctually, any design uses the FLOAT, REAL, or DOUBLE PRECISION data types may be anti-pattern.The range of values ​​used by most programmers does not need to meet the maximum/minimum range defined by the IEEE 754 standard. The cumulative effect of inexact floating point numbers is severe when calculating totals. Use NUMERIC or DECIMAL types in SQL instead of FLOAT and its similar data types for fractional storage of fixed-precision.These data types store data precisely based on the precision you specify when you define this column. Don't use floating point numbers as much as possible.`, }, "COL.010": { Summary: "The use of enum Type is not recommend.", - Content: `ENUM定义了列中值的类型,使用字符串表示ENUM里的值时,实际存储在列中的数据是这些值在定义时的序数。因此,这列的数据是字节对齐的,当您进行一次排序查询时,结果是按照实际存储的序数值排序的,而不是按字符串值的字母顺序排序的。这可能不是您所希望的。没有什么语法支持从ENUM或者check约束中添加或删除一个值;您只能使用一个新的集合重新定义这一列。如果您打算废弃一个选项,您可能会为历史数据而烦恼。作为一种策略,改变元数据——也就是说,改变表和列的定义——应该是不常见的,并且要注意测试和质量保证。有一个更好的解决方案来约束一列中的可选值:创建一张检查表,每一行包含一个允许在列中出现的候选值;然后在引用新表的旧表上声明一个外键约束。`, + Content: `ENUM defines the type of the value in the column. The data actually stored in the column is the ordinal of these values ​​when they are defined when a string is used to represent the value in ENUM.Therefore, the data in this column is byte-aligned. When you do a sort query, the results are sorted by the actual stored ordinal value, not by the alphabetical order of the string values.This may not be what you want. There is no grammatical support to add or remove a value from an ENUM or check constraint; you can only redefine this column with a new collection.If you plan to discard an option, you may be annoyed with history data. As a strategy, changing metadata—that is, changing the definition of tables and columns—should be uncommon and pay attention to testing and quality assurance.There is a better solution to constrain the optional values ​​in a column: create a checklist with each row containing a candidate value that is allowed to appear in the column; then declare a foreign key constraint on the old table that references the new table.`, }, // 这个建议从sqlcheck迁移来的,实际生产环境每条建表SQL都会给这条建议,看多了会不开心。 "COL.011": { Summary: "NULL is used only when a unique constraint is required, and NOT NULL is used only when the column cannot have a missing value.", - Content: `NULL和0是不同的,10乘以NULL还是NULL。NULL和空字符串是不一样的。将一个字符串和标准SQL中的NULL联合起来的结果还是NULL。NULL和FALSE也是不同的。AND、OR和NOT这三个布尔操作如果涉及NULL,其结果也让很多人感到困惑。当您将一列声明为NOT NULL时,也就是说这列中的每一个值都必须存在且是有意义的。使用NULL来表示任意类型不存在的空值。 当您将一列声明为NOT NULL时,也就是说这列中的每一个值都必须存在且是有意义的。`, + Content: `NULL and 0 are different,10 is multiplied by NULL is equal to NULL.NULL and empty strings are different.The result of combining a string with NULL in standard SQL is still NULL. NULL and FALSE are also different. The three Boolean operations of AND, OR, and NOT also confuse many people if involving NULL.When you declare a column as NOT NULL, that is, each value in this column must exist and be meaningful. Use NULL to represent a null value that does not exist for any type.`, }, "COL.012": { Summary: "Never set BLOB and TEXT to NULL.", - Content: `BLOB和TEXT类型的字段不可设置为NULL`, + Content: `Fields of BLOB and TEXT type can't be set to NULL.`, }, "COL.013": { Summary: "TIMESTAMP type without default value.", - Content: `TIMESTAMP类型未设置默认值`, + Content: `TIMESTAMP type doesn't set default value.`, }, "COL.014": { Summary: "specify character set for columns.", - Content: `建议列与表使用同一个字符集,不要单独指定列的字符集。`, + Content: `It's recommended that the column and table use the same character set. Don't specify the character set of the column separately.`, }, "COL.015": { Summary: "The default value cannot be specified for a field of BLOB type.", - Content: `BLOB类型的字段不可指定默认值`, + Content: `field of BLOB type can't specify default value.`, }, "COL.016": { Summary: "Recommend to use INT(10) or BIGINT(20) specify the integer definition.", - Content: `INT(M) 在 integer 数据类型中,M 表示最大显示宽度。 在 INT(M) 中,M 的值跟 INT(M) 所占多少存储空间并无任何关系。 INT(3)、INT(4)、INT(8) 在磁盘上都是占用 4 bytes 的存储空间。`, + Content: `INT(M) in data type of integer,M means maximum display width.In INT(M),the value of M has nothing to do with how much storage space INT(M) occupies. INT(3),INT(4),INT(8) occupy 4 bytes of storage space on the disk.`, }, "COL.017": { Summary: "Define varchar's length too long.", - Content: fmt.Sprintf(`varchar 是可变长字符串,不预先分配存储空间,长度不要超过%d,如果存储长度过长MySQL将定义字段类型为text,独立出来一张表,用主键来对应,避免影响其它字段索引效率。`, common.Config.MaxVarcharLength), + Content: fmt.Sprintf(`Varchar is a variable-length string. It's storage space is not pre-allocated. The length should not exceed %d. If the storage length is too long, MySQL will define the field type as text,separate a table and use the primary key to avoid the impact of other fields.`, common.Config.MaxVarcharLength), }, "DIS.001": { Summary: "remove unnecessary DISTINCT condition.", - Content: `太多DISTINCT条件是复杂的裹脚布式查询的症状。考虑将复杂查询分解成许多简单的查询,并减少DISTINCT条件的数量。如果主键列是列的结果集的一部分,则DISTINCT条件可能没有影响。`, + Content: `Too many DISTINCT conditions are symptoms of complex queries. Try to break a complex query into many simple queries and reduce the number of DISTINCT conditions. If the primary key column is part of a column's result set, the DISTINCT condition may have no effect.`, }, "DIS.002": { Summary: "COUNT(DISTINCT) multiple column may get the result unexpected.", - Content: `COUNT(DISTINCT col)计算该列除NULL之外的不重复行数,注意COUNT(DISTINCT col, col2)如果其中一列全为NULL那么即使另一列有不同的值,也返回0。`, + Content: `COUNT(DISTINCT col) calculates the number of non-repeating rows in the column except NULL. Note that COUNT(DISTINCT col, col2) returns 0 if one of the columns is all NULL even if the other column has a different value.`, }, // DIS.003灵感来源于如下链接 // http://www.ijstr.org/final-print/oct2015/Query-Optimization-Techniques-Tips-For-Writing-Efficient-And-Faster-Sql-Queries.pdf "DIS.003": { Summary: "DISTINCT * dosen’t make sense for a table with a primary key.", - Content: `当表已经有主键时,对所有列进行DISTINCT的输出结果与不进行DISTINCT操作的结果相同,请不要画蛇添足。`, + Content: `When the table already has a primary key, the result of operation with DISTINCT for all columns is the same as that without DISTINCT.Please don't add extras.`, }, "FUN.001": { Summary: "Avoid using functions or other operation in WHERE conditions.", - Content: `虽然在SQL中使用函数可以简化很多复杂的查询,但使用了函数的查询无法利用表中已经建立的索引,该查询将会是全表扫描,性能较差。通常建议将列名写在比较运算符左侧,将查询过滤条件放在比较运算符右侧。`, + Content: `Although using functions in SQL can simplify many complex queries, which can't take advantage of the indexes already established in the table. The query will make full table scanned with poor performance. Generally, it's recommended to write the column name to the left of the comparison operator while the query filter to the right of it.`, }, "FUN.002": { Summary: "The COUNT(*) operation performed poorly when a WHERE condition or non-myisam engine is specified.", - Content: `COUNT(*)的作用是统计表行数,COUNT(COL)的作用是统计指定列非NULL的行数。MyISAM表对于COUNT(*)统计全表行数进行了特殊的优化,通常情况下非常快。但对于非MyISAM表或指定了某些WHERE条件,COUNT(*)操作需要扫描大量的行才能获取精确的结果,性能也因此不佳。有时候某些业务场景并不需要完全精确的COUNT值,此时可以用近似值来代替。EXPLAIN出来的优化器估算的行数就是一个不错的近似值,执行EXPLAIN并不需要真正去执行查询,所以成本很低。`, + Content: `The role of COUNT(*) is to count the number of rows in the table while that of COUNT(COL) is to count the number of rows of the specified column that are not NULL.the MyISAM table is specially optimized for statistics of COUNT(*) for full table rows, which is usually very fast.But for non-MyISAM tables or for certain WHERE conditions, the COUNT(*) operation needs to scan a large number of rows to get accurate results, which result pool performance.Sometimes some business scenarios don't require an accurate COUNT value, in which case an approximation can be used instead.The number of rows estimated by the optimizer from EXPLAIN is a good approximation. Executing EXPLAIN doesn't require real execution of the query,which costs very low.`, }, "FUN.003": { Summary: "String concatenation may produce nullable columns.", - Content: `在一些查询请求中,您需要强制让某一列或者某个表达式返回非NULL的值,从而让查询逻辑变得更简单,担忧不想将这个值存下来。使用COALESCE()函数来构造连接的表达式,这样即使是空值列也不会使整表达式变为NULL。`, + Content: `In some query requests, you need to force a column or an expression to return a non-NULL value to make the query logic simpler and to worry about not saving this value. Use the COALESCE() function to construct a concatenated expression so that even a null column does not make the whole expression NULL.`, }, "FUN.004": { Summary: "The use of SYSDATE() functions is not recommended.", - Content: `SYSDATE()函数可能导致主从数据不一致,请使用NOW()函数替代SYSDATE()。`, + Content: `The SYSDATE() function may cause inconsistence between master and slave data. Use the NOW() function instead of SYSDATE().`, }, "FUN.005": { Summary: "The use of COUNT(col) or COUNT(const) is not recommended.", - Content: `不要使用COUNT(col)或COUNT(常量)来替代COUNT(*),COUNT(*)是SQL92定义的标准统计行数的方法,跟数据无关,跟NULL和非NULL也无关。`, + Content: `Don't use COUNT(col) or COUNT(constant) instead of COUNT(*). COUNT(*) is the standard method to count number of rows defined by SQL92, independent of data, NULL and non-NULL.`, }, "FUN.006": { Summary: "Caution the NPE exception when using SUM(col).", - Content: `当某一列的值全是NULL时,COUNT(COL)的返回结果为0,但SUM(COL)的返回结果为NULL,因此使用SUM()时需注意NPE问题。可以使用如下方式来避免SUM的NPE问题: SELECT IF(ISNULL(SUM(COL)), 0, SUM(COL)) FROM tbl`, + Content: `When the value of a column is all NULL, the result of COUNT(COL) is 0, but the result of SUM(COL) is NULL, so you need to pay attention to the NPE problem when using SUM(). You can use the following methods to avoid the NPE problem of SUM: SELECT IF(ISNULL(SUM(COL)), 0, SUM(COL)) FROM tbl.`, }, "GRP.001": { Summary: "GROUP BY is not recommended for equivalent query columns.", - Content: `GROUP BY中的列在前面的WHERE条件中使用了等值查询,对这样的列进行GROUP BY意义不大。`, + Content: `Columns in GROUP BY statement use equivalent queries in the preceding WHERE condition, it doesn't make much sense to use GROUP BY on such columns.`, }, "JOI.001": { Summary: "JOIN statements are mixed with commas and ANSI patterns.", - Content: `表连接的时候混用逗号和ANSI JOIN不便于人类理解,并且MySQL不同版本的表连接行为和优先级均有所不同,当MySQL版本变化后可能会引入错误。`, + Content: `The use of mixing commas and ANSI JOINs when joinning tables is not easy for human to understand,and different versions of MySQL have different behaviors and priorities of joinning tables,which may introduce error when MySQL version changes.`, }, "JOI.002": { Summary: "The same table join twice.", - Content: `相同的表在FROM子句中至少出现两次,可以简化为对该表的单次访问。`, + Content: `It can be simplified to a single access to the table when the same table appears at least twice in the FROM clause.`, }, "JOI.003": { Summary: "OUTER JOIN failure", - Content: `由于WHERE条件错误使得OUTER JOIN的外部表无数据返回,这会将查询隐式转换为 INNER JOIN 。如:select c from L left join R using(c) where L.a=5 and R.b=10。这种SQL逻辑上可能存在错误或程序员对OUTER JOIN如何工作存在误解,因为LEFT/RIGHT JOIN是LEFT/RIGHT OUTER JOIN的缩写。`, + Content: `No value returned from outer table of OUTER JOIN due to error of WHERE condition will implicitly convert the query to an INNER JOIN.such as: select c from L left join R using(c) where L.a=5 and R.b=10.This kind of SQL may have logic error or may occur due to the programmer's misunderstanding to OUTER JOIN because LEFT/RIGHT JOIN is an abbreviation for LEFT/RIGHT OUTER JOIN.`, }, "JOI.004": { Summary: "The use of exclusive JOIN is not recommended.", - Content: `只在右侧表为NULL的带WHERE子句的LEFT OUTER JOIN语句,有可能是在WHERE子句中使用错误的列,如:“... FROM l LEFT OUTER JOIN r ON l.l = r.r WHERE r.z IS NULL”,这个查询正确的逻辑可能是 WHERE r.r IS NULL。`, + Content: `A LEFT OUTER JOIN statement with a WHERE clause only on the right side of the table may be the reason of using wrong column in the WHERE clause,such as:"... FROM l LEFT OUTER JOIN r ON l.l = r.r WHERE r.z IS NULL",the correct logic of which may be "WHERE rr IS NULL". `, }, "JOI.005": { Summary: "Reduce the number of JOIN.", - Content: `太多的JOIN是复杂的裹脚布式查询的症状。考虑将复杂查询分解成许多简单的查询,并减少JOIN的数量。`, + Content: `Too many JOINs are symptoms of complex queries. Try to break a complex query into many simple queries and reducing the number of JOINs.`, }, "JOI.006": { Summary: "Rewriting nested queries as joins typically results in more efficient execution and more efficient optimization", - Content: `一般来说,非嵌套子查询总是用于关联子查询,最多是来自FROM子句中的一个表,这些子查询用于ANY、ALL和EXISTS的谓词。如果可以根据查询语义决定子查询最多返回一个行,那么一个不相关的子查询或来自FROM子句中的多个表的子查询就被压平了。`, + Content: `Generally,non-nested subqueries are always used to associate subqueries, up to one table from the FROM clause, which are used for predicates of ANY, ALL, and EXISTS. If a subquery can return up to one row according to query semantics, then an unrelated subquery or subquery of multiple tables from the FROM clause is flattened.`, }, "JOI.007": { Summary: "Federated table updates are not recommended", - Content: `当需要同时更新多张表时建议使用简单SQL,一条SQL只更新一张表,尽量不要将多张表的更新在同一条SQL中完成。`, + Content: `It's recommended to use simple SQL when you need to update multiple tables at the same time.One SQL only updates one table. Try not to update multiple tables in the same SQL.`, }, "JOI.008": { Summary: "Don’t use JOIN query in different DB.", - Content: `一般来说,跨DB的Join查询意味着查询语句跨越了两个不同的子系统,这可能意味着系统耦合度过高或库表结构设计不合理。`, + Content: `Generally, a Join query across DB means that the query across two different subsystems, which may mean that the system has a high degree of coupling or the table structure of library is designed unproperly.`, }, // TODO: 跨库事务的检查,目前SOAR未对事务做处理 "KEY.001": { Summary: "Recommend use auto increment column as primary key,please set auto increment column as the first column if you use joint autokey.", - Content: `建议使用自增列作为主键,如使用联合自增主键时请将自增键作为第一列`, + Content: `It's recommended to use the self-incrementing column as the primary key. If you use the union auto-increment primary key, please set the auto-increment key as the first column.`, }, "KEY.002": { Summary: "Table structures cannot be changed online without primary or unique keys.", - Content: `无主键或唯一键,无法在线变更表结构`, + Content: `Can't change the table structure online when there is no primary key or unique key.`, }, "KEY.003": { Summary: "Avoid recursive relationships such as foreign keys.", - Content: `存在递归关系的数据很常见,数据常会像树或者以层级方式组织。然而,创建一个外键约束来强制执行同一表中两列之间的关系,会导致笨拙的查询。树的每一层对应着另一个连接。您将需要发出递归查询,以获得节点的所有后代或所有祖先。解决方案是构造一个附加的闭包表。它记录了树中所有节点间的关系,而不仅仅是那些具有直接的父子关系。您也可以比较不同层次的数据设计:闭包表,路径枚举,嵌套集。然后根据应用程序的需要选择一个。`, + Content: `It's common that data has recursive relationships,and data is often organized like a tree or hierarchically. However, creating a foreign key constraint to enforce the relationship between two columns in the same table will lead clumsy queries.Each layer of the tree corresponds to another connection. You will need to issue a recursive query to get all descendants or all ancestors of the node. The solution is to construct an additional closure table. It records the relationships between all the nodes in the tree, but not just those with direct parent-child relationships. You can also compare data design of different levels: closure tables, path enumerations, nested sets. Then choose one according to the needs of the application.`, }, // TODO: 新增复合索引,字段按散粒度是否由大到小排序,区分度最高的在最左边 "KEY.004": { Summary: "Reminder: align the index attributes with the query.", - Content: `如果为列创建复合索引,请确保查询属性与索引属性的顺序相同,以便DBMS在处理查询时使用索引。如果查询和索引属性订单没有对齐,那么DBMS可能无法在查询处理期间使用索引。`, + Content: `Please make sure that the query attributes are in the same order as the index attributes if you create a composite index for a column so that the DBMS uses indexes when processing the queries.If queries and index attributes are not aligned, the DBMS may not be able to use indexes when processing the queries.`, }, "KEY.005": { Summary: "Tables build too many indexes.", - Content: `表建的索引过多`, + Content: `Too many indexes built in the table`, }, "KEY.006": { Summary: "Too many columns in the primary key.", - Content: `主键中的列过多`, + Content: `Too many columns in the primary key.`, }, "KEY.007": { Summary: "No primary key or primary key isn’t int or bigint is specified.", - Content: `未指定主键或主键非int或bigint,建议将主键设置为int unsigned或bigint unsigned。`, + Content: `The primary key isn't specified or the primary key isn't int or bigint. It's recommended to set the primary key to int unsigned or bigint unsigned.`, }, "KEY.008": { Summary: "The index may not be available for use if the ORDER BY column is not ordered in the same direction.", - Content: `在MySQL 8.0之前当ORDER BY多个列指定的排序方向不同时将无法使用已经建立的索引。`, + Content: `Indexes already established couldn't be used when the ORDER BY of multiple columns specified different sort directions before MySQL 8.0.`, }, "KEY.009": { Summary: "Check data uniqueness before adding a unique key.", - Content: `请提前检查添加唯一索引列的数据唯一性,如果数据不唯一在线表结构调整时将有可能自动将重复列删除,这有可能导致数据丢失。`, + Content: `Please check the uniqueness of the data added in the unique index column in advance. If the data is not unique, duplicate column will be deleted automatically when the online table structure begin adjusted, which may result in data loss.`, }, "KWR.001": { Summary: "SQL_CALC_FOUND_ROWS is inefficient.", - Content: `因为SQL_CALC_FOUND_ROWS不能很好地扩展,所以可能导致性能问题; 建议业务使用其他策略来替代SQL_CALC_FOUND_ROWS提供的计数功能,比如:分页结果展示等。`, + Content: `It may result performance problems because that SQL_CALC_FOUND_ROWS doesn't scale well.it's recommended that the business use other strategies to replace the counting functions provided by SQL_CALC_FOUND_ROWS, such as: display paging results.`, }, "KWR.002": { Summary: "MySQL keywords are not recommended for column or table names.", - Content: `当使用关键字做为列名或表名时程序需要对列名和表名进行转义,如果疏忽被将导致请求无法执行。`, + Content: `The program needs to escape the column name and table name when using a keyword as name of column or table. Otherwise,the request will be unexecutable.`, }, "KWR.003": { Summary: "Complex Numbers are not recommended for column or table names.", - Content: `表名应该仅仅表示表里面的实体内容,不应该表示实体数量,对应于 DO 类名也是单数形式,符合表达习惯。`, + Content: `The table name should only represent the entity content in the table and should not indicate the number of entities ,corresponding to the name of DO class is also singular to meet the expression habit.`, }, "LCK.001": { Summary: "Note:INSERT INTO xx SELECT will greater lock granularity.", - Content: `INSERT INTO xx SELECT加锁粒度较大请谨慎`, + Content: `Please be cautious that INSERT INTO xx SELECT will greater lock granularity.`, }, "LCK.002": { Summary: "Caution:INSERT ON DUPLICATE KEY UPDATE", - Content: `当主键为自增键时使用INSERT ON DUPLICATE KEY UPDATE可能会导致主键出现大量不连续快速增长,导致主键快速溢出无法继续写入。极端情况下还有可能导致主从数据不一致。`, + Content: `Using INSERT ON DUPLICATE KEY UPDATE may cause a large number of discontinuous rapid growth of the primary key when the primary key is an auto-increment key , causing the primary key to quickly overflow and unable to continue writing. It is also possible to cause inconsistence of master and slave data in some extreme cases.`, }, "LIT.001": { Summary: "Store IP addresses with character types.", - Content: `字符串字面上看起来像IP地址,但不是INET_ATON()的参数,表示数据被存储为字符而不是整数。将IP地址存储为整数更为有效。`, + Content: `The string literally looks like an IP address, but is not a parameter of INET_ATON(), indicating that the data is stored as a character rather than an integer. It's more efficient to store the IP address as integer.`, }, "LIT.002": { Summary: "Date/time is not enclosed in quotation marks.", - Content: `诸如“WHERE col <2010-02-12”之类的查询是有效的SQL,但可能是一个错误,因为它将被解释为“WHERE col <1996”; 日期/时间文字应该加引号。`, + Content: `A query such as "WHERE col <2010-02-12" is a valid SQL, but it may be an error because it will be interpreted as "WHERE col <1996"; text of date/time should be quoted.`, }, "LIT.003": { Summary: "A collection of related data stored in a column.", - Content: `将ID存储为一个列表,作为VARCHAR/TEXT列,这样能导致性能和数据完整性问题。查询这样的列需要使用模式匹配的表达式。使用逗号分隔的列表来做多表联结查询定位一行数据是极不优雅和耗时的。这将使验证ID更加困难。考虑一下,列表最多支持存放多少数据呢?将ID存储在一张单独的表中,代替使用多值属性,从而每个单独的属性值都可以占据一行。这样交叉表实现了两张表之间的多对多关系。这将更好地简化查询,也更有效地验证ID。`, + Content: `Storing ID as a list as a VARCHAR/TEXT column can result problem of performance and data integrity. Querying such a column requires an expression that uses pattern matching. Using a comma-separated list to do multi-table join queries to locate a row of data is extremely inelegant and time consuming. This will make it more difficult to verify the ID . Consider how much data does the list support at most? Store the ID in a separate table instead of using a multi-valued attribute so that each single attribute value can occupy one row. This across table implements a many-to-many relationship between two tables which will make it simplify to query and efficiency to validate the ID.`, }, "LIT.004": { Summary: "Use a semicolon or the designated DELIMITER end.", - Content: `USE database, SHOW DATABASES等命令也需要使用使用分号或已设定的DELIMITER结尾。`, + Content: `Commands such as USE database, SHOW DATABASES, etc. also need to end with semicolon or DELIMITER already set.`, }, "RES.001": { Summary: "Nondeterministic GROUP BY.", - Content: `SQL返回的列既不在聚合函数中也不是GROUP BY表达式的列中,因此这些值的结果将是非确定性的。如:select a, b, c from tbl where foo="bar" group by a,该SQL返回的结果就是不确定的。`, + Content: `The columns returned by SQL are neither in the aggregate function nor in the columns of the GROUP BY expression, so the result of these values ​​will be uncertain. Such as: "select a, b, c from tbl where foo="bar" group by a", the result returned by the SQL is uncertain.`, }, "RES.002": { Summary: "LIMIT query without ORDER BY.", - Content: `没有ORDER BY的LIMIT会导致非确定性的结果,这取决于查询执行计划。`, + Content: `LIMIT without ORDER BY results in uncertain results, which depends on the query execution plan.`, }, "RES.003": { Summary: "Using LIMIT with UPDATE/DELETE.", - Content: `UPDATE/DELETE操作使用LIMIT条件和不添加WHERE条件一样危险,它可将会导致主从数据不一致或从库同步中断。`, + Content: `UPDATE/DELETE operations using the LIMIT condition are as dangerous as not adding a WHERE condition, which can cause inconsistence of master and slave data or interrupt synchronization of slaves.`, }, "RES.004": { Summary: "Using ORDER BY with UPDATE/DELETE.", - Content: `UPDATE/DELETE操作不要指定ORDER BY条件。`, + Content: `Don't specify an ORDER BY condition for UPDATE/DELETE operations.`, }, "RES.005": { Summary: "UPDATE may have a logical error that causes data corruption.", @@ -433,91 +432,91 @@ func init() { }, "RES.006": { Summary: "Compare condition always false.", - Content: "查询条件永远非真,这将导致查询无匹配到的结果。", + Content: "Query condition never being true will result in the query having no matching results.", }, "RES.007": { - Summary: "COmpare condition always true.", - Content: "查询条件永远为真,这将导致WHERE条件失效进行全表查询。", + Summary: "Compare condition always true.", + Content: "Query condition always being true will result in WHERE condition failing to a full table query.", }, "RES.008": { Summary: "The use of LOAD DATA/SELECT ... INTO OUTFILE is not recommended.", - Content: "SELECT INTO OUTFILE需要授予FILE权限,这通过会引入安全问题。LOAD DATA虽然可以提高数据导入速度,但同时也可能导致从库同步延迟过大。", + Content: "SELECT INTO OUTFILE needs to grant FILE permission, which will introduce security problems. Although LOAD DATA can increase the import speed of data, it can also cause the delay of synchronization delay of the slave to be too large.", }, "SEC.001": { Summary: "Caution:using TRUNCATE operation.", - Content: `一般来说想清空一张表最快速的做法就是使用TRUNCATE TABLE tbl_name;语句。但TRUNCATE操作也并非是毫无代价的,TRUNCATE TABLE无法返回被删除的准确行数,如果需要返回被删除的行数建议使用DELETE语法。TRUNCATE操作还会重置AUTO_INCREMENT,如果不想重置该值建议使用DELETE FROM tbl_name WHERE 1;替代。TRUNCATE操作会对数据字典添加源数据锁(MDL),当一次需要TRUNCATE很多表时会影响整个实例的所有请求,因此如果要TRUNCATE多个表建议用DROP+CREATE的方式以减少锁时长。`, + Content: `Generally,the quickest way to clear a table is to use "TRUNCATE TABLE tbl_name". However, the TRUNCATE operation is not without costs. TRUNCATE TABLE can't return the exact number of deleted rows. If you need to return the number of deleted rows, it's recommended to use DELETE. The TRUNCATE operation will also reset AUTO_INCREMENT, and if you don't want to reset the value, it is recommended to use "DELETE FROM tbl_name WHERE 1" instead.The TRUNCATE operation adds a source data lock (MDL) to the data dictionary.It affects all requests for the entire instance When a large number of TRUNCATE tables are needed at once. Therefore, if you want to TRUNCATE multiple tables, use DROP+CREATE to reduce the duration of locking.`, }, "SEC.002": { Summary: "Don’t stored password in clear text.", - Content: `使用明文存储密码或者使用明文在网络上传递密码都是不安全的。如果攻击者能够截获您用来插入密码的SQL语句,他们就能直接读到密码。另外,将用户输入的字符串以明文的形式插入到纯SQL语句中,也会让攻击者发现它。如果您能够读取密码,黑客也可以。解决方案是使用单向哈希函数对原始密码进行加密编码。哈希是指将输入字符串转化成另一个新的、不可识别的字符串的函数。对密码加密表达式加点随机串来防御“字典攻击”。不要将明文密码输入到SQL查询语句中。在应用程序代码中计算哈希串,只在SQL查询中使用哈希串。`, + Content: `It's not safe to store passwords in plain text or pass passwords on the network in plain text. If the attacker can intercept the SQL statement that you used to insert the password, they can read the password directly. In addition, inserting a string entered by the user into a plain SQL statement in plain text will also allow the attacker to discover it. If you can read the password, the hacker can,too. The solution is to encrypt the original password using a one-way hash function. A hash is a function that converts an input string into another new, unrecognizable string. Add a random string to encryption expression of the password to defend against "dictionary attacks." Do not enter the clear text password into the SQL query statement. Hash strings are computed in code of application, and only used in SQL queries.`, }, "SEC.003": { Summary: "Back up when using actions such as DELETE/DROP/TRUNCATE.", - Content: `在执行高危操作之前对数据进行备份是十分有必要的。`, + Content: `It's necessary to back up your data before performing high-risk operations.`, }, "STA.001": { Summary: "'!=' isn’t a standard operator.", - Content: `"<>"才是标准SQL中的不等于运算符。`, + Content: `"<>" is the unequal operator in standard SQL.`, }, "STA.002": { Summary: "Recommend: Don’t add white space after table or database.", - Content: `当使用db.table或table.column格式访问表或字段时,请不要在点号后面添加空格,虽然这样语法正确。`, + Content: `Don't add spaces after the dot when accessing a table or field using db.table or table.column format,although the syntax is correct.`, }, "STA.003": { Summary: "Index naming is not standard.", - Content: `建议普通二级索引以idx_为前缀,唯一索引以uk_为前缀。`, + Content: `It's recommended that the normal secondary index be prefixed with idx_ and the unique index be prefixed with uk_.`, }, "STA.004": { Summary: "Do not use characters other than letters, Numbers, and underscores when naming names.", - Content: `以字母或下划线开头,名字只允许使用字母、数字和下划线。请统一大小写,不要使用驼峰命名法。不要在名字中出现连续下划线'__',这样很难辨认。`, + Content: `Begin with a letter or an underscore, the name is only allowed to use letters, numbers, and underscores. Please be all lowercase or all uppercase, do not use Camel-Case. Don't have a continuous underscore '__' in your name, which is hard to read.`, }, "SUB.001": { Summary: "MySQL doesn't optimize subqueries very well.", - Content: `MySQL将外部查询中的每一行作为依赖子查询执行子查询。 这是导致严重性能问题的常见原因。这可能会在 MySQL 5.6版本中得到改善, 但对于5.1及更早版本, 建议将该类查询分别重写为JOIN或LEFT OUTER JOIN。`, + Content: `MySQL executes subquery for each row in outer query as dependent subquery. This is a common cause of serious performance problems. This may be improved in MySQL 5.6, but for 5.1 and earlier, it is recommended to rewrite the query to JOIN or LEFT OUTER JOIN.`, }, "SUB.002": { Summary: "If you don't care about duplication, use UNION ALL instead of UNION.", - Content: `与去除重复的UNION不同,UNION ALL允许重复元组。如果您不关心重复元组,那么使用UNION ALL将是一个更快的选项。`, + Content: `Unlike the UNION with duplicates removed, UNION ALL allows duplicate tuples. If you don't care about repeating tuples, using UNION ALL will be a faster option.`, }, "SUB.003": { Summary: "Consider using a EXISTS instead of a DISTINCT subquery.", - Content: `DISTINCT关键字在对元组排序后删除重复。相反,考虑使用一个带有EXISTS关键字的子查询,您可以避免返回整个表。`, + Content: `The DISTINCT keyword removes duplicates after sorting tuples. Instead, consider using a subquery with the EXISTS keyword to avoid returning the entire table.`, }, // TODO: 5.6有了semi join还要把in转成exists么? // Use EXISTS instead of IN to check existence of data. // http://www.winwire.com/25-tips-to-improve-sql-query-performance/ "SUB.004": { Summary: "The nested connections in the execution plan are too deep.", - Content: `MySQL对子查询的优化效果不佳,MySQL将外部查询中的每一行作为依赖子查询执行子查询。 这是导致严重性能问题的常见原因。`, + Content: `MySQL doesn't perform well on subqueries, and MySQL executes subqueries for each row in the query as dependent subqueries. This is a common cause of serious performance problems.`, }, // SUB.005灵感来自 https://blog.csdn.net/zhuocr/article/details/61192418 "SUB.005": { Summary: "Subqueries do not support limits.", - Content: `当前MySQL版本不支持在子查询中进行'LIMIT & IN/ALL/ANY/SOME'。`, + Content: `The current MySQL version doesn't support 'LIMIT & IN/ALL/ANY/SOME' in subqueries.`, }, "SUB.006": { Summary: "The use of functions in subquery is not recommended.", - Content: `MySQL将外部查询中的每一行作为依赖子查询执行子查询,如果在子查询中使用函数,即使是semi-join也很难进行高效的查询。可以将子查询重写为OUTER JOIN语句并用连接条件对数据进行过滤。`, + Content: `MySQL executes subqueries for each row in the query as dependent subqueries. If a function is used in a subquery, even semi-join is difficult to perform efficient queries. You can rewrite the subquery to an OUTER JOIN statement and filter the data with join conditions.`, }, "TBL.001": { Summary: "The use of partition table is not recommended.", - Content: `不建议使用分区表`, + Content: `Partition table is not recommended.`, }, "TBL.002": { Summary: "Select the appropriate storage engine for the table.", - Content: `建表或修改表的存储引擎时建议使用推荐的存储引擎,如:` + strings.Join(common.Config.TableAllowEngines, ","), + Content: `It's recommended to use the recommended storage engine when building or modifying the storage engine of the table, such as:` + strings.Join(common.Config.TableAllowEngines, ","), }, "TBL.003": { Summary: "A table named DUAL has special meaning in the database.", - Content: `DUAL表为虚拟表,不需要创建即可使用,也不建议服务以DUAL命名表。`, + Content: `DUAL table is a virtual table that can be used without creation. It's also not recommended that the service name the table with DUAL.`, }, "TBL.004": { Summary: "The initial AUTO_INCREMENT value of the table is not 0.", - Content: `AUTO_INCREMENT不为0会导致数据空洞。`, + Content: `It will result in data holes if AUTO_INCREMENT is not 0.`, }, "TBL.005": { Summary: "Please use the recommended character set.", - Content: `表字符集只允许设置为` + strings.Join(common.Config.TableAllowCharsets, ","), + Content: `The table character set is only allowed to be set to` + strings.Join(common.Config.TableAllowCharsets, ","), }, } }