《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)。不过,其细节超出了本书范围。

相关文章
|
15天前
|
SQL 关系型数据库 MySQL
数据库开发之SQL简介以及DDL的详细解析
数据库开发之SQL简介以及DDL的详细解析
26 0
|
3天前
|
SQL 数据库 Windows
sql数据库安装过程,SQL数据库的安装过
本文概述了安装SQL Server数据库的步骤:准备硬件和软件环境,运行安装程序,选择安装类型,接受许可协议,设定安装路径和组件,配置实例和服务账户,选择身份验证模式,配置其他设置,然后安装并完成。安装后需检查验证SQL Server是否正常工作。确保遵循步骤以顺利完成安装。
41 3
|
7天前
|
SQL 关系型数据库 MySQL
利用 SQL 注入识别数据库方法总结
利用 SQL 注入识别数据库方法总结
|
7天前
|
分布式计算 DataWorks 关系型数据库
DataWorks产品使用合集之在使用 DataWorks 数据集成同步 PostgreSQL 数据库中的 Geometry 类型数据如何解决
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。
17 0
|
7天前
|
SQL 关系型数据库 MySQL
【MySQL】:探秘主流关系型数据库管理系统及SQL语言
【MySQL】:探秘主流关系型数据库管理系统及SQL语言
14 0
|
8天前
|
分布式计算 关系型数据库 大数据
MaxCompute产品使用合集之怎么才可以将 PostgreSQL 中的 geometry 空间类型字段同步到 MaxCompute 或另一个 PostgreSQL 数据库
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。
|
13天前
|
SQL Java 数据库连接
Java从入门到精通:2.3.2数据库编程——了解SQL语言,编写基本查询语句
Java从入门到精通:2.3.2数据库编程——了解SQL语言,编写基本查询语句
|
14天前
|
SQL Oracle 关系型数据库
sql 数据库教学
SQL(Structured Query Language,结构化查询语言)是用于管理关系数据库管理系统(RDBMS)的标准编程语言。它涵盖了数据的插入、查询、更新和删除,数据库模式的创建和修改,
|
14天前
|
SQL XML 数据库
sql导入数据库命令
在SQL Server中,数据库导入可通过多种方式实现:1) 使用SSMS的“导入数据”向导从各种源(如Excel、CSV)导入;2) BULK INSERT语句适用于导入文本文件;3) bcp命令行工具进行批量数据交换;4) OPENROWSET函数直接从外部数据源(如Excel)插入数据。在操作前,请记得备份数据库,并可能需对数据进行预处理以符合SQL Server要求。注意不同方法可能依版本和配置而异。
|
18天前
|
SQL Oracle 关系型数据库
Oracle SQL*Plus的SPOOL命令:数据库世界的“录像机”
【4月更文挑战第19天】`SQL*Plus`的`SPOOL`命令是Oracle数据库中的“录像机”,能记录所有操作和输出。它在用户开始“SPOOL ON”时启动,记录SQL查询、输出、错误信息等。完成后,“SPOOL OFF”停止记录并生成日志文件,便于回顾和检查。日志文件可自定义保存位置和命名,支持多文件录制,方便分类管理。无论数据分析、SQL脚本编写还是日常维护,`SPOOL`都是强大的工具,值得一试!