我正在使用Oracle DB 11 g
我有一个主键为CHAR(4)的数据库表-尽管此列只使用数字。
我注意到有一些记录显示“0018”或“0123”。
我注意到一些奇怪的事情,需要一些帮助
- CHAR列是否会“自动”向值中填充零?
- 我还注意到,在编写SQL语句时,如果我不在where子句中使用引号,它将返回结果,但如果我使用引号,它将不返回结果。例如
DB CHAR(4)列具有关键字'0018'
我使用以下查询
SELECT * FROM TABLE_A WHERE COLUMN_1=18;
我按预期得到行。
但当我尝试以下操作时
SELECT * FROM TABLE_A WHERE COLUMN_1='18';
这不起作用,但这确实再次起作用
SELECT * FROM TABLE_A WHERE COLUMN_1='0018';
因此,我有点困惑,第一个查询在没有引号的情况下如何能按预期工作?
2条答案
按热度按时间eqfvzcg81#
CHAR列是否会“自动”向值中填充零?
否。从文档中:
如果插入的值短于列长度,则Oracle会将该值用空格填补到列长度。
因此,如果插入数字
18
,它将被隐式转换为字符串'18 '
,并带有两个尾随空格。这意味着其他东西正在对您的数据进行零填充-可能是插入之前的应用程序/代码,也可能是触发器中的数据。
我还注意到,在编写SQL时,如果我不在where子句中使用引号,它将返回结果,但如果我使用引号,它不会
文档中还显示了数据类型比较和转换规则:
将字符值与数值进行比较时,Oracle会将字符数据转换为数值。
执行此操作时:
字符串
'0018'
被隐式转换为数字18
,这样就可以与数值文字进行比较。转换后,前导零就没有意义了,因此'0018'
、'018 '
和18
'都将匹配。使用与匹配的用零填充的列值,您确实得到了一个结果:
18
('0018'
转换为数字)=18
这意味着表中的 * 每个 * 值在进行比较之前都必须进行转换;这也意味着如果
column_1
上有一个正常的索引,那么它不会在比较中使用。执行此操作时:
列和文本是相同的数据类型,因此不必应用转换(因此可以使用普通的索引)。Oracle在这里将使用填充空白的比较语义,因为列是
char
,将较短的文字值填充到列大小为'18 '
,并且只有在字符串完全匹配的情况下才匹配,因此'18 '
将匹配,但是'0018'
或' 18 '
或其他任何字符串都不匹配。如果用零填充的列值不匹配,则不会得到结果:
'0018'
!='18 '
('18'
会填补至长度4)执行此操作时:
列和文字是相同的数据类型,因此不进行转换,也不应用填充,因为文字已经与列值具有相同的长度,并且同样,它仅在字符串完全匹配的情况下才匹配-因此
'0018'
将匹配,但'18 '
或' 18 '
或任何其他内容都不匹配。使用与匹配的用零填充的列值,您确实得到了一个结果:
'0018'
='0018'
k10s72fa2#
不总是零,有时是空格。如果所有字符值都是数字,是的,它将填充零,直到字符字段的固定大小。
因为隐式类型转换。系统要么将char转换为numeric,要么将numeric转换为char,在这种情况下,它要么丢弃前导零并比较数值,要么填充为相同的数据类型,然后进行比较。我敢肯定它将字符转换为数值,因此在比较时丢弃前导零。
有关数据类型比较和隐式转换的详细信息,请参见:https://docs.oracle.com/cd/B13789_01/server.101/b10759/sql_elements002.htm
更多信息: