《SQL与关系数据库理论——如何编写健壮的SQL代码》一2.7 SQL中的类型检查和型转

简介: 本节书摘来华章计算机《SQL与关系数据库理论——如何编写健壮的SQL代码》一书中的第2章 ,第2.7节 C. J. Date 著 单世民 何英昊 许侃 译 更多章节内容可以访问云栖社区“华章计算机”公众号查看。

本节书摘来华章计算机《SQL与关系数据库理论——如何编写健壮的SQL代码》一书中的第2章 ,第2.7节 C. J. Date 著 单世民 何英昊 许侃 译 更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.7 SQL中的类型检查和型转

SQL只支持弱形式的强类型化(如果你明白我的意思的话)。具体说包括:

  • BOOLEAN值只能赋值到BOOLEAN变量,并只能和BOOLEAN值比较。
  • 数字值只能赋值给数值变量,并且只能与数字值比较(此处的“数字”(numeric)指的是SMALLINT、BIGINT、NUMERIC、DECIMAL 或者FLOAT )。
  • 字符串值只能赋值给字符串变量并且只能与字符串值进行比较(此处的“字符串”指的是CHAR、VARCHAR或者CLOB)
  • 位串值只能赋值给位串变量并且只能和位串值比较(这里的“位串”指的是BINARY 、BINARY VARYING或BLOB )

因此,像数值与字符串这样的比较就是非法的。然而,即使两个数的类型不同,它们之间的比较也是合法的,比如分别属于INTEGER和FLOAT类型的两个数(此时,整型值会在进行比较之前强制型转为FLOAT类型)。这就涉及类型型转问题。在通常的计算领域中,一个广为认可的原则就是要尽量避免型转,因为它们容易出错。尤其是在SQL中,允许型转的一个怪异后果就是某些集合并、交、差运算会产生一些在任何运算元中都没有出现过的行!比如,考虑图2.3中的SQL表T1和T2。假设T1中的X列为INTEGER型,T2表中的X列为NUMERIC(5,1)类型;T1中的Y列为NUMERIC (5,1)类型;T2表中的Y列为INTEGER类型。现在,考虑下面的SQL查询:

SELECT X , Y FROM T1
UNION
SELECT X , Y FROM T2

结果显示在图2.3的最右侧:结果中的X列和Y列都是NUMERIC(5,1)类型,且这些列中的值实际上都由INTEGER型转为NUMERIC(5,1)类型。因此,结果是由未在T1和T2表中出现的行组成的——非常奇怪的并,你要是这么想的话是可以理解的。注17
image

图2.3:很奇怪的“并”
强烈建议:只要可能就尽量避免型转。(我自己的习惯是:无论是在SQL还是其他上下文中,都完全不用它们。)尤其是在SQL上下文中,要确保同名列始终具有同一类型;这个规则以及本书中其他建议,目的是确保能基本避免类型转换。当类型转换无法避免时,建议使用CAST或CAST的等价物进行显式类型转换。比如(对于前述的UNION查询):

SELECT CAST ( X AS NUMERIC(5,1) ) AS X , Y FROM T1
UNION
SELECT X , CAST ( Y AS NUMERIC(5,1) ) AS Y FROM T2

然而,为完整起见我还是要多说一句,某些型转很不幸地内建于SQL之中从而无法回避(我觉得下述说明在这个地方可能没多大用处,但我不想把它们完全忽略):

  • 如果表表达式tx用作行子查询,那么tx所表示的表t就应该只有一行r,将并且表t型转为行r。注意:子查询一词在SQL上下文中随处可见。第12章将详细解释子查询;在其之前,你可以将其不太严谨地看成一个由括号封闭的SELECT表达式。
  • 如果表表达式tx用作标量子查询,那么tx所表示的表应该只有一行一列,因此也只能包含一个值v,并且表t双重型转为值v。注意:此种情况尤其会在SQL风格的聚集计算中出现(参见第7章)。
  • 实践中,在ALL或ANY比较rxsq中的行表达式rx,一般由一个简单的标量表达式构成,此时标量表达式所表示的标量值实际上被型转为只包含此标量值的行。在rxsq中:(a)是后接ALL或ANY的“<”或“>”比较运算符;(b)sq是子查询。注意:在本书中,使用行表达式一词表示行子查询或行选择器调用(行选择器是我对SQL中所谓的行值构建器(row value constructor)的叫法,参见第3章)。换句话说,我使用行表达式(row expression)来表示任何代表一个行的表达式,就像我用表表达式(table expression)来表示任何代表一个表的表达式一样。ALL或ANY比较在第11章中进行详细讨论。

最后,SQL在与字符串相关的极特殊场合也使用术语型转(coercion)。不过,其细节超出了本书范围。

相关实践学习
体验RDS通用云盘核心能力
本次实验任务是创建一个云数据库RDS MySQL(通用云盘),并通过云服务器ECS对RDS MySQL实例进行压测,体验IO加速和IO突发带来的性能提升;并通过DMS执行DDL,将数据归档到OSS,再结合云盘缩容,体验数据归档带来的成本优势。
相关文章
|
1月前
|
关系型数据库 MySQL 数据库连接
python脚本:连接数据库,检查直播流是否可用
【10月更文挑战第13天】本脚本使用 `mysql-connector-python` 连接MySQL数据库,检查 `live_streams` 表中每个直播流URL的可用性。通过 `requests` 库发送HTTP请求,输出每个URL的检查结果。需安装 `mysql-connector-python` 和 `requests` 库,并配置数据库连接参数。
132 68
|
2月前
|
SQL Java 数据库连接
mybatis使用四:dao接口参数与mapper 接口中SQL的对应和对应方式的总结,MyBatis的parameterType传入参数类型
这篇文章是关于MyBatis中DAO接口参数与Mapper接口中SQL的对应关系,以及如何使用parameterType传入参数类型的详细总结。
54 10
|
2月前
|
SQL 存储 关系型数据库
SQL判断CHAR类型字段不为空的方法与技巧
在SQL查询中,判断一个CHAR类型字段是否不为空是一个常见的需求
|
2月前
|
SQL 关系型数据库 MySQL
创建SQL数据库的基本步骤与代码指南
在信息时代,数据管理显得尤为重要,其中数据库系统已成为信息技术架构的关键部分。而当我们谈论数据库系统时,SQL(结构化查询语言)无疑是其中最核心的工具之一。本文将详细介绍如何使用SQL创建数据库,包括编写相应的代码和必要的步骤。由于篇幅限制,本文可能无法达到您要求的2000字长度,但会尽量涵盖创建数
105 3
|
2月前
|
SQL 监控 关系型数据库
SQL错误代码1303解析与处理方法
在SQL编程和数据库管理中,遇到错误代码是常有的事,其中错误代码1303在不同数据库系统中可能代表不同的含义
|
2月前
|
SQL 安全 关系型数据库
SQL错误代码1303解析与解决方案:深入理解并应对权限问题
在数据库管理和开发过程中,遇到错误代码是常见的事情,每个错误代码都代表着一种特定的问题
|
3月前
|
SQL 监控 关系型数据库
MySQL数据库中如何检查一条SQL语句是否被回滚
检查MySQL中的SQL语句是否被回滚需要综合使用日志分析、事务状态监控和事务控制语句。理解和应用这些工具和命令,可以有效地管理和验证数据库事务的执行情况,确保数据的一致性和系统的稳定性。此外,熟悉事务的ACID属性和正确设置事务隔离级别对于预防数据问题和解决事务冲突同样重要。
97 2
|
3月前
|
SQL 分布式计算 大数据
大数据开发SQL代码编码原则和规范
这段SQL编码原则强调代码的功能完整性、清晰度、执行效率及可读性,通过统一关键词大小写、缩进量以及禁止使用模糊操作如select *等手段提升代码质量。此外,SQL编码规范还详细规定了代码头部信息、字段与子句排列、运算符前后间隔、CASE语句编写、查询嵌套、表别名定义以及SQL注释的具体要求,确保代码的一致性和维护性。
113 0
|
3月前
|
SQL 安全 数据库
基于SQL Server事务日志的数据库恢复技术及实战代码详解
基于事务日志的数据库恢复技术是SQL Server中一个非常强大的功能,它能够帮助数据库管理员在数据丢失或损坏的情况下,有效地恢复数据。通过定期备份数据库和事务日志,并在需要时按照正确的步骤恢复,可以最大限度地减少数据丢失的风险。需要注意的是,恢复数据是一个需要谨慎操作的过程,建议在执行恢复操作之前,详细了解相关的操作步骤和注意事项,以确保数据的安全和完整。
170 0
|
4月前
|
SQL 存储 数据库
SQL Server 中的备份类型详解
【8月更文挑战第31天】
105 0