很少看到有人这样写SQL

本文探讨了SQL编写方式及其对数据库性能的影响,强调了良好数据库设计的重要性,并通过具体实例展示了规范化设计的优势。

很少看到有人这样写SQL

 

      好久没写代码了,想编写一套独立的企业宣传网站,包含前台信息展示及后台数据维护。但都好几天了,我也仅是10月24日这天才写了下面这一点点SQL(MS SQL Server 2000 环境),只因工作忙,下班后已经无心与代码格斗。

 

 

 

      就上面这段普普通通的SQL代码,我都已经很久没有看到有人这样去写了,看到的大多是无注释、无必要验证的SQL。

      原因有两点:

      1、现在的项目大量充斥着三方ORM框架(如Hibernate)的身影,更多时间关心的是对象实体模型,而非数据库模型;

      2、所有一切有利的证据都在指示程序设计应该以对象实体模型为开端,数据库模型仅为持久化方案的一种选择而已。

      但是,据我所知,目前大量的应用程序正是标榜着“OOD”、“UML”,但最终的持久化载体——数据库却成为真正的“垃圾库”。试想,我曾看到过的一张“人力资源表”,一共有96个列(查询用的SQL语句为:select count(name) from syscolumns where id = object_id('HrmResource')(MS SQL Server 2000 环境)),我曾在一则网文中看到过这样一段数据库优化设计的文字:

逻辑数据库和表的设计    
    数据库的逻辑设计、包括表与表之间的关系是优化关系型数据库性能的核心。一个好的逻辑数据库设计可以为优化数据库和应用程序打下良好的基础。    
   
    标准化的数据库逻辑设计包括用多的、有相互关系的窄表来代替很多列的长数据表。下面是一些使用标准化表的一些好处。    
   
        A:由于表窄,因此可以使排序和建立索引更为迅速    
        B:由于多表,所以多镞的索引成为可能    
        C:更窄更紧凑的索引    
        D:每个表中可以有少一些的索引,因此可以提高insert   update   delete等的速度,因为这些操作在索引多的情况下会对系统性能产生很大的影响    
        E:更少的空值和更少的多余值,增加了数据库的紧凑性由于标准化,所以会增加了在获取数据时引用表的数目和其间的连接关系的复杂性。太多的表和复杂的连接关系会降低服务器的性能,因此在这两者之间需要综合考虑。     
定义具有相关关系的主键和外来键时应该注意的事项主要是:用于连接多表的主键和参考的键要有相同的数据类型。

      由此可见,这个“人力资源表”的设计是多么地糟糕,并且据了解,这个“人力资源表”所在的数据库上运行的B/S软件的确是运行效率较低,常常执行一个查询都会需要较长的时间来响应。这也证明了上述引用的文字中观点的正确性。

      还记得曾经有人问一个问题:“设计数据库时为什么我们通常都会给数据库表设置主键?”,众人答:“为了标识数据行的唯一性。”,我曰:“因为主键是聚集索引(MS SQL Server中的术语),可以加快增删改操作的执行速度。”。很明显,关心数据库的设计的确是可取的。据相关资料显示,大多数应用程序的性能瓶颈并不是应用程序逻辑本身,而在于数据库的设计。

      我现在的工作与代码无关,更多的是在客户那里做咨询和需求调研,为了尽快与妻儿能一起生活,很多时候也只是尽力忍耐。无可厚非,我依然更痴迷于代码的世界,对周围看到的软件设计失误造成的问题也太过敏感,这些都包含了程序员的一些基本特征。然而,为了妻儿,我也只能坚持工作,只为当前的工作有足够的休息和很一般的收入。

      

      已经十二点了,又该进被窝了,明天还要上班。各位晚安!

 

 

                                                                                                     By CodingMouse

                                                                                                     2009年10月28日

<think>我们正在讨论SQL规范中关于列别名使用双引号包裹的建议与实际使用情况不符的问题。 根据SQL标准,列的别名应该使用双引号(")包裹,以区分关键字和保留字,并允许别名包含空格或特殊字符。然而,在实际开发中,我们很少看到这样的做法。 原因分析: 1. 数据库兼容性问题:不同的数据库系统对标识符的引用符号要求不同。例如,MySQL使用反引号(`)来引用标识符,而SQL Server使用方括号([])。只有遵循ANSI SQL标准时,才会使用双引号。但在实际中,为了跨数据库兼容,开发者可能避免使用特定数据库的引用符号,而选择不使用任何引号(仅当别名不含空格和特殊字符时)。 2. 可读性和简洁性:不加引号的别名起来更简单,阅读时也更清晰。例如: SELECT column_name AS alias_name ... 比 SELECT column_name AS "alias_name" ... 更简洁。 3. 习惯问题:大多数教程和文档中都不使用双引号,因此开发者养成了不用的习惯。 4. 大小敏感问题:在SQL标准中,使用双引号包裹的别名是大小敏感的,而不使用双引号则会被转换为大(或小,取决于数据库)。但许多开发者希望不区分大小,因此避免使用双引号。 5. 工具生成:许多ORM框架和SQL生成工具默认不生成双引号,除非别名中包含空格或特殊字符。 然而,当别名中包含空格、特殊字符或与关键字冲突时,使用双引号(或其他数据库特定的引用符号)是必需的。 举例: 以下查询在别名包含空格时必须使用引号(以PostgreSQL为例): ```sql -- 正确 SELECT column_name AS "my alias" FROM table; -- 错误(因为别名包含空格) SELECT column_name AS my alias FROM table; ``` 但通常,我们避免在别名中使用空格,而是使用下划线(_)来连接单词,这样就不需要引号了。 总结:虽然SQL规范建议使用双引号包裹别名,但在实际中,只要别名不包含空格和特殊字符,并且不是保留字,开发者倾向于省略引号,以提高代码的简洁性和可读性,同时避免数据库兼容性问题。 相关问题: 1. 在哪些数据库系统中必须使用双引号来包裹别名? 2. 如何在SQL注入攻击中利用引号处理不当的漏洞? 3. SQL标识符的引用规则在不同数据库中有哪些差异? </think>### SQL规范中列别名使用双引号包裹的实践分析 SQL规范(如ANSI SQL标准)建议使用双引号(`"`)包裹列别名,例如: ```sql SELECT employee_id AS "员工编号", salary*12 AS "年薪" FROM employees; ``` 但在实际开发中,这种法较为罕见,主要原因如下: --- #### 一、核心原因分析 1. **兼容性问题** - MySQL默认使用反引号(`` ` ``)而非双引号包裹标识符[^4] - SQL Server使用方括号(`[]`)作为标识符限定符 - 示例:MySQL中更常见法 ```sql SELECT employee_id AS `员工编号` FROM employees; /* MySQL习惯法 */ ``` 2. **可读性与简洁性** - 无引号的别名更简洁直观(如`AS annual_salary`) - 包含空格的别名需求较(如`"Annual Salary"`) - 实践中多采用下划线命名法(`annual_salary`)避免空格 3. **开发工具影响** - ORM框架(如Hibernate)生成的SQL通常省略引号 - 可视化工具(如Navicat)默认不添加引号 - 开发者通过大小区分语义(`employeeId` vs `EMPLOYEEID`) 4. **历史惯性** - 早期数据库(如Oracle)主要使用双引号 - 但现代框架教程(如SQLAlchemy、Sequelize)极示范引号用法 --- #### 二、双引号包裹的适用场景 虽然使用率低,但在以下情况仍需引号: 1. **别名含特殊字符时** ```sql SELECT price AS "价格(¥)" FROM products; /* 包含括号和符号 */ ``` 2. **区分大小需求** ```sql SELECT name AS "FirstName" FROM users; /* 保留精确大小 */ ``` 3. **使用SQL关键字作别名** ```sql SELECT count AS "count" FROM metrics; /* 避免与COUNT()函数冲突 */ ``` --- #### 三、各数据库实现差异对比 | 数据库 | 标识符引用符 | 默认大小处理 | |--------------|--------------|----------------------| | **MySQL** | 反引号 `` ` `` | 忽略大小(Linux区分)| | **PostgreSQL**| 双引号 `"` | 严格区分大小 | | **SQL Server**| 方括号 `[]` | 不区分大小 | | **Oracle** | 双引号 `"` | 创建时区分大小 | > 注:在堆叠注入攻击中,不同数据库的标识符处理差异可能被利用绕过过滤[^1][^2] --- #### 四、开发建议 1. **一致性优先** - 团队统一约定命名规范(推荐蛇形命名:`annual_salary`) 2. **按需使用引号** - 仅当存在特殊字符、空格或保留字冲突时使用 3. **安全考量** - 避免动态拼接别名(防止SQL注入) ```php // 危险示例(堆叠注入风险[^1]) $sql = "SELECT id AS `$user_input` FROM table"; ``` 4. **跨数据库方案** - 使用ORM的参数化查询避免直接处理标识符 --- ### 总结 SQL规范建议的双引号别名包裹在实际中较使用,主要受**数据库实现差异**、**开发习惯**和**可读性需求**影响。现代开发更倾向于通过命名规范(如蛇形命名)避免特殊字符,仅在必要时使用数据库特定的引用符。安全方面需警惕别名动态拼接导致的注入风险[^1][^2]。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值