SQL 自 1987 年以来一直标准化,并保持为 ISO/IEC 9075尽管每个引擎都在顶部添加了自己的方言 - 这正是格式化程序必须解析而不是模式匹配的原因。
我必须审查的最糟糕的查询是关于一个逻辑思想的 340 行:Laravel SaaS 的收入报告,写为一 DB::select() raw string,由三个开发人员在八个月的时间里建立起来,他们每个人对大写有不同的想法,而对换行则没有。在那一面文字墙上的某个地方,a LEFT JOIN 已经悄悄地变成了一个 INNER JOIN refactor的时候,零订单的客户从报告中消失了,bug是一个词,找到它花了一天半的时间- 不是因为逻辑很硬,而是因为查询 无法读取的,而不可读的代码则将其错误隐藏在众目睽睽之下。
Here's 关于SQL的事情:数据库并不关心你的格式化,解析器读 select id,name from users where active=1 並 SELECT id, name FROM users WHERE active = 1 as同一个语句,产生同一个执行计划,同时返回同一个行 格式化SQL纯粹是人类的- 这正是它's值得做的原因,因为人类是审查它的人,在凌晨2点调试它,并在三份工作后继承它可以't skim的查询,是你可以't验证的查询。
安静 SQL 格式化程序 将任何查询 - 从日志粘贴,ORM's调试输出,同事's Slack消息,遗留存储过程 - 一键转换为一致缩进,一致外壳,可复习的SQL。toolz。dev上的完全在您的浏览器中运行,这对于SQL来说比几乎任何其他文本都更重要你'd粘贴到在线工具中,因为生产查询携带你的模式,有时还携带你的数据。
本指南涵盖了如何使用它、实际重要的格式化约定(关键字外壳、缩进和永恒的逗号战)以及格式化程序每天为自己付费的工作流程。
TL;博士: 将任何查询粘贴到 Toolz.dev SQL 格式化程序 and get back consistently indented, keywords cased SQL - 即时,免费,客户端,无注册格式化永远不会改变查询的作用或运行速度;它改变了人类是否可以验证它值得采用的约定:大写关键字,每行一个子句,每个子句下面的缩进,并选择一个逗号样式,停止争论它与。 json格式化程序 对于数据库上方的 API 层和 文本差异工具 用于比较查询的两个版本。
主要特点
一键一致缩进
The格式化器's核心招式:各大项子句- SELECT、 FROM、 WHERE、 GROUP BY、 ORDER BY -开始自己的行,列,条件,并在下面缩进连接 这是"river"结构经验丰富的SQL阅读器扫描通过:眼睛沿着左边缘阅读子句关键字运行,然后潜入哪个子句重要,具有清晰结构评论的60行格式查询 更快 6行未格式化的相比,因为结构正在为你做一半的阅读我的340行恐怖故事将是二十分钟的评论与这种形状 - 改变的连接类型将单独坐在自己的线上,明显错误。
关键词案例标准化
SELECT 对比 select reginally does't对任何数据库都很重要- SQL关键字在标准上是区分大小写的,每种方言都尊重这一点。不过,对于代码库来说,这非常重要,因为混合外壳是视觉噪声,使结构相同的查询看起来不同。大写关键字是较旧的约定,可从编辑器中确定,没有语法突出显示,其中 SELECT 在帽子里 ... the hightering。I仍然写大写 - 关键字弹出到小写标识符,它保留了每个脱光突出显示的上下文:日志,差异,纯文本电子邮件,终端输出格式化程序标准化到您选择的约定,因此由五个人编写的代码库读起来就像是由一个人编写的。
处理 ORM 和日志输出
最需要格式化的查询是人类没有写的查询:Eloquent 和 ActiveRecord 输出、Doctrine's 生成的连接、慢速查询日志中的单行怪物。 ORM 输出以机器生成的别名的一行形式到达(t0、 t1、 laravel_reserved_0),而原始阅读是你头痛的方法。我最频繁使用格式化程序的一个:从 Laravel's 查询日志或望远镜中抓取查询,对其进行格式化,然后实际查看 ORM 决定做什么 - 这是每个"的第一步为什么这个端点很慢"调查,就在之前 EXPLAIN。
多方言宽容
现实世界的 SQL 是一个方言系列:MySQL's 反向引用标识符、PostgreSQL's 双引号和 :: casts, SQL Server's 方括号和 TOP,SQLite's easygoing everything。一个有用的格式化程序处理所有这些,而不需要你先声明一个方言,保留了特定于方言的语法而不是"纠正"它。ANSI/ISO SQL标准(ISO/IEC 9075)定义了公共核心,但实际上没有人编写纯标准SQL,只说标准的格式化程序会在第一个回击时窒息。
保留语义,保证
Worth明确指出,因为它's阻止人的恐惧:格式化不能改变结果空白和关键字大小写在SQL中不是语义的 - 一个历史警告是 字符串文字 case敏感或不依赖于您的整理进行比较,并且格式化程序永远不会触及您引用的字符串的内部,输出是相同的语句,字节对字节,其中字节很重要。运行 EXPLAIN 如果您想查看,两个版本上都有相同的计划。
客户端,这在这里实际上很重要
SQL 是最敏感的文本类别,通常会被粘贴到在线工具中,查询会显示您的模式 - 表名、列名、关系 - 以及从日志中复制的查询经常包含字面值:电子邮件 in WHERE 子句、ID 范围,偶尔是根本不应该出现在查询字符串中的东西。 Toolz.dev 格式化程序 处理浏览器中的所有内容;没有传输任何内容。对于 SQL 来说,I'd 调用客户端处理是要求,而不是功能 - 在网络选项卡中验证它,然后放松。
如何使用 SQL 格式化程序
1步:捕获查询
SQL从其来源复制:您的迁移文件,存储过程,ORM's调试输出(DB::listen() 或拉拉维尔的望远镜, ActiveRecord::Base.logger rails 中)、慢速查询日志,或者你的 APM 工具的查询选项卡,如果来自日志,它可能已经转义了报价或参数占位符(?、 $1) - that's很好,格式化程序处理占位符,并且清楚地看到它们通常是重点。
2步:粘贴和格式
打开 SQL格式化程序、粘贴,出现格式化版本,没有方言仪式,不需要配置即可获得良好的默认值,如果您的查询包含多个由分号分隔的语句,它们会格式化为单独的语句 - 对阅读整个迁移脚本很有用。
3步:像评论者一样阅读它
现在是否存在格式化的内容:扫描左边缘。哪些表被连接,哪些连接类型?是 WHERE 条款具有您期望的条件 - 并且是 AND/OR 分组以您的方式括号 想 他们分组? (SQL 推杆中的操作员优先级) AND 之前 OR(而两者的未加括号的混合是我回顾中看到的第二大错误源,紧接着错误的加入类型。)格式化的 SQL 使两个错误在几秒钟内可见。
第 4 步:有选择地将其复制回来
对于进入代码库的查询,请将格式化的版本复制到迁移中 ->select() 原始表达式, .sql file。t一次性调试,don't费心往返;格式化的副本在你读完的那一刻就达到了目的。一处 不是 to paste格式化的SQL:回到将查询存储为配置字符串的系统中,其中某人's diff工具现在将显示一面空白变化的墙。用于始终读取的格式;仅在您'准备拥有diff时重新格式化存储的查询。
5步:规范团队公约
Formatter's最大的价值是复合:选择可以自动化的约定-关键字大小写和缩进宽度是这个格式化程序直接控制的两个-格式化进入代码库的路上所有新的东西,SQL审查摩擦永久下降在你的贡献指南中写下选择。选择的具体约定远少于使用同一条的每个人-这句话在软件中的每一次格式化辩论中都是真实的,并且在辩论中大约没有人相信。
技术深度潜水:值得发表意见的公约
关键词外壳。 Uppercase关键字,小写标识符是占主导地位的约定和我的推荐论证是't传统-it's鲁棒性语法突出显示消失在日志,终端,代码审查评论和堆栈溢出答案粘贴到Slack;大写关键字突出显示与文本一起旅行的反驳论证(小写一切,让编辑器突出显示)是连贯的和I've工作在代码库中快乐地使用它什么's不连贯的是混合,这是你得到的没有格式化程序强制选择。
每行一个子句,缩进内容。 收益最高的结构性规则。 SELECT 开始一行;它的列在下面缩进(如果短则在同一行)。每个 JOIN 与它有自己的线条 ON 条件可见 - 隐藏在中线的连接条件是错误连接错误隐藏的地方。 WHERE 条件每行堆叠一根,对齐,与 AND/OR leading 每行所以逻辑结构垂直读取 当查询's 条件读为列时,缺失的条件可见为 a 图案中的间隙的,哪只人的眼睛特别擅长点睛。
逗号战。 尾(每列之后)自然读取;前导逗号(每列之前,行首)使标点结构:
-- Trailing (most common)
SELECT
u.id,
u.email,
o.total
-- Leading (the DBA classic)
SELECT
u.id
, u.email
, o.total
Leading-comma 倡导者有两个真正好的观点:评论除第一行之外的任何行都不会破坏语句,并且在左边距处立即可见缺失的逗号。Trailing-comma 倡导者有一个:它看起来像你写的每一种语言。我写尾随逗号,并且已经不再对此感到难过 - 但请注意,与现代 JavaScript 或 Python 不同,SQL 确实如此 不是 final列后原谅一个悬空逗号,这就是为什么这场争论根本存在,以及为什么dba圈子里领先风格拒绝死去 全面披露:toolz。dev格式化程序采取主流的一面,并发出尾随逗号- 它没有领先逗号模式,所以如果你're一个忠诚的领先逗号商店这是它赢得的一个约定't为你重新格式化。选择一个房子风格,持续应用,然后继续前进。
格式化不做什么。 它没有't优化。一种格式化 SELECT * 跨五表连接是一个漂亮的缩进性能问题。格式化是 前提条件 对于优化 - 您无法对无法读取的查询进行推理 - 但推理仍然需要 EXPLAIN、索引意识,并了解你的数据's形状,我认为管道是:格式,读, EXPLAIN然后优化。跳过步骤一并不't让你更快;它使步骤二到四变得更慢。同一学科在 API 上应用一层,这就是为什么 JSON 格式化程序指南 对有效载荷进行结构相同的论证。
评论得以保留。 与最小化不同,格式化保留注释 - -- 行评论和 /* */ 块完好无损地通过。使用它们。A -- deliberately LEFT JOIN: include customers with no orders 加入上方的评论是有史以来最便宜的错误保险,它's 我的 340 行恐怖故事所需的评论。
常见用例
代码审查
Pull请求中的未格式化SQL是一个审查,它是不't将发生-审查者's眼睛滑落的文本墙,批准着陆无论如何,格式化查询之前打开PR是基本的礼貌与可衡量的回报:加入类型,条件分组和列列表变得单独可见,这意味着它们变得单独可审查每一个真正的SQL错误I've陷入审查-错误的加入,未加括号 OR的,该 DELETE 缺少一半 WHERE clause - 我抓住了,因为查询的格式足够好,可以逐行读取。
调试 ORM 生成的查询
ORM很精彩直到终点很慢,在这一点上你需要看到实际的SQL - 并且ORM输出总是有一条密集的线格式化它,故事出现:急切加载错过的N + 1,加入关系定义默默添加,的 ORDER BY on a unindexed 列。在拉拉维尔的作品中这是一个每周几次的仪式:望远镜,复制, 格式、绞杀、修复口才代码、重复。格式化程序不't诊断任何东西本身;它使查询足够清晰 你 能。
关于遗产查询的考古学
2015年的存储过程,报告视图没人敢碰,与原作者's格式化嵌入配置文件中的查询(即无),在修改遗留SQL之前,格式化它,端到端读取它- you'll例行性地找到条件,可以't永远为真,加入到不再接收写入的表中,逻辑当前团队's假设相矛盾,格式化第一回合"可怕的遗留查询"变成"长但易读的查询,"这是一个不同且更好的问题。
比较查询版本
Report's的数字在发布之间发生变化时,问题是"查询中发生了什么变化,"并且答案需要区分两个版本 - 只有当两者首先格式相同时,才可以对两者进行相同的设置格式化,然后通过运行它们 文本差异工具:噪音消失,两条变换的线条独立,这个确切的序列找到了我的内接bug,最终,我现在做到了 之前 一天半的混乱而不是之后。
教学和文档
SQL在教程,运行簿和内部文档中阅读次数比编写次数多得多,由对模式不太熟悉的读者而不是作者。带有大写关键字和每行一个概念结构的格式化示例极易学习 - 结构与内容一起教学。当我编写带有嵌入式查询的文档时,每个人都会首先通过格式化程序;docs中的未格式化SQL告诉读者作者没有't期望任何人真正阅读它。
格式化约定比较
| 公约选择 | A选项 | B选项 | 我的接受 |
|---|---|---|---|
| 关键词案例 | SELECT (大写字母) |
select (小写) |
大写 - 在不突出显示的情况下保留上下文 |
| 标识符情况 | 蛇_案例 | 匹配表定义 | 匹配定义;永远不要与模式作斗争 |
| 逗号 | 尾随(id,) |
领先(, id) |
落后,但领先是可以防御的--只要选择一个 |
| 子句布局 | 每行一个子句 | 紧凑的单线 | 每行一个,用于任何过去的琐碎事物 |
AND/OR 安置 |
领先每个条件行 | 尾随前一行 | 领先 - 逻辑垂直读取 |
| 加入条件 | ON 在自己的线上或内联 JOIN |
埋在中线 | 始终通过连接可见 |
| 缩进宽度 | 2 个空格 | 4 个空间 | 要么; SQL 嵌套小于 JSON,所以这里 4 就可以了 |
这些行都没有错误的答案,而 that's 正是陷阱 - 因为每个选项都是可以防御的,团队会永远重新提起诉讼,除非格式化程序使决策机械地获胜,这招很无聊:选择、配置、格式化所有内容,并将回收的论证时间花在影响执行计划的事情上。对于围绕此工具包的日常工具包的其余部分,请参阅 编码工具指南 而且范围更广 web开发人员工具包。
常问问题
SQL格式化程序做什么?
SQL 格式化程序将查询's 的空白、换行和关键字外壳重写为一致的、可读的结构- 每个子句在自己的行、条件和列上缩进,关键字标准化为一个情况,语句's 的含义是未被触及的:SQL 解析器完全忽略格式化,因此格式化的查询返回相同的结果,执行计划相同,更改纯粹是针对审查、调试和维护查询的人类。
SQL格式化会改变查询性能吗?
No。Whitespace和关键字大小写在SQL中不是语义的- 数据库将两个版本解析成相同的内部表示,并产生相同的执行计划,您可以通过运行来验证 EXPLAIN on each。formating是性能工作的先决条件而不是性能工作本身:你可以't关于索引的理由,并在查询中加入顺序你可以't读取。
SQL关键字应该是大写还是小写?
2个都是有效的- SQL关键字按照标准是不区分大小写的- 所以这是一个可读性约定,而不是正确性规则。大写关键字(SELECT、 FROM、 WHERE()仍然是最常见的选择,因为它们在剥离颜色的上下文中充当内置突出显示:日志、差异、终端和纯文本消息。无论您选择哪个,整个代码库的一致性都远远不止选择本身。
SQL中的前导逗号是什么,人们为什么要使用它们?
Leading-comma 样式将逗号放置在每列行的开头 (, email)而不是前一个的结尾。倡导者喜欢它,因为评论除第一个之外的任何列都不会产生语法错误,并且缺少的逗号在左边距处立即可见 - 真正的优势,因为SQL不't容忍像现代JavaScript那样在最后一个列之后悬空逗号。尾随逗号仍然更常见;如果一致应用,则任一都有效。
我可以格式化由 Eloquent 或 ActiveRecord 等 ORM 生成的 SQL 吗?
Yes, and it's格式化器的最佳用途之一-ORM调试输出以单一密集线的形式到达,带有机器生成的别名,并且格式化它是诊断慢端点和N + 1问题的第一步。从您的ORM's日志记录(拉拉维尔望远镜,ActiveRecord日志)中捕获查询,将其粘贴到 SQL格式化程序并在到达之前阅读 ORM 实际构建的内容 EXPLAIN。
格式化程序是否适用于 MySQL、PostgreSQL 和 SQL Server 语法?
是的 - 实用的格式化程序处理主要方言'怪癖,保留 MySQL 反向标记、PostgreSQL 双引号标识符和 :: casts,而 SQL Server 方括号而不是重写它们,ANSI SQL 标准定义了共享核心,但没有生产数据库说的是纯标准 SQL,因此方言容差是格式化程序在真实查询上有用的要求。
将生产查询粘贴到在线 SQL 格式化程序中安全吗?
仅进入客户端,因为 SQL 异常敏感:查询会暴露您的模式,而从日志复制的查询通常包含电子邮件或 ID 等字面值 WHERE 条款。 Toolz.dev SQL 格式化程序 处理浏览器中的所有内容,不传输或存储任何内容 - 在粘贴时通过查看网络选项卡自行验证。避免生产中任何基于服务器的格式化程序。
格式化是否保留 SQL 注释?
是的--两者都有 -- 行评论和 /* */ block注释完整地通过,不像minification那样删除它们,这使得格式化对于注释带有意图的带注释的查询和存储过程是安全的。使用那个:解释故意的一行注释 LEFT JOIN 或者一个不寻常的情况是对下一个开发人员最便宜的保护"修复"一些东西被't打破了。



