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

相关文章
|
23天前
|
SQL 关系型数据库 MySQL
实时计算 Flink版产品使用合集之数据库执行的是UPDATE操作,那么Flink监听到的类型是什么
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStreamAPI、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
23天前
|
SQL 存储 安全
第七章 SQL错误信息 - SQL错误代码 -400 到 -500
第七章 SQL错误信息 - SQL错误代码 -400 到 -500
29 1
|
23天前
|
SQL 数据库连接 索引
第四章 SQL错误信息 - SQL错误代码 -1 到 -99
第四章 SQL错误信息 - SQL错误代码 -1 到 -99
28 0
|
23天前
|
SQL 关系型数据库 数据库
实时计算 Flink版操作报错之使用SQL 将 PostgreSQL 的 date 类型字段转换为 TIMESTAMP 类型时遇到报错,该如何处理
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
1月前
|
SQL 算法 数据库
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
145 6
|
2天前
|
SQL Java 数据库连接
MyBatis SQL 批量更新(代码➕案例)
MyBatis SQL 批量更新(代码➕案例)
5 0
|
4天前
|
存储 SQL NoSQL
深入了解数据库技术:核心原理、类型及行业应用
一、引言 数据库技术是信息技术领域的重要组成部分,它负责数据的存储、检索、管理和保护
|
5天前
|
SQL 机器学习/深度学习 分布式计算
MaxCompute产品使用合集之sql代码中支持插入jinja语法语句吗
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。
|
6天前
|
存储 SQL NoSQL
数据库有哪些类型?
【6月更文挑战第9天】数据库有哪些类型?
17 2
|
8天前
|
关系型数据库 MySQL 数据库
MySQL数据库——触发器-案例(Insert类型、Update类型和Delete类型)
MySQL数据库——触发器-案例(Insert类型、Update类型和Delete类型)
14 0

热门文章

最新文章