Oracle -为什么CHAR列自动添加前导零?

xyhw6mcr  于 2022-12-03  发布在  Oracle
关注(0)|答案(2)|浏览(162)

我正在使用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';

因此,我有点困惑,第一个查询在没有引号的情况下如何能按预期工作?

eqfvzcg8

eqfvzcg81#

CHAR列是否会“自动”向值中填充零?
否。从文档中:
如果插入的值短于列长度,则Oracle会将该值用空格填补到列长度。
因此,如果插入数字18,它将被隐式转换为字符串'18 ',并带有两个尾随空格。
这意味着其他东西正在对您的数据进行零填充-可能是插入之前的应用程序/代码,也可能是触发器中的数据。
我还注意到,在编写SQL时,如果我不在where子句中使用引号,它将返回结果,但如果我使用引号,它不会
文档中还显示了数据类型比较和转换规则:
将字符值与数值进行比较时,Oracle会将字符数据转换为数值。
执行此操作时:

SELECT * FROM TABLE_A WHERE COLUMN_1=18;

字符串'0018'被隐式转换为数字18,这样就可以与数值文字进行比较。转换后,前导零就没有意义了,因此'0018''018 '18 '都将匹配。
使用与匹配的用零填充的列值,您确实得到了一个结果:18'0018'转换为数字)= 18
这意味着表中的 * 每个 * 值在进行比较之前都必须进行转换;这也意味着如果column_1上有一个正常的索引,那么它不会在比较中使用。
执行此操作时:

SELECT * FROM TABLE_A WHERE COLUMN_1='18';

列和文本是相同的数据类型,因此不必应用转换(因此可以使用普通的索引)。Oracle在这里将使用填充空白的比较语义,因为列是char,将较短的文字值填充到列大小为'18 ',并且只有在字符串完全匹配的情况下才匹配,因此'18 '将匹配,但是'0018'' 18 '或其他任何字符串都不匹配。
如果用零填充的列值不匹配,则不会得到结果:'0018'!= '18 ''18'会填补至长度4)
执行此操作时:

SELECT * FROM TABLE_A WHERE COLUMN_1='0018';

列和文字是相同的数据类型,因此不进行转换,也不应用填充,因为文字已经与列值具有相同的长度,并且同样,它仅在字符串完全匹配的情况下才匹配-因此'0018'将匹配,但'18 '' 18 '或任何其他内容都不匹配。
使用与匹配的用零填充的列值,您确实得到了一个结果:'0018' = '0018'

k10s72fa

k10s72fa2#

    • CHAR列是否"自动"向值中填充零?**

不总是零,有时是空格。如果所有字符值都是数字,是的,它将填充零,直到字符字段的固定大小。

    • 所以我有点困惑,第一个查询在没有引号的情况下如何能按预期工作?**

因为隐式类型转换。系统要么将char转换为numeric,要么将numeric转换为char,在这种情况下,它要么丢弃前导零并比较数值,要么填充为相同的数据类型,然后进行比较。我敢肯定它将字符转换为数值,因此在比较时丢弃前导零。
有关数据类型比较和隐式转换的详细信息,请参见:https://docs.oracle.com/cd/B13789_01/server.101/b10759/sql_elements002.htm
更多信息:

  • 在以下情况下:如果您的数据库中有一个列,那么请选择一个列。我认为18已经是一个字符数据,因此与"0018"相比,它变成了"18"(注意18后面的2个空格)
  • 表1中的列1 = 18; columnN_1转换为数值,因此18 = 18
  • 表中的数据类型。column_1已经是字符(4),因此'0018'='0018'

相关问题