首页 > 数据库 >详细了解SQL语句规范

详细了解SQL语句规范

时间:2024-12-06 20:00:23浏览次数:5  
标签:语句 count 数据库 查询 详细 SQL NULL

SQL语句规范

说个大概,

使用 ISNULL()来判断是否为 NULL 值

不要使用 count(列名)或 count(常量)来替代 count(*)

代码中写分页查询逻辑时,若 count 为 0 应直接返回,避免执行后面的分页语句。

不得使用外键与级联,一切外键概念必须在应用层解决

禁止使用存储过程,存储过程难以调试和扩展,更没有移植性

数据订正(特别是删除或修改记录操作)时,要先 select,避免出现误删除,确认无误才能执行更新语句

对于数据库中表记录的查询和变更,只要涉及多个表,都需要在列名前加表的别名(或表名)进行限定

还有等等

 

\1. 【强制】不要使用 count(列名)或 count(常量)来替代 count(*),count(*)是 SQL92 定义的标准统计行数的语法,跟数据库无关,跟 NULL 和非 NULL 无关。

说明:count(*)会统计值为 NULL 的行,而 count(列名)不会统计此列为 NULL 值的行。

  • 遵循标准语法,通用性强:count (*) 是 SQL92 定义的标准统计行数的语法,与具体的数据库无关,无论使用哪种数据库管理系统(如 MySQL、Oracle、SQL Server 等),其含义和用法都是统一的,这样编写的 SQL 语句具有更好的通用性和可移植性,便于在不同的数据库环境中迁移和部署应用程序,减少因语法差异导致的代码修改成本。

  • 准确统计行数,包含 NULL 值行:count (列名) 不会统计该列值为 NULL 的行,而 count () 会统计所有行,包括值为 NULL 的行。在很多业务场景中,我们往往需要确切知道表中的总记录数,而不区分某列是否为 NULL,使用 count () 能准确满足这一需求,确保数据统计的完整性和准确性,符合实际的业务分析和数据处理要求。

 

\2. 【强制】count(distinct col) 计算该列除 NULL 之外的不重复行数,注意 count(distinct col1, col2) 如果其中一列全为 NULL,那么即使另一列有不同的值,也返回为 0。

  • 精准去重统计:通过 count (distinct col) 能够准确地计算出指定列中去除 NULL 值后不重复的行数,这对于分析数据的多样性、统计不同类别或个体的数量等业务场景非常有用。例如,在统计一个用户表中不同地区的用户数量(以地区字段为例)时,使用该语法可以精确得到有多少个不同地区的用户,忽略重复地区以及地区字段为 NULL 的情况,为业务决策提供准确的数据支持,如根据不同地区用户数量进行市场推广资源分配等。

  • 明确多列去重规则:对于 count (distinct col1, col2) 这种多列去重的情况,明确了只要其中一列全为 NULL,就返回 0 的规则,避免了对多列组合去重统计结果的误解,让开发人员能准确把握在多列条件下数据的唯一性情况,正确地进行数据分析和业务逻辑处理,例如在分析具有多维度属性(如产品按品牌和颜色分类统计不同组合的数量)的数据时,依据此规则能得到符合预期的统计结果。

 

\3. 【强制】当某一列的值全是 NULL 时,count(col)的返回结果为 0,但 sum(col)的返回结果为NULL,因此使用 sum()时需注意 NPE 问题。

正例:可以使用如下方式来避免 sum 的 NPE 问题:SELECT IFNULL( SUM(column), 0) FROM table;

  • 清晰数据操作结果:明确了当某一列的值全是 NULL 时,count (col) 返回结果为 0,sum (col) 返回结果为 NULL,这使得开发人员在进行数据统计和聚合操作时,清楚地了解不同函数对 NULL 值的处理方式,避免因不了解而导致的错误预期和后续逻辑错误。例如,在财务报表统计中,如果某一费用项对应的列全为 NULL,使用 count 和 sum 函数能准确得到符合实际情况的结果,便于后续基于正确结果进行数据展示和分析。

  • 避免空指针异常(NPE):由于 sum (col) 在列全为 NULL 时返回 NULL,在后续对该结果进行数值运算或者应用于其他逻辑判断时,很可能引发空指针异常(NPE),导致程序出错。通过使用如 SELECT IFNULL (SUM (column), 0) FROM table 这样的方式,可以将 NULL 值转换为 0,有效避免了 NPE 的发生,保障程序的稳定性和正确性,特别是在复杂的业务逻辑中,涉及多个数据处理步骤和运算时,避免此类异常尤为重要。

 

\4. 【强制】使用 ISNULL()来判断是否为 NULL 值。

说明:NULL 与任何值的直接比较都为 NULL。

1) NULL<>NULL 的返回结果是 NULL,而不是 false。

2) NULL=NULL 的返回结果是 NULL,而不是 true。

3) NULL<>1 的返回结果是 NULL,而不是 true。

反例:在 SQL 语句中,如果在 null 前换行,影响可读性。select * from table where column1 is null and column3 is not null; 而ISNULL(column)是一个整体,简洁易懂。从性能数据上分析,ISNULL(column)执行效率更快一些。

  • 准确判断 NULL 值:NULL 在 SQL 中有其特殊的比较规则,与任何值的直接比较结果都为 NULL,而不是常规的 true 或 false,这使得直接用等号或不等号来判断 NULL 值容易产生错误的判断结果。使用 ISNULL () 函数专门来判断是否为 NULL 值,能够准确地进行 NULL 值的检测,避免因 NULL 值比较逻辑错误导致的数据筛选不准确、查询结果不符合预期等问题,保证 SQL 语句按照正确的逻辑筛选和处理数据。

  • 提高代码可读性与执行效率:从代码可读性角度看,ISNULL (column) 作为一个整体,清晰明了地表达了判断该列是否为 NULL 的意图,相较于复杂的 NULL 值比较表达式(如 NULL = NULL 等容易让人误解的写法)更易于理解。同时,从性能数据上分析,ISNULL (column) 执行效率更快一些,能够在一定程度上提升 SQL 语句整体的执行速度,优化查询性能,减少数据库资源的消耗,提高系统的响应能力。

 

\5. 【强制】代码中写分页查询逻辑时,若 count 为 0 应直接返回,避免执行后面的分页语句。

  • 优化性能,减少不必要操作:在分页查询中,如果通过 COUNT 函数统计出符合查询条件的总行数为 0,意味着没有满足条件的数据需要分页展示,此时直接返回可以避免执行后续复杂的分页相关语句(如涉及 LIMIT 子句等用于获取指定页数据的操作),减少了数据库的不必要计算和资源消耗,特别是在高并发场景下,大量无数据的分页查询如果都执行完整的分页语句,会浪费大量的服务器资源,影响系统整体性能。

  • 提升用户体验:对于用户来说,快速得到没有查询结果的反馈,比等待数据库执行完一系列无用操作后再显示无数据的提示要更好,能够让用户及时知晓当前查询条件下没有数据,避免长时间等待,提高了用户体验,使应用程序的交互更加友好和高效。

 

\6. 【强制】不得使用外键与级联,一切外键概念必须在应用层解决。

说明:(概念解释)学生表中的 student_id 是主键,那么成绩表中的 student_id 则为外键。如果更新学生表中的 student_id,同时触发成绩表中的 student_id 更新,即为级联更新。外键与级联更新适用于单机低并发,不适合分布式、高并发集群;级联更新是强阻塞,存在数据库更新风暴的风险;外键影响数据库的插入速度。

  • 适应分布式、高并发环境:外键与级联更新适用于单机低并发环境,但在分布式、高并发集群环境下,存在诸多问题。比如级联更新是强阻塞的,当更新主表中的外键字段时,会触发相关从表的级联更新操作,在高并发情况下,大量的级联更新请求可能会相互阻塞,形成数据库更新风暴,导致数据库性能急剧下降甚至瘫痪,严重影响系统的可用性和稳定性。

  • 提高插入速度,降低数据库负担:外键的存在会影响数据库的插入速度,因为在插入数据时,数据库需要额外检查外键约束,确保插入的数据符合外键关联关系,这增加了插入操作的开销。在应用层解决外键概念,可以避免这种因外键约束检查带来的性能损耗,让数据库插入操作更加高效,同时也降低了数据库的复杂度和维护成本,便于应对大规模数据和高并发的业务场景。

 

\7. 【强制】禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。

  • 便于调试与维护:存储过程将一系列 SQL 语句封装在数据库端,其内部逻辑相对复杂且不直观,在出现问题时,调试难度较大,不像普通的 SQL 语句可以方便地通过数据库客户端工具查看执行计划、分析语句执行情况等。禁止使用存储过程,采用更清晰的普通 SQL 语句编写业务逻辑,开发人员能够更轻松地定位和解决问题,降低了维护成本,提高了系统的可维护性。

  • 增强可扩展性与移植性:随着业务的发展和变化,应用程序的功能需求可能不断扩展,存储过程的修改相对复杂,不易与其他业务模块协同扩展。而且不同数据库系统对存储过程的语法和支持程度有较大差异,缺乏移植性,不利于在不同的数据库环境中进行应用迁移。使用普通 SQL 语句编写代码则可以更灵活地根据业务变化进行调整,并且更容易在不同数据库间进行移植,保障系统的可扩展性和兼容性。

 

\8. 【强制】数据订正(特别是删除或修改记录操作)时,要先 select,避免出现误删除,确认无误才能执行更新语句。

  • 防止数据误操作:在对数据库中的数据进行删除或修改等订正操作时,直接执行操作语句可能会因为各种原因(如写错条件、对数据范围判断失误等)导致误删除或误修改重要数据,造成不可挽回的损失。先执行 SELECT 语句,按照与后续订正操作相同的条件查询出要操作的数据,开发人员可以仔细核对查询结果是否确实是需要处理的数据,确认无误后再执行更新语句,这是一种谨慎的数据操作方式,能有效避免因人为失误引发的数据安全事故,保障数据的完整性和准确性。

 

\9. 【强制】对于数据库中表记录的查询和变更,只要涉及多个表,都需要在列名前加表的别名(或表名)进行限定。

说明:对多表进行查询记录、更新记录、删除记录时,如果对操作列没有限定表的别名(或表名),并且操作列在多个表中存在时,就会抛异常。

正例:select t1.name from table_first as t1 , table_second as t2 where t1.id=t2.id;

反例:在某业务中,由于多表关联查询语句没有加表的别名(或表名)的限制,正常运行两年后,最近在

某个表中增加一个同名字段,在预发布环境做数据库变更后,线上查询语句出现出 1052 异常:Column 'name' in field list is ambiguous。

  • 避免列名歧义与异常:在多表查询、更新或删除操作中,如果不对操作列使用表的别名(或表名)进行限定,当多个表中存在同名字段时,数据库无法确定具体要操作的是哪个表中的字段,就会抛出异常(如常见的 1052 异常),导致 SQL 语句无法正确执行。通过添加表别名限定列名,可以明确地指定操作的具体对象,确保 SQL 语句按照预期的逻辑准确地处理数据,避免因列名歧义产生的错误和异常情况,保障业务操作的顺利进行。

  • 增强代码可读性与可维护性:即使在当前没有列名冲突的情况下,添加表别名也有助于提高代码的可读性,清晰地展示出每个字段所属的表,方便其他开发人员阅读和理解 SQL 语句的逻辑,尤其是在复杂的多表关联查询和业务逻辑处理中,更易于后续的代码维护和功能扩展。

 

 

10.【推荐】SQL 语句中表的别名前加 as,并且以 t1、t2、t3、...的顺序依次命名。

说明:1)别名可以是表的简称,或者是依照表在 SQL 语句中出现的顺序,以 t1、t2、t3 的方式命名。2)别名前加 as 使别名更容易识别。

正例:select t1.name from table_first as t1, table_second as t2 where t1.id=t2.id;

  • 提升代码可读性:在 SQL 语句中表的别名前加 as,使别名的定义更加清晰明确,让人一眼就能分辨出哪个是表的别名,便于阅读和理解整个 SQL 语句的结构和逻辑。按照 t1、t2、t3、... 的顺序依次命名别名,遵循了一种统一、有序的命名规范,在多表关联查询等复杂语句中,能使代码看起来更加规整、有条理,降低了理解成本,方便开发人员之间的沟通和协作。

  • 便于代码维护与管理:统一的别名命名方式有助于代码的维护和管理,无论是在后续修改 SQL 语句、排查问题还是进行代码审查时,都能依据规范快速定位和理解不同表在语句中的角色,避免因别名命名混乱导致的误解和错误操作,提高了代码的整体质量和可维护性。

 

11.【推荐】in 操作能避免则避免,若实在避免不了,需要仔细评估 in 后边的集合元素数量,控制在 1000 个之内。

  • 性能优化考虑:在 SQL 中,使用 in 操作时,数据库需要对其后边的集合元素逐个进行匹配检查,当集合元素数量过多时,会导致查询性能急剧下降,因为比较的次数会随着元素数量的增加而大幅增加。控制 in 后面集合元素数量在 1000 个之内,可以在一定程度上保证查询性能处于相对合理的水平,避免因大量元素的匹配操作使数据库长时间执行查询语句,提高系统的响应速度,优化用户体验,尤其在数据量较大或者高并发的业务场景下,对性能的影响更为明显。

  • 减少潜在风险:过多的集合元素还可能引发其他潜在问题,比如可能超出数据库对 in 操作的某些限制(不同数据库系统有不同的内部限制参数),导致查询失败或者出现不可预期的错误。合理控制元素数量能够降低这类风险,保障 SQL 语句的稳定性和可靠性,确保业务数据查询操作能够正常进行。

 

12.【参考】因国际化需要,所有的字符存储与表示,均采用 utf8 字符集,那么字符计数方法需要注意。

说明:

SELECT LENGTH("轻松工作"); 返回为 12

SELECT CHARACTER_LENGTH("轻松工作"); 返回为 4

如果需要存储表情,那么选择 utf8mb4 来进行存储,注意它与 utf8 编码的区别。

  • 支持国际化字符存储与展示:采用 utf8 字符集能够很好地兼容各种语言的字符,满足国际化业务需求,使得应用程序可以正确地存储和显示来自不同国家和地区语言的文字内容,无论是中文、英文、日文还是其他语言文字,都可以在数据库中准确地进行处理,扩大了应用程序的适用范围,方便全球用户使用,提升了应用的通用性和国际化水平。

  • 准确进行字符计数:明确了在 utf8 字符集下不同的字符计数方法(如 LENGTH 和 CHARACTER_LENGTH 函数的区别),开发人员可以根据实际需求准确地统计字符数量,避免因字符编码导致的计数错误,比如在进行文本长度限制、文本内容分析等涉及字符数量处理的业务场景中,能够正确地运用合适的函数得到准确的结果,保障业务逻辑的正确执行。同时,对于需要存储表情等特殊字符的情况,选择 utf8mb4 编码来存储,进一步完善了对多样化字符的存储支持,适应更多样的业务内容需求。

 

 

13.【参考】TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少,但 TRUNCATE无事务且不触发 trigger,有可能造成事故,故不建议在开发代码中使用此语句。

说明:TRUNCATE TABLE 在功能上与不带 WHERE 子句的 DELETE 语句相同。

  • 性能优势了解:了解到 TRUNCATE TABLE 比 DELETE 速度快,且消耗的系统和事务日志资源少,这让开发人员清楚其在性能方面的特点,在一些特定的非关键业务场景下(如测试环境中快速清理测试数据等),如果能够确保操作的安全性,可以利用其性能优势来提高数据清理等操作的效率,节省时间和系统资源。

  • 风险防范意识:同时明确它无事务且不触发 trigger 的特性可能带来的风险,比如在正式的生产环境中,如果误操作使用了 TRUNCATE TABLE,由于没有事务回滚机制,一旦执行就无法撤销,可能会导致大量重要数据丢失等严重事故,所以不建议在开发代码中使用此语句,有助于培养开发人员谨慎使用此类有潜在风险操作的意识,保障生产环境数据的安全性和稳定性。

 

遵循这些 SQL 语句规范,能够在编写 SQL 语句时更加科学、合理,提高代码质量,优化数据库性能,同时保障数据的安全性和业务操作的准确性,更好地满足不同业务场景下对数据库操作的需求。

 

标签:语句,count,数据库,查询,详细,SQL,NULL
From: https://blog.csdn.net/qq_62097431/article/details/144158961

相关文章

  • 聚水潭销售出库单数据集成到SQLServer的技术详解
    聚水潭·奇门数据集成到SQLServer的技术案例分享在企业信息化建设中,数据的高效流动和准确对接至关重要。本文将聚焦于一个具体的系统对接集成案例:如何将聚水潭·奇门平台上的销售出库单数据,通过轻易云数据集成平台,可靠地写入到SQLServer数据库中。案例背景本次集成方案名为......
  • 并发编程系列---【数组切割并行查询-解决sql的in超过1000的问题】
    1.问题List<List<Object>>splitList=CollUtil.split(dataList,800);List<User>resultList=newArrayList<>();//使用parallelStream输出切割后的结果,每个子列表的大小splitList.parallelStream().forEach(sublist->{List<User>users=userMa......
  • 31-OpenCVSharp--特征描述之HOG描述符详细使用方法
    专栏地址:《OpenCV功能使用详解200篇》《OpenCV算子使用详解300篇》《Halcon算子使用详解300篇》内容持续更新,欢迎点击订阅1.HOG特征描述符算法概述HOG(HistogramofOrientedGradients)是一种常用于物体检测(如行人检测)的特征描述符,它通过捕捉图像中局部区域的......
  • 28-OpenCVSharp--图像ROI裁剪详细使用方法
    专栏地址:《OpenCV功能使用详解200篇》《OpenCV算子使用详解300篇》《Halcon算子使用详解300篇》内容持续更新,欢迎点击订阅OpenCVSharp图像裁剪selectROI算法详解在计算机视觉中,图像裁剪是非常基础的操作之一,常常用于从图像中提取感兴趣区域(RegionofInter......
  • mysqldump 导出批量忽略某些表的bat脚本
    @echooff::启用了延迟变量扩展,允许在代码块中使用!variable!来访问变量的最新值。setlocalenabledelayedexpansionSETYYYY=%DATE:~0,4%SETMM=%DATE:~5,2%SETDD=%DATE:~8,2%echo%YYYY%-%MM%-%DD%  %TIME%::设置数据库连接信息setDB_USER=rootsetDB_PASSWORD=1234s......
  • 【详细教程】如何下载伯索云学堂上面已购买的视频课程
    前言:很多同学都想知道伯索云学堂视频课程怎么下载,但是伯索云上面已购买的视频课程是不提供直接下载方式的,所以下面就教大家如何下载伯索云学堂上面已购买的视频课程。一、下载器首页输入A回车,再输入伯索云对应序号并按回车,提示登录,再输入Y登录对应的伯索云账号二、此时会有弹窗......
  • Y20030029 Java+微信+SPRINGBOOT+MYSQL+LW+传统文化展示微信小程序的设计与开发 配置
    传统文化展示微信小程序1.项目摘要2.课题开发的背景和意义3.项目功能4.界面展示5.源码获取1.项目摘要基于微信小程序的传统文化展示小程序是一个集合了多种传统文化元素与现代化技术的创新平台。它充分利用了微信小程序的便捷性和普及性,为广大用户提供了一个深入......
  • 关于for循环语句嵌套
    做了半天,才做出来,崩溃。还是练的少。。。。。呜呜呜。进入正题。以题来讲解该知识点。题目是输出**********`#include<stdio.h>intmain(){ inti,j=0,k=0;for(i=1;i<5;i++){ for(j=0;j<=i;j++)if(j<=1){continue;}elseprintf(""); for(k;k<i;k++) ......
  • PostgreSQL技术大讲堂 - 第73讲:AI4DB系列公开课--搭建私域大模型
    ​PostgreSQL技术大讲堂-第73讲,主题:AI4DB系列公开课--搭建私域大模型讲课内容:1、下载Chinese-LLaMA-Alpaca大模型2、创建基于miniconda虚拟环境3、下载基座模型4、安装pip依赖软件包5、启动开源版openai接口6、安装配置ChatGPTNextWeb工具7、测试DBA小助手假如你在为......
  • MySQL数据库写入异常,主库内存溢出,扩容+清理buff/cach!很开门
    MySQL数据库写入异常,主库内存溢出,扩容+清理buff/cach!很开门最近数据出现了两次写入异常报错如下:org.springframework,jdbc.UncategorizedsQlException:PreparedstatementCallback;uncategzed50LExcention[sql语句]TheMysOlserverisrunningwiththe--read-onlyoption......