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

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

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

时间: 2025-01-01 16:08:29

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

《《SQL与关系数据库理论——如何编写健壮的SQL代码》》一导读

前 言 SQL无所不在.尽管如此,SQL却难以使用:SQL是复杂的,令人困惑且容易出错(我敢说比它的卫道士所声称的更容易出错).所以,为了写出你能确信的精确SQL代码(意思是它准确地做到了要求它做的事),你就必须遵从一些适当的准则.而本书的主题就是:关系化地使用SQL,这就是你需要的准则.不过,这到底意味着什么?难道SQL不是关系化的吗? 没错,SQL确实是用于关系化数据库的标准语言,但是这个事实本身并不能让它成为关系化的语言.让人感到不幸的真相是:SQL在太多的方面背离了关系理论:重复行和nu

《你不可不知的关系数据库理论》——14.2 SQL与关系模型的不同点

14.2 SQL与关系模型的不同点 此部分列出了SQL与关系模型的不同点,主要是为了参考,同时顺便进行一些附加说明.我知道可能会有人对列表中的个别术语吹毛求疵,一一解释列表中这些特性是非常不容易的,特别是它的正交性(例如,保证这些特性都相互独立,互不影响).但是我认为这些吹毛求疵都不是重要的,重要的是它们累积起来造成的影响,坦率地说是相当惊人的3. 不再啰嗦了,下面具体来看一下它们的不同点: SQL不能够完全区分表的值和表变量.SQL表与关系(或关系变量)不同,因为它们不允许或不需要(根据具体情

《视图更新与关系数据库理论》——第2章 技术背景

第2章 技术背景 视图更新与关系数据库理论适合我的一切也应该能适合你. --Walt Whitman<Leaves of Grass>(1885) 上一章的讨论是基于SQL的,因为大家对它都很熟悉.但实际上很可惜,SQL并不适合作为这种探究的基础,也无法满足目前手上课题对细节技术讨论的要求.一方面来讲,我们需要检验的概念很多时候完全无法用SQL语句表达:从另一方面来看,即使是可以表达的时候,SQL通常也会引入一大堆与之毫无关系而又没有必要的复杂内容,很容易使人一叶障目,不见森林.由于以上原因,

《视图更新与关系数据库理论》——第1章 抛砖引玉

第1章 抛砖引玉视图更新与关系数据库理论身教胜于言教. --Samuel Johnson<Rasselas>(1759) 本书中所涉及的大多数范例都是基于我们耳熟能详的(可别说是老掉牙的)"供应商与零部件"数据库而来的.我为再一次把这个老生常谈的例子拿出来表示歉意,但正如我在其他地方所说,我认为在各种不同的出版物上使用同样的例子对于学习而言是有利无害的.就SQL来说[1],数据库包含3张表,更确切地说,是3张基表,分别称为供应商表S("suppliers"

《你不可不知的关系数据库理论》导读

前言 你不可不知的关系数据库理论关系数据模型是百年来最伟大的技术发明之一,它是我们完成数据库领域任何事情的基础.的确,它使数据库管理成为一门科学,而不再像过去那样是一些技巧.技术和经验法则的特定集合.因此,每一个与数据库管理有关的专业人员,或多或少都会主动去获得一些与关系模型有关的知识,以加深对关系模型的理解.因为如果没有它,想开展高效的工作.获得较高的工作性能几乎是不可能的. 不幸的是,想要达到如上所说的"获得知识,加深理解"是不容易的.这有多方面的原因,但影响最大的原因是SQL语言

《视图更新与关系数据库理论》导读

前言 视图更新与关系数据库理论本书是这个系列的第3本书,它的两位"前辈"是: <SQL and Relational Theory: How to Write Accurate SQL Code>(第2版) <Database Design and Relational Theory: Normal Forms and All That Jazz> 以上两本书于2012年由O'Reilly出版发行.第1本书的目标读者是所有种类数据库的从业人员,书中解释了关系理论

《你不可不知的关系数据库理论》——第1章 数据库基本概念

第1章 数据库基本概念 你不可不知的关系数据库理论我们的生活被琐事浪费掉了--简化,简化. --Henry David Thoreau: Walden(1854) 本章是一个介绍性的概述,目的是提供一个距离我们非常遥远的观点.它故意没有讲解得很深奥,如果你已经了解了关于数据库管理的一些知识,也许会发现本章内容都已熟悉.但是我想你应该花些时间把本章从头到尾通读一遍,这是非常值得的,如果只是想获得背景知识,可以看后续的章节.同时,本章还介绍了一些可以运行的示例,在后面的章节中我们也一定会遇到这些例子

《你不可不知的关系数据库理论》——14.1 概述

14.1 概述 再重复一下我在第10章讲过的内容,我确信先了解关系模型,然后再学习SQL会比先学习SQL再学习关系模型要容易些.其原因是如果先学习SQL再学习关系模型的话,会需要很多未了解的知识(因此本书才按照这样的结构来安排,就像在第1章中介绍的一样).实际上,我相信并不是任何人都真正了解SQL的方方面面,只是知道了这种语言,而不是真正了解它的实质.SQL如此庞大.如此复杂.如此特别.如此非正交(此处忽略了它的逻辑差异.不一致性.矛盾等1),经过分析后我不得不相信SQL是很难教会的.我不止一次

《视图更新与关系数据库理论》——1.1 可交换性原则

1.1 可交换性原则 到目前为止,表S是基表,LS和NLS是视图.现在仔细观察,你会发现其实我们还可以用另一种方式来看它们,那就是把LS和NLS作为基表,而S作为视图,具体如下所示. CREATE TABLE LS ( SNO VARCHAR(5) NOT NULL , SNAME VARCHAR(25) NOT NULL , STATUS INTEGER NOT NULL , CITY VARCHAR(20) NOT NULL , UNIQUE ( SNO ) ) ; CREATE TABLE