您的位置:首页 > 数据库 > Oracle

ORACLE官方SQL语言参考笔记之Oracle SQL的基本元素篇(第三章-第二节)

2018-04-03 10:06 831 查看

数据类型比较规则篇

本文简述

此书下载方法:关注微信公众号,点击功能介绍-书籍链接下载,即可获取,有道云链接:ORACLE官方SQL语言参考笔记

由于第三章后篇幅较大,分成小节来做笔记

中文名:《SQL语言参考笔记》

英文名:《SQL Language Reference》

作者:二次猿

时间:阅读于2018年3月21日

准备工作:具体可以参考简书和二次猿公众号常用表

注意事项:跳过基本概念和非重要内容,重点举例说明,并且加粗,部分内容可能在其他章节会再次详细介绍,表格如果排版不美观,可以复制到excle进行直观展示,代码部分根据实际情况注释和说明

数据类型比较规则篇
本文简述
3.2 数据类型比较规则
3.2.1 数值型

3.2.2 日期型

3.2.3 字符型
3.2.3.1 二进制和语言比较

3.2.3.2 空白和非填充比较语义

3.2.4 对象型

3.2.5 数组和嵌套表

3.2.6 数据类型的优先级

3.2.7 数据类型转换
3.2.7.1 隐式和显式数据转换

3.2.7.2 隐式数据转换

3.2.7.3 隐式数据转换示例
3.2.7.3.1 文本文字示例

3.2.7.3.2 字符和数字值示例

3.2.7.3.3 日期示例

3.2.7.4 显式数据转换

3.2.8 数据转换的安全性考虑

本文重点内容

本人是一枚程序猿,如果觉得整理的不错,请关注个人微信公众号(扫一扫):

3.2 数据类型比较规则

3.2.1 数值型

一个较大的值被认为大于一个较小的值。所有负数都小于零,所有正数。因此,-1小于100;-100小于-1。

浮点值NaN(不是数字型)比任何其他数值都大,并且等于它本身。

3.2.2 日期型

较晚的日期被认为比较早的日期大。例如,“2005-03-29”的日期比“2006-01-05”的日期要小,而“2006-1-5 01:35pm”的日期则大于‘2005-1-5 10:09am’.

3.2.3 字符型

字符值是根据两种衡量标准进行比较的:

二进制或语言排序

空白或非填充比较语义

以下各小节介绍了这两项措施。

3.2.3.1 二进制和语言比较

在默认的二进制比较中,Oracle根据数据库字符集中字符的数字代码的串联值来比较字符串。一个字符如果它的数值大于字符集中的另一个数值,则为大于另一个。Oracle认为空白少于任何字符,这在大多数字符集中是正确的

详细的ASCII,EBCDIC码见书中内容,本文不再详细列出

这些是一些常见的字符集:

7位ASCII(美国信息交换标准代码)

EBCDIC码(扩展二进制编码十进制交换码)

ISO 8859/1(国际标准化组织)

JEUC日本扩展UNIX

如果数字代码的二进制序列与您正在比较的字符的语言序列不匹配,则语言比较非常有用。如果NLS_SORT PAR使用语言比较参数的设置不是二进制,NLS_COMP参数被设置为Language。在语言排序中,所有SQL排序和比较都基于NLS_SORT指定的语言规则。

3.2.3.2 空白和非填充比较语义

对于空白语义,如果这两个值有不同的长度,那么Oracle首先将空白添加到较短的值的末尾,这样它们的长度是相等的。然后,Oracle比较字符的值。从一个字符到第一个不同字符。在第一个不同位置中具有较大字符的值被认为更大。如果两个值没有不同的字符,那么他们被认为是平等的。此规则意味着,如果两个值仅在尾随空格数上不同,则它们是相等的。对象中的两个值时,Oracle才使用空白填充比较语义。比较是数据类型char、nchar、文本文本或用户函数返回的值的表达式。

对于非填充语义,Oracle将两个值逐字符进行比较,直到第一个字符不同为止。在这个位置上具有较大字符的值被认为是更大的。如果两个不同长度的值是相同的,直到较短的一个结束,那么较长的值被认为是更大的。如果两个相同长度的值没有不同的字符,那么这些值会被认为是相等的。当比较中的一个或两个值具有数据类型VARCHAR 2或NVARCHAR 2时,Oracle使用非填充比较语义。

使用不同的比较语义比较两个字符值的结果可能有所不同。下表显示了使用每个比较比较五对字符值的结果。在语义上。通常,空白和非填充比较的结果是相同的。表中的最后一个比较说明了空白填充比较语义与非填充比较语义之间的差异。

空白语义非填充语义
‘ac’>’ab’‘ac’>’ab’
‘ab’>’a ‘‘ab’>’a ‘
‘ab’>’a’‘ab’>’a’
‘ab’=’ab’‘ab’=’ab’
‘a ‘=’a’‘a ‘>’a’

3.2.4 对象型

对象值使用两个比较函数之一进行比较: MAP和ORDER。这两个函数都比较对象类型实例,但它们之间有很大的不同。这些功能必须是指定为将与其他对象类型比较的任何对象类型的一部分。

3.2.5 数组和嵌套表

见第七章的嵌套表的比较在第7-4页的“比较条件”中描述。

3.2.6 数据类型的优先级

Oracle使用数据类型优先级来确定隐式数据类型转换,这在后面的章节中进行了讨论。Oracle数据类型具有以下优先权:

日期、时间和间隔数据类型

双精度浮点值(BINARY_DOUBLE)

单精度浮点值(BINARY_FLOAT)

数字类型( NUMBER)

字符数据类型(Character data types)

所有其他内置数据类型(All other built-in data types)

3.2.7 数据类型转换

通常,表达式不能包含不同数据类型的值。例如,表达式不能乘以5乘以10,然后再添加“James”。但是,Oracle支持从一种数据类型到另一种数据类型的值的隐式和显式转换。

3.2.7.1 隐式和显式数据转换

Oracle建议您指定显式转换,而不是依赖于隐式或自动转换,原因如下:

当使用显式数据类型转换函数时,sql语句更容易理解。

隐式数据类型转换可能会对性能产生负面影响,特别是如果将列值的数据类型转换为常量而不是相反的情况。

隐式转换取决于其发生的上下文,并且在每种情况下都可能不会以相同的方式工作。例如,从datetime值到VARCHAR2值的隐式转换可能会根据NLS_DATE_FORMAT参数的值返回意外的年份。

隐式转换的算法在软件版本和Oracle产品之间会发生变化。显式转换的行为更可预测。

如果在索引表达式中发生隐式数据类型转换,则Oracle数据库可能不会使用索引,因为它是为预转换数据类型定义的。这可能会产生负面影响。

3.2.7.2 隐式数据转换

当这种转换有意义时,Oracle数据库会自动将一种数据类型的值转换为另一种数据类型。

如下表是Oracle隐式转换的矩阵.。该表显示了所有可能的转换,而不考虑转换的方向或进行转换的上下文。规则开始了按照表格来处理这些细节。

BINARY_DOU>BLE LONG
-CHARVARCHAR2NCHARNVARCHAR2DATEDATETIME\/INTERVALNUMBERBINARY_FLOATRAWROWIDCLOBBLOBNCLOB
CHAR-XXXXXXXXXX-XX
VARCHAR2X-XXXXXXXXXXX
NCHARXXXXXXXXXXXX
NVARCHAR2XXXXXXXXXXXX
DATEXXXX
DATETIME/INTERVALXXXXX
NUMBERXXXXXX
BINARY_FLOATXXXXXX
BINARY_DOUBLEXXXXXX
LONGXXXXX1XX
RAWXXXXXX
ROWIDXXX
CLOBXXXXX
BLOBX
NCLOBXXXXXX
不能直接将Long转换为Interval,但可以使用to_char(Interval)将Long转换为VARCHAR 2,然后将得到的VARCHAR 2值转换为Interval

以下规则适用于隐式数据类型转换:

在插入和更新操作期间,Oracle将值转换为受影响列的数据类型。

在SELECT FROM操作期间,Oracle将数据从列转换为目标变量的类型。

当操作数值时,Oracle通常调整精度和缩放,以允许最大容量。在这种情况下,这些操作产生的数值数据类型可能与n不同。在基础表中找到的数字数据类型。

当比较字符值和数值时,Oracle将字符数据转换为数字值。

字符值或数字值与浮点数值之间的转换可能不准确,因为字符类型和数字使用十进制精度来表示数字值,浮点数使用二进制精度。

当将CLOB值转换为字符数据类型(如VARCHAR2)或将BLOB转换为原始数据时,如果要转换的数据大于目标数据类型,则数据库将返回一个错误

在从时间戳值转换到日期值期间,时间戳值的小数秒部分被截断,当时间戳值的小数秒部分被舍入时。

BINARY_FLOAT转换到BINARY_DOUBLE是精确的

如果BINARY_Double值使用BINARY_FLOW支持的更多精度位,则从BINAL_DOUBLE到BINAL_FLOW的转换是不精确的。

当比较字符值和日期值时,Oracle将字符数据转换为日期。

当使用sql函数或运算符时,其数据类型的参数不是它接受的参数,Oracle将参数转换为接受的数据类型。

在分配任务时,Oracle将等号(=)右侧的值转换为左侧赋值目标的数据类型。

在串联操作,Oracle将从非字符数据类型char或nchar

在对字符和非字符数据类型进行算术操作和比较期间,Oracle将从任何字符数据类型转换为数字、日期或rowid(视情况而定)。在CHAR/VARCHAR2和NCHAR/NVARCHAR2之间的算术操作中,Oracle将转换为一个数字。

大多数SQL字符函数都启用了接受CLOBS作为参数的功能,Oracle在CLOB和字符类型之间执行隐式转换。因此,尚未启用的函数CLOBS可以通过隐式转换接受CLOBS。在这种情况下,Oracle在调用函数之前将CLOBS转换为CHAR或VARCHAR2。如果clob大于4000字节,则Oracle只将前4000字节转换为char。

当将原始或长原始数据转换到字符数据和从字符数据转换时,二进制数据以十六进制形式表示,一个十六进制字符表示原始数据的每四个位。

比较CHAR和VARCHAR2和nchar和类型类型之间可能需要不同的字符集。在这种情况下,转换的默认方向是数据库字符集。国家字符集。

不同字符类型的转换方向:

-to_CHARto_VARCHAR2to_NCHARto_NVARCHAR2
from CHARVARCHAR2NCHARNVARCHAR2
from VARCHAR2VARCHAR2NVARCHAR2NVARCHAR2
from NCHARNCHARNCHARNVARCHAR2
from NVARCHAR2NVARCHAR2NVARCHAR2NVARCHAR2
用户定义的类型(如集合)不能隐式转换,但必须使用强制转换…多集(CAST…MULTISET)。

3.2.7.3 隐式数据转换示例

3.2.7.3.1 文本文字示例

文本文字‘10’具有数据类型CHAR。Oracle在数字表达式中出现的数字数据类型将隐式转换为Number数据类型,如下所示:

SELECT salary + '10' FROM hr.employees;


3.2.7.3.2 字符和数字值示例

当条件比较字符值和数字值时,Oracle隐式地将字符值转换为数字值,而不是将数字值转换为字符值。在以下语句,Oracle隐式地将“200”转换为200:

SELECT last_name FROM hr.employees WHERE employee_id = '200';


3.2.7.3.3 日期示例

在下面的语句,Oracle隐式转换的”24-6月-06”使用默认的日期格式的DD-MON-YY日期值:

SELECT last_name, hire_date
FROM hr.employees
WHERE hire_date = '24-6月-06';


注意:可以通过sqlplus命令在cmd中登入后SQL语句查看实际情况的默认格式,当然如果你有修改过那么默认格式就是你修改过的,你可以执行如下其中一个SQL语句都可以查看默认格式情况

--语句1:
SELECT s.value
FROM nls_database_parameters s
WHERE s.parameter = 'NLS_DATE_FORMAT';
--语句2:
SELECT SYSDATE FROM dual;


3.2.7.4 显式数据转换

可以使用sql转换函数显式指定数据类型转换。如下表显式地将值从一种数据类型转换为另一种数据类型的SQL函数。

在Oracle可以执行隐式数据类型转换的情况下,不能指定长和长的原始值。例如,长和长的原始值不能出现在带有函数或运算符的表达式中(如果表格自动换行导致不美观可以复制到excle中查看更直观)。

-to_CHAR, VARCHAR2, NCHAR, NVARCHAR2to_NUMBERto_Datetime/Intervalto_RAW,to_ROWIDto_LONG,LONGRAWto_CLOB, NCLOB,BLOBto_BINARY_FLOATto BINARY_DOUBLE
from CHAR,VARCHAR2,NCHAR,NVARCHAR2TO_CHAR(char.)
TO_NCHAR(char.)
TO_NUMBERTO_DATE
TO_TIMESTAMP
TO_TIMESTAMP_TZ
TO_YMINTERVAL
TO_DSINTERVAL
HEXTORAWCHARTO=ROWIDTO_CLOB
TO_NCLOB
TO_BINARY_FLOATTO_BINARY_DOUBLE
from NUMBERTO_CHAR(number)
TO_NCHAR(number)
TO_DATE
NUMTOYM-INTERVAL
NUMTODS-INTERVAL
TO_BINARY_FLOATTO_BINARY_DOUBLE
from Datetime/IntervalTO_CHAR(date)
TO_NCHAR(datetime)
from RAWRAWTOHEX
RAWTONHEX
TO_BLOB
from ROWIDROWIDTOCHAR
from LONG /LONG RAWTO_LOB
from CLOB,NCLOB,BLOBTO_CHAR
TO_NCHAR
TO_CLOB
TO_NCLOB
from CLOB,NCLOB, BLOBTO_CHAR
TO_NCHAR
TO_CLOB
TO_NCLOB
from BINARY_FLOATTO_CHAR(char.)
TO_NCHAR(char.)
TO_NUMBERTO_BINARY_FLOATTO_BINARY_DOUBLE
from BINARY_DOUBLETO_CHAR(char.)
TO_NCHAR(char.)
TO_NUMBERTO_BINARY_FLOATTO_BINARY_DOUBLE

3.2.8 数据转换的安全性考虑

当通过隐式转换或不指定格式模型的显式转换将日期时间值转换为文本时,格式模型是由全球化会话参数之一定义的。根据源数据类型的不同,参数名为NLS_DATE_FORMAT、NLS_TIMESTAMP_FORMAT或NLS_TIMESTAMP_TZ_FORMAT。这些参数的值可以在客户端环境或ALTER_SESSION语句中指定

当不使用显式格式模型的转换应用于c#的日期时间值时,格式模型对会话参数的依赖可能会对数据库安全性产生负面影响。链接到动态SQL语句的文本。

DynamicSQL语句是在传递到数据库执行之前将文本从片段中连接起来的语句。动态SQL经常与内置的PL/sql相关联。PackageDBMS_SQL或使用PL/SQL语句立即执行,但这些并不是动态构造的SQL文本可以作为参数传递的唯一位置。例如:

EXECUTE IMMEDIATE
'SELECT last_name FROM employees WHERE hire_date > ''' || start_date || '''';


其中开始日期具有数据类型日期

在上面的示例中,使用会话参数NLS_DATE_FORMAT中指定的格式模型将start_date的值转换为文本。结果被连接到SQL文本中。日期时间格式模型可以简单地由以双引号括起来的文字文本组成。因此,任何可以显式设置会话全球化参数的用户都可以决定哪个文本。是由上述转换产生的。如果SQL语句是由PL/SQL过程执行的,则该过程容易通过Session参数受到SQL注入的攻击。如果该过程以定义器的权限运行,并且具有比会话本身更高的权限,则用户可以获得对敏感数据的未经授权的访问

数值的隐式和显式转换也可能遇到类似的问题,因为转换结果可能取决于会话参数NLS_NUMERIC_

CHARACTERS。此参数定义小数分隔符和组分隔符。如果十进制分隔符被定义为引号或双引号,则可能出现sql注入.

本文重点内容



本人是一枚程序猿,如果觉得整理的不错,请关注个人微信公众号(扫一扫):

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  学习笔记 ORACLE