SQL 自 1987 年起就已標準化並維持為 ISO/IEC 9075,儘管每個引擎都在上面添加了自己的方言 - 這正是格式化程式必須解析而不是模式匹配的原因。
我必須審查的最糟糕的查詢是關於一個邏輯思想的 340 行:一份 Laravel SaaS 的收入報告,寫成一份 DB::select() 原始字串,由三位開發人員在八個月內建立,他們每個人對大寫都有不同的想法,對換行沒有不同的想法。在那堵文字牆的某個地方,a LEFT JOIN 悄悄地變成了一個 INNER JOIN 在重構過程中,零訂單的客戶從報告中消失了。錯誤是一個字。找到它花了一天半的時間--不是因為邏輯很難,而是因為查詢是 難以讀懂,無法讀取的程式碼將其錯誤隱藏在眾目睽睽之下。
這裡'關於 SQL 的事情是:資料庫不關心您的格式。解析器讀取 select id,name from users where active=1 和 SELECT id, name FROM users WHERE active = 1 作為相同的語句,產生相同的執行計劃,同時傳回相同的行。格式化 SQL 純粹是為人類準備的 - 這正是它的原因'值得做,因為人類是審查它的人,凌晨 2 點調試它,然後繼承三個作業。您可以't skim 查詢是您可以't 驗證的查詢。
一個 SQL 格式化程式 將任何查詢(從日誌、ORM' 貼上)轉換為一鍵式一致縮排、一致大小寫的、可審查的 SQL。 toolz。dev 上的一個完全在您的瀏覽器中運行,這對於 SQL 比幾乎任何其他文字都更重要,you'd 貼上到線上工具中,因為生產查詢攜帶您的架構,有時還攜帶您的資料。
本指南涵蓋如何使用它、實際重要的格式約定(關鍵字大小寫、縮排和永恆的逗號戰爭)以及格式化程式每天為自己付費的工作流程。
TL;DR: 將任何查詢貼上到 Toolz.dev SQL 格式化程式 並返回一致縮排的關鍵字大小寫 SQL - 即時、免費、客戶端、無註冊。格式永遠不會改變查詢的作用或運行速度;它會改變人類是否可以驗證它。值得採用的約定:大寫關鍵字,每行一個子句,在每個子句下縮進,然後選擇逗號樣式並停止爭論。與配對 json 格式化程式 對於資料庫上方的 API 層 文字差異工具 用於比較查詢的兩個版本。
主要特點
一鍵一致縮排
formatter's 核心移動:每個主要子句 - SELECT, FROM, WHERE, GROUP BY, ORDER BY - 開始自己的行,列、條件,並在下面縮排連接。這是"河流&報價;結構體驗 SQL 閱讀器掃描依據:眼睛沿著左邊緣向下延伸,閱讀子句關鍵字,然後深入研究任何重要的子句。 60 行格式化查詢,結構評論清晰 更快 比 6 行未格式化的故事,因為結構為您完成了一半的閱讀。我的 340 行恐怖故事將是一個 20 分鐘的評論,採用這種形狀 - 更改的連接類型將單獨坐在自己的行上,顯然是錯誤的。
關鍵字案例標準化
SELECT 與 select 確實不'對任何資料庫都很重要 - 根據標準,SQL 關鍵字不區分大小寫,每種方言都尊重這一點。不過,這對程式碼庫來說非常重要,因為混合大小寫是視覺噪聲,它使結構相同的查詢看起來不同。大寫關鍵字是較舊的約定,可以追溯到沒有語法突出顯示的編輯器,其中 SELECT 在帽子裡 是 突出顯示。我仍然寫大寫 - 關鍵字彈出到小寫標識符上,並且它可以在剝離突出顯示的每個上下文中保留:日誌、差異、純文字電子郵件、終端輸出。格式化程式會根據您選擇的約定進行標準化,因此由五個人編寫的程式碼庫讀起來就像由一個人編寫一樣。
處理 ORM 和日誌輸出
最需要格式化的查詢是無人寫的查詢:Eloquent 和 ActiveRecord 輸出,Doctrine'產生的連接,慢速查詢日誌中的單行怪物。 ORM 輸出以一行形式到達,並帶有機器產生的別名 (t0, t1, laravel_reserved_0),原始閱讀它就是你頭痛的原因。我最常使用的格式化程式:從 Laravel' 取得查詢;查詢日誌或望遠鏡,格式化它,然後實際查看 ORM 決定做什麼 - 這是每個 " 的第一步;為什麼這個端點很慢&引用;調查,就在之前 EXPLAIN.
多方言耐受性
Real-world SQL 是一個方言家族:MySQL's 反引號引用標識符,PostgreSQL's 雙引號和 :: 演員表、SQL Server's 方括號和 TOP,SQLite'一切都很輕鬆。有用的格式化程式可以處理所有這些,而無需您先聲明方言,保留方言特定的語法而不是"更正和引用;它。 ANSI/ISO SQL 標準 (ISO/IEC 9075) 定義了公共核心,但在實踐中沒有人編寫純標準 SQL,並且只講該標準的格式化程式會在第一個反向點擊時阻塞。
保留語意,保證
值得明確說明,因為它'是阻止人們的恐懼:格式化無法改變結果。空白和關鍵字大小寫在 SQL 中不是語意的 - 歷史上的警告是這一點 字串文字 根據您的校對進行區分大小寫的比較,格式化程式永遠不會觸及所引用字串的內部。輸出是相同的語句,逐字節,其中位元組很重要。跑步 EXPLAIN 如果您想查看兩個版本:相同的計劃。
客戶端,這實際上在這裡很重要
SQL 是最敏感的文字類別,通常會貼到線上工具中。查詢會顯示您的模式 - 表名、列名、關係 - 從日誌複製的查詢通常包含文字值:電子郵件 WHERE 子句、ID 範圍,偶爾會出現根本不應該出現在查詢字串中的內容。這 toolz。dev 格式化程式 處理瀏覽器中的所有內容;什麼都沒有傳輸。特別是對於 SQL,I'd 呼叫客戶端處理需求,而不是功能 - 在網路標籤中驗證它,然後放鬆。
如何使用 SQL 格式化程式
第 1 步:擷取查詢
從 SQL 的來源複製 SQL:您的遷移檔案、預存程序、ORM's 調試輸出 (DB::listen() 或拉拉維爾的望遠鏡, ActiveRecord::Base.logger 在 Rails 中,APM 工具的慢速查詢日誌或查詢標籤。如果它來自日誌,它可能已轉義引用或參數佔位符 (?, $1) - 那'好吧,格式化程式處理佔位符,清楚地看到它們通常是重點。
第 2 步:貼上和格式
打開 SQL 格式化程式,貼上,格式化版本出現。沒有方言儀式,不需要配置即可獲得良好的預設值。如果您的查詢包含多個由分號分隔的語句,它們會格式化為單獨的語句 - 對於閱讀整個遷移腳本很有用。
第三步:像審稿人一樣閱讀
現在存在以下格式化嗎:掃描左邊緣。哪些表被連接,以及哪些連接類型?有 WHERE 條款具有您期望的條件 - 並且確實如此 AND/OR 分組以您的方式括起來 想 他們分組? (SQL 中的運算子優先權放置 AND 之前 OR,兩者的未括號混合是我在評論中看到的第二大錯誤來源,就在錯誤的連接類型之後。)格式化的 SQL 使這兩個錯誤在幾秒鐘內可見。
第 4 步:選擇性地將其複製回來
對於進入程式碼庫的查詢,請將格式化版本複製到遷移中 ->select() 原始表達,the .sql 文件。對於一次性調試,don'不要費心往返;格式化的副本在您閱讀的那一刻就達到了其目的。一個地方 不是 將格式化的 SQL: 貼上回將查詢儲存為設定字串的系統,其中 something's diff 工具現在將顯示空白牆變更。始終讀取的格式;僅在您'準備好擁有差異時重新格式化儲存的查詢。
第 5 步:標準化團隊約定
格式化程式'最大的價值是複合:選擇您可以自動化的約定- 關鍵字大小寫和縮排寬度是此格式化程式直接控制的兩個- 格式化進入程式碼庫的所有新內容,並且SQL 審查摩擦力永久下降。在您的貢獻指南中寫下選擇。所選的具體約定遠不如使用相同約定的每個人都重要 - 這句話適用於軟體中的每次格式化辯論,並且在辯論中幾乎沒有人相信。
技術深度潛水:值得發表意見的會議
關鍵字外殼。 大寫關鍵字、小寫識別碼是主要的約定,也是我的建議。參數是't 傳統 - it's 穩健性。語法突出顯示在日誌、終端、程式碼審查註釋和貼上到 Slack 中的堆疊溢位答案中消失;大寫關鍵字是突出顯示與文字一起傳播的。反駁(所有內容都小寫,讓編輯突出顯示)是連貫的,I'曾在快樂地使用它的人工資料庫中工作過。 What'不連貫的是混合,這是沒有格式化程式強制選擇的情況下得到的。
每行一個子句,縮排內容。 回報最高的結構性規則。 SELECT 開始一條線;它的列在下面縮排(如果短則在同一行上)。每個 JOIN 有自己的路線 ON 條件可見 - 連接條件隱藏在中線是錯誤連接錯誤隱藏的地方。 WHERE 條件每行堆疊一個,對齊,與 AND/OR 引導每一行,以便邏輯結構垂直讀取。當查詢's 條件讀作列時,缺失的條件可見為 a 圖案中的間隙,人眼非常擅長發現哪些。
逗號戰爭。 後置逗號(每列之後)自然閱讀;前導逗號(每列之前、行開頭)使標點符號結構化:
-- Trailing (most common)
SELECT
u.id,
u.email,
o.total
-- Leading (the DBA classic)
SELECT
u.id
, u.email
, o.total
前置逗號倡導者有兩個真正好的觀點:評論除第一行之外的任何行都不會破壞語句,並且缺失的逗號在左邊距處立即可見。尾隨逗號倡導者有一個:它看起來就像你寫的所有其他語言。我寫尾隨逗號並且不再對此感到難過 - 但請注意,與現代 JavaScript 或 Python 不同,SQL 確實如此 不是 請原諒最後一欄後有一個懸空的逗號,這就是為什麼這場爭論根本存在,也是為什麼主導風格拒絕在 DBA 圈子中消亡。全面揭露:toolz。dev 格式化程式站在主流一邊並發出尾隨逗號 - 它沒有前導逗號模式,所以如果您'是一家忠誠的前導逗號商店,這是它贏得的一個約定'為您重新格式化。選擇房屋風格,一致應用,然後繼續前進。
格式化不做什麼。 它沒有't 優化。格式化 SELECT * 跨越五桌連接是一個精美縮排的性能問題。格式是 前提條件 對於最佳化 - 您無法對無法讀取的查詢進行推理 - 但推理仍然需要 EXPLAIN,索引意識,了解您的資料's 形狀。我認為管道是:格式、讀取、 EXPLAIN,然後優化。跳過第一步並#39;它會讓你更快;它會使第二步到第四步變慢。相同的規則在 API 上應用一層,這就是原因 JSON 格式化程式指南 對有效負載提出結構相同的論點。
評論得以保留。 與縮小不同,格式化保留註釋 - -- 行註釋和 /* */ 塊完好無損地通過。使用它們。 A -- deliberately LEFT JOIN: include customers with no orders 上面的評論是有史以來最便宜的錯誤保險,它'這是我的 340 行恐怖故事所需的評論。
常見用例
代碼審查
拉取請求中未格式化的 SQL 是 ' 的評論;不會發生 - 審稿人'無論如何,眼睛都會從文字牆上滑落,批准就會落地。在開啟 PR 之前格式化查詢是基本的禮貌,具有可衡量的回報:連接類型、條件分組和列列表變得單獨可見,這意味著它們變得可以單獨審查。每個真正的 SQL bug I'都陷入了審查--加入錯誤,未括號 OR, DELETE 缺了一半 WHERE 子句 - 我發現是因為查詢格式足夠好,可以逐行讀取。
調試 ORM 產生的查詢
ORM 非常棒,直到終點變慢,此時您需要看到實際的 SQL - 並且 ORM 輸出始終是一行密集。格式化它,故事就會出現:急切載入錯過的 N+1,默默添加的連接關係定義, ORDER BY 在未索引的列上。在 Laravel 的作品中,這是每週幾次的儀式:望遠鏡,複製, 格式,眨眼,修復雄辯的程式碼,重複。格式化程式不會't自行診斷任何事物;它使查詢足夠清晰 你 可以。
遺留查詢考古學
每個長壽命的系統都有它們:2015年的預存程序、沒人敢觸摸的報告視圖、嵌入到原作者配置文件中的查詢'格式化(即,無)。在修改舊版 SQL 之前,對其進行格式化並首尾相連地讀取 - you'通常會找到 can'tever be true 的條件,加入不再接收寫入的表格,並對目前團隊進行邏輯'假設相矛盾。格式化第一回合&引用;可怕的遺留查詢&引用;進入&引用;長而清晰的查詢&引用;這是一個不同且更好的問題。
比較查詢版本
當報告's 數字在版本之間變化時,問題是 "查詢中發生了什麼變化,"答案需要區分兩個版本 - 只有當兩個版本首先格式相同時才有效。使用相同的設定格式化兩者,然後將它們運行 文字差異工具:噪音消失,兩條改變的線路獨立存在。這個精確的序列最終發現了我的內部連接錯誤。我現在就做 之前 一天半的混亂而不是之後。
教學和文獻
教學、運行手冊和內部文件中的 SQL 被閱讀的次數比編寫次數多得多,讀者對模式的熟悉程度不如作者。具有大寫關鍵字和每行一個概念結構的格式化範例更容易學習 - 該結構與內容一起教授。當我編寫帶有嵌入式查詢的文件時,每個人都會先瀏覽格式化程式;文件中未格式化的 SQL 告訴讀者作者沒有'希望有人真正閱讀它。
格式化約定進行比較
| 公約選擇 | 選項a | 選項b | 我的看法 |
|---|---|---|---|
| 關鍵字案例 | SELECT (大寫) |
select (小寫) |
大寫 - 在上下文中保留而不突出顯示 |
| 標識符大小寫 | 蛇案 | 匹配表定義 | 匹配定義;永遠不要與模式戰鬥 |
| 逗號 | 尾隨(id,) |
領先 (, id) |
落後,但領先是可以防守的--只要選一個 |
| 子句佈局 | 每行一個子句 | 緊湊型單線 | 過去瑣碎的事情每行一個 |
AND/OR 安置 |
引領每條條件線 | 尾隨上一條線 | 領先 - 邏輯垂直讀取 |
| 加入條件 | ON 在自己的線上或內聯 JOIN |
埋在中線 | 連接時始終可見 |
| 縮排寬度 | 2 個空間 | 4 個空間 | 要嘛; SQL 嵌套小於 JSON,因此 4 在這裡很好 |
這些行都沒有錯誤的答案,並且#39;正是陷阱 - 因為每個選項都是可以防禦的,所以團隊會永遠重新訴訟它們,除非格式化者做出機械決定。獲勝的舉動很無聊:選擇、配置、格式化所有內容,並將回收的爭論時間花在影響執行計劃的事情上。有關此工具包的其餘日常工具包,請參閱 編碼工具指南 而且更廣泛 web 開發人員工具包.
問號
SQL 格式化程式的作用是什麼?
SQL 格式化程式重寫查詢'將空格、換行符和關鍵字外殼轉換為一致的、可讀的結構 - 每個子句都有自己的行、縮排的條件和列,關鍵字標準化為一個情況。語句'其含義未受影響:SQL 解析器完全忽略格式化,因此格式化的查詢傳回具有相同執行計畫的相同結果。此變更純粹針對審查、調試和維護查詢的人。
格式化 SQL 會改變查詢效能嗎?
不,SQL 中的空白和關鍵字大小寫不是語義的 - 資料庫將兩個版本解析為相同的內部表示並產生相同的執行計劃,您可以透過運行來驗證 EXPLAIN 在每一個上。格式化是效能工作而不是效能工作本身的先決條件:您可以't 推理索引並在查詢中加入順序您可以't 閱讀。
SQL 關鍵字應該是大寫還是小寫?
兩者都是有效的 - 根據標準,SQL 關鍵字不區分大小寫 - 所以這是一個可讀性約定,而不是正確性規則。大寫關鍵字(SELECT, FROM, WHERE) 仍然是最常見的選擇,因為它們在剝離顏色的上下文中充當內建突出顯示:日誌、差異、終端和純文字訊息。無論您選擇哪一個,程式碼庫的一致性都比選擇本身更重要。
SQL 中的前導逗號是什麼?為什麼人們使用它們?
前導逗號樣式將逗號放在每列行的開頭 (, email)而不是前一列的結尾。倡導者喜歡它,因為評論除第一列之外的任何列都不會產生語法錯誤,並且丟失的逗號在左邊距處立即可見 - 真正的優勢,因為 SQL 沒有'不要像現代 JavaScript 那樣容忍最後一列之後的懸空逗號。尾隨逗號仍然更常見;如果應用一致,則任一都有效。
我可以格式化由 Eloquent 或 ActiveRecord 等 ORM 產生的 SQL 嗎?
是的,它'格式化器的最佳用途之一 - ORM 偵錯輸出以帶有機器生成別名的單一密集行形式到達,對其進行格式化是診斷慢速端點和 N+1 問題的第一步。從 ORM's 記錄中擷取查詢(Laravel Telescope、ActiveRecord 日誌),將其貼上到 SQL 格式化程式,並在伸手之前閱讀 ORM 實際建構的內容 EXPLAIN.
格式化程式是否適用於 MySQL、PostgreSQL 和 SQL Server 語法?
是的 - 實用格式化程式處理主要方言'怪癖,保留 MySQL 反引號、PostgreSQL 雙引號識別碼和 :: casts 和 SQL Server 方括號而不是重寫它們。 ANSI SQL 標準定義了共享核心,但沒有生產資料庫會講純標準 SQL,因此方言容差是格式化程式對真實查詢有用的要求。
將生產查詢貼上到線上 SQL 格式化程式中安全嗎?
僅針對客戶端,因為 SQL 異常敏感:查詢暴露您的模式,並且從日誌複製的查詢通常包含文字值,例如電子郵件或 ID WHERE 條款。這 Toolz.dev SQL 格式化程式 處理瀏覽器中的所有內容,不傳輸或儲存任何內容 - 在貼上時透過查看網路標籤自行驗證。避免生產過程中出現任何基於伺服器的格式化程式。
格式化會保留 SQL 註釋嗎?
是的--兩者都有 -- 行註釋和 /* */ 阻止評論完好無損地通過,這與縮小不同,縮小會刪除它們。這使得格式對於註釋具有意圖的註釋查詢和預存程序是安全的。使用它:解釋故意的一行評論 LEFT JOIN 或者,不尋常的情況是針對下一個開發人員的最便宜的保護"修復"是't 損壞的東西。



