惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
腾讯CDC
T
Threatpost
L
Lohrmann on Cybersecurity
P
Proofpoint News Feed
The Cloudflare Blog
博客园 - 聂微东
MyScale Blog
MyScale Blog
M
MIT News - Artificial intelligence
Hacker News - Newest:
Hacker News - Newest: "LLM"
S
SegmentFault 最新的问题
博客园 - 三生石上(FineUI控件)
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Project Zero
Project Zero
Simon Willison's Weblog
Simon Willison's Weblog
S
Schneier on Security
Spread Privacy
Spread Privacy
The GitHub Blog
The GitHub Blog
D
DataBreaches.Net
S
Securelist
Schneier on Security
Schneier on Security
Microsoft Azure Blog
Microsoft Azure Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Cisco Talos Blog
Cisco Talos Blog
博客园 - 叶小钗
量子位
I
InfoQ
J
Java Code Geeks
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
人人都是产品经理
人人都是产品经理
博客园_首页
C
CERT Recently Published Vulnerability Notes
I
Intezer
Y
Y Combinator Blog
T
Tailwind CSS Blog
Microsoft Security Blog
Microsoft Security Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
大猫的无限游戏
大猫的无限游戏
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
A
About on SuperTechFans
A
Arctic Wolf
阮一峰的网络日志
阮一峰的网络日志
P
Proofpoint News Feed
G
Google Developers Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
Vercel News
Vercel News
PCI Perspectives
PCI Perspectives
The Last Watchdog
The Last Watchdog
月光博客
月光博客

中文博客 on 范叶亮 | Leo Van

多智能体系统 (Multi-Agent System) 确定性和掌控欲 - 你的 AI 不是你的 AI LLM Token 消耗节省计划 (How to Save Token for LLM) 智能体的角色定位和身份演化 (Agent Role Orientation and Identity Evolution) 本地部署 OpenClaw,QwenPaw 和 Hermes Agent (Local Deployment of OpenClaw, QwenPaw and Hermes Agent) 本地部署智能体 - OpenClaw,QwenPaw,Hermes Agent ... 部署 Matrix 服务器 Synapse (Deployment of Matrix Server Synapse) 部署 frp 内网穿透服务 (Deployment of frp NAT Traversal Service) 本地部署大模型服务 (Local Deployment of LLM Services) AI 时代的生产力和生产关系 (Forces and Relations of Production in AI Era) 业余无线电入门 - CQ, CQ, CQ, this is BD1CZP. Calling CQ and standing by. 重构 - 之于代码、之于工作、之于生活 大语言模型微调 (Fine-tuning Large Language Models) 提升图片分辨率和质量 - Invoke AI 101 教程 使用画布创建和组合生成新的图片 - Invoke AI 101 教程 探索 AI 模型和概念适配器 - Invoke AI 101 教程 理解图像到图像和降噪过程 - Invoke AI 101 教程 使用控制层和指示控制图片的生成 - Invoke AI 101 教程 使用 Invoke 创作你的第一张图片 - Invoke AI 101 教程 在 OpenWrt 和群晖中自动申请和部署证书 凡人歌 - 凡人,但不要烦心 Shell 调用方式 fork,exec 和 source (Run Shell with fork, exec and source) 重定向和管道 (Redirect and Pipe) 模型压缩和推理加速 (Model Compression and Inference Acceleration) 我们需要多少种编程语言 (How Many Programming Languages do We Need) 数据可视化小贴士 - 面向动态文档生成,秉承规范、统一和实用的理念 从 rm -rf * 说起 - 喜新、怀旧、再出发 当我谈摄影时,我谈些什么 - 色彩篇 Part 1 CSS 布局和定位 (CSS Layout and Position) 当我谈修图时,我谈些什么 - 色彩篇 Part 1 在 Windows 下利用 WSL2 和 Ubuntu 配置 GPU 机器学习环境 文学编程和可重复性研究 (Literate Programming and Reproducible Research) 在 OpenWrt 中安装 Jellyfin 搭建家庭影音中心 自私和贪婪 (Selfish and Greedy) 评分和排名算法 (Rating & Ranking Algorithms) 小记这一波裁员浪潮 基于内容的图像检索 (Content-based Image Retrieval, CBIR) 你所应该知道的 A/B 测试 (A/B Test You Should Know) 一个人的摩旅 (Travel with My Motorcycle Alone) 设计语言初探 (A Glimpse of Design Language) Spark 集群搭建 (Spark Cluster Setup) Hive 安装和配置 (Hive Setup) Hadoop 集群搭建 (Hadoop Cluster Setup) 虚拟环境准备 (Virtual Environment Preparation) 大数据 SQL 性能调优 (Big Data SQL Performance Tuning) 进程,线程和协程 (Process, Thread and Coroutine) - 实现篇 进程,线程和协程 (Process, Thread and Coroutine) - 理论篇 胶囊网络 (Capsule Network) 投票公平合理吗? 图存储与计算 (Network Storage and Computing) - 复杂网络系列 网络算法 (Network Algorithms) - 复杂网络系列 真实世界网络结构 (Structure of Real-World Network) - 复杂网络系列 网络表示,测度和度量 (Network Representation, Measures and Metrics) - 复杂网络系列 文本相似度 (Text Similarity) 而立之前 (Life before 30) 最近邻搜索 (Nearest Neighbor Search) 无模型策略预测和控制 - 时序差分学习 (Model-Free Policy Prediction and Control - Temporal Difference Learning) - 强化学习系列 无模型策略预测和控制 - 蒙特卡洛方法 (Model-Free Policy Prediction and Control - Monte-Carlo Learning) - 强化学习系列 利用动态规划求解马尔可夫决策过程 (Planning by Dynamic Programming) - 强化学习系列 贝叶斯优化 (Bayesian Optimization) 马尔可夫决策过程 (Markov Decision Process) - 强化学习系列 多臂赌博机 (Multi-armed Bandit) - 强化学习系列 强化学习简介 (Introduction of Reinforcement Learning) - 强化学习系列 在群晖 NAS 上编译安装 tmux 隐马尔可夫,条件随机场和序列标注 (Hidden Markov Model, Conditional Random Fields and Sequence Labeling) 图嵌入和图神经网络 (Graph Embedding and Graph Neural Network) 预训练自然语言模型 (Pre-trained Models for NLP) toB 产品用户权限 (User Privileges of toB Products) 京东数科 HIPO 学习之旅 (JDD HIPO Learning Journey) 杭州和东京之旅 (Tour of Hangzhou and Tokyo) 国际智慧温室种植挑战赛 (International Autonomous Greenhouse Challenge) 记忆中的儿时 (My Childhood in Memory) 启发式算法 (Heuristic Algorithms) 关不掉的浏览器标签页 (Browser Tabs You do not Close) 贝塞尔曲线 (Bézier Curve) 如何阅读一本书 (How to Read a Book) 相似性和距离度量 (Similarity and Distance Measurement) 集成学习算法 (Ensemble Learning) 计算复杂性与动态规划 (Computational Complexity and Dynamic Programming) 利用 Flask 和 Google App Engine 部署模型服务 序列到序列和注意力机制 (Seq2Seq and Attention Machanism) 词向量 (Word Embeddings) 循环神经网络 (Recurrent Neural Network, RNN) 泰国之行 (Tour of Thailand) 媒介之战 (War of Medias) 卷积神经网络 (Convolutional Neural Network, CNN) 买书,囤书,看书 (Buy Books, Hoard Books and Read Books) Play Safe, Smart Choice & Yuppie 基于 PyQt5/PySide2 和 QML 的跨平台 GUI 程序开发 流形学习 (Manifold Learning) 深度学习优化算法 (Optimization Methods for Deep Learning) 深度学习优化算法 (Optimization Methods for Deeplearning) 生成对抗网络简介 (GAN Introduction) Ising 模型,Hopfield 网络和受限的玻尔兹曼机 (Ising, Hopfield and RBM) 马尔科夫链蒙特卡洛方法和吉布斯采样 (MCMC and Gibbs Sampling) 特征值分解,奇异值分解和主成分分析 (EVD, SVD and PCA) 墨尔本之行 (Trip to Melbourne)
SQL 样式指南 (SQL Style Guide)
范叶亮 · 2021-05-04 · via 中文博客 on 范叶亮 | Leo Van

SQL 样式指南

SQL Style Guide

分类: 编程 / 字数: 1263 / 标签: SQL, 样式指南, Style Guide, Common Table Expressions, CTEs


代码样式指南主要用于规范项目中代码的一致性,使得代码简单、可读和易于维护,从一定程度上也影响代码的质量。一句话概括如何评价代码的质量:

衡量代码质量的唯一有效标准:WTF/min – Robert C. Martin

Google 针对大多数编程语言(例如:C/C++,Java,JavaScript,Python,R 等)都整理了相关的代码风格,但对于 SQL 这种用于数据库查询特殊目的的编程语言并没有整理对应的风格。同其他编程语言代码风格一样,没有哪种风格是最好的,只要在项目中采用统一合理的风格即可。

本文参考的 SQL 样式指南有如下几种:

  1. https://www.sqlstyle.guide/zh/
  2. https://about.gitlab.com/handbook/business-technology/data-team/platform/sql-style-guide/
  3. https://docs.telemetry.mozilla.org/concepts/sql_style.html
  4. https://github.com/mattm/sql-style-guide

本文给出的 SQL 样式指南基于上述几种进行整理和修改。

一般原则

  • 使用一致的、描述性名称。
  • 使用空格(2 个或 4 个,项目中保持一致),避免使用 TAB 缩进。
  • 在 SQL 中加入必要的注释,块注释使用 /* */,行注释使用 --,并在末尾换行。
  • 使用单引号 ' 作为被引号包裹的标识符。
  • 运算符前后添加空格,逗号 , 后添加空格,避免行尾有空格。
  • 每行代码不超过 80 个字符。

命名惯例

  • 避免名称和保留字一样。
  • 关键词、函数名称采用大写,字段名、表名采用小蛇式(lower snake case)命名。
  • 名称要以字母开头,不能以下划线结尾,名称中仅可以使用字母、数字和下划线。
  • 不要在名字中出现连续下划线 __,这样很难辨认。
  • 尽量避免使用缩写词。使用时一定确定这个缩写简明易懂。
  • 字段名总是使用单数。

对齐和换行

  • 避免川流式对齐代码。

    /* Good */
    SELECT id
    FROM table_name
    WHERE column = "test"
    ;
    
    /* Bad */
    SELECT id
      FROM talbe_name
     WHERE column = "test"
    ;
    
  • 多个元素组合无法呈现在一行中时,应将第一个元素另起一行。

    /* Good */
    SELECT
      CASE postcode
        WHEN 'BN1' THEN 'Brighton'
        WHEN 'EH1' THEN 'Edinburgh'
      END AS city
    FROM table_name
    ;
    
    /* Bad */
    SELECT
      CASE postcode WHEN 'BN1' THEN 'Brighton'
                    WHEN 'EH1' THEN 'Edinburgh'
      END AS city
    FROM table_name
    ;
    
  • 由括号构成的多行,结尾括号应单独一行。

    /* Good */
    SELECT id
    FROM table_name
    WHERE postcode IN (
      'looooooooooooooooooooooooong_BN1',
      'loooooooooooooooooooooooooog_EH1'
    )
    
    /* Bad */
    SELECT id
    FROM table_name
    WHERE postcode IN ('looooooooong_BN1',
                       'looooooooong_EH1')
    
  • 多行采用右侧逗号和左侧关键字连接。

    /* Good */
    SELECT
      id,
      name
    FROM
      talbe_name
    WHERE
      id > 1
      AND name LIKE "%Tom%"
    ;
    
    /* Bad */
    SELECT
      id
      , name
    FROM
      table_name
    WHERE
      id > 1 AND
      name LIKE "%Tom%"
    ;
    
  • 根关键词建议单独一行,多个参数单独一行。

    /* Good */
    SELECT
      id,
      name
    FROM
      table_name
    WHERE
      id > 1
      AND name LIKE "%Tom%"
    LIMIT
      10
    ;
    
    /* Acceptable */
    SELECT
      id,
      name
    FROM table_name
    WHERE
      id > 1
      AND name LIKE "%Tom%"
    LIMIT 10
    ;
    
    /* Bad */
    SELECT id, name
    FROM table_name
    WHERE
      id > 1
      AND name LIKE "%Tom%"
    LIMIT 10
    ;
    

明确指定

  • 使用 AS 明确指定别名,而非隐式。

    /* Good */
    SELECT
      table_name_1.id AS user_id,
      table_name_2.name AS user_name
    FROM
      looooooooong_table_name_1 AS table_name_1
    LEFT JOIN
      looooooooong_table_name_2 AS table_name_2
    ON
      table_name_1.id = table_name_2.id
    ;
    
    /* Bad */
    SELECT
      table_name_1.id user_id,
      table_name_2.name user_name
    FROM
      looooooooong_table_name_1 table_name_1
    LEFT JOIN
      looooooooong_table_name_2 table_name_2
    ON
      table_name_1.id = table_name_2.id
    ;
    
  • 避免使用隐式关联。

    /* Good */
    SELECT
      table_name_1.id,
      table_name_2.name
    FROM
      table_name_1
    INNER JOIN
      table_name_2
    ON
      table_name_1.id = table_name_2.id
    ;
    
    /* Bad */
    SELECT
      table_name_1.id,
      table_name_2.name
    FROM
      table_name_1,
      table_name_2
    ON
      table_name_1.id = table_name_2.id
    ;
    
  • 明确关联类型。

    /* Good */
    SELECT
      table_name_1.id,
      table_name_2.name
    FROM
      table_name_1
    INNER JOIN
      table_name_2
    ON
      table_name_1.id = table_name_2.id
    ;
    
    /* Bad */
    SELECT
      table_name_1.id,
      table_name_2.name
    FROM
      table_name_1
    JOIN
      table_name_2
    ON
      table_name_1.id = table_name_2.id
    ;
    
  • 明确指定分组列。

    /* Good */
    SELECT
      submission_date,
      normalized_channel IN ('nightly', 'aurora', 'beta') AS is_prerelease,
      COUNT(*) AS count
    FROM
      telemetry.clients_daily
    WHERE
      submission_date > '2019-07-01'
    GROUP BY
      submission_date,
      is_prerelease
    ;
    
    /* Bad */
    SELECT
      submission_date,
      normalized_channel IN ('nightly', 'aurora', 'beta') AS is_prerelease,
      COUNT(*) AS count
    FROM
      telemetry.clients_daily
    WHERE
      submission_date > '2019-07-01'
    GROUP BY
      1, 2
    ;
    

子查询

  • 尽量使用 Common Table Expressions (CTEs) 而非子查询。

    /* Good */
    WITH sample AS (
      SELECT
        client_id,
        submission_date
      FROM
        main_summary
      WHERE
        sample_id = '42'
    )
    
    SELECT *
    FROM sample
    LIMIT 10
    
    /* Bad */
    SELECT *
    FROM (
      SELECT
        client_id,
        submission_date
      FROM
        main_summary
      WHERE
        sample_id = '42'
    )
    LIMIT 10
    
  • 尽量在 CTEs 中处理查询而非主语句中。

    /* Good */
    WITH backings_per_category AS (
      SELECT
        ...
    ), backers AS (
      SELECT
        backings_per_category.backer_id,
        COUNT(backings_per_category.id) AS projects_backed_per_category
      INNER JOIN ksr.users AS users ON users.id = backings_per_category.backer_id
      GROUP BY backings_per_category.backer_id
    ), backers_and_creators AS (
      ...
    )
    SELECT * FROM backers_and_creators;
    
    /* Bad */
    WITH backings_per_category AS (
      SELECT
        ...
    ), backers AS (
      SELECT
        backer_id,
        COUNT(backings_per_category.id) AS projects_backed_per_category
    ), backers_and_creators AS (
      ...
    )
    SELECT *
    FROM backers_and_creators
    INNER JOIN backers
    ON backers_and_creators
    ON backers.backer_id = backers_and_creators.backer_id
    

其他

  • 尽量使用 != 而不是 <> 表示不等于。
  • 尽量使用 BETWEEN 而不是多个 AND 语句。
  • 尽量使用 IN() 而不是多个 OR 语句。
  • 尽量避免使用 SELECT *
  • 尽量避免使用无意义的别名,例如:a, b, c