【问题标题】:Oracle - Why is CHAR Column is automatically adding a leading zero?Oracle - 为什么 CHAR 列自动添加前导零?
【发布时间】:2022-12-03 00:21:30
【问题描述】:

我正在使用 Oracle DB 11g

我有一个主键为 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';

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

【问题讨论】:

  • 因为隐式转换。系统将 column_1 转换为截断前导零的数字。或者 18 被转换为 char(4) ,它添加了前导零。我不记得哪一个胜出,但两者之一正在发生。随着填充的发生。这是 char 数据类型的函数。 varchar(可变长度字符)不会填充。
  • @xQbert Oracle 从最少限制的数据类型转换为最多限制的数据类型,因此如果将字符串与数字进行比较,它将尝试将字符串转换为数字。

标签: sql oracle oracle11g char oracle-sqldeveloper


【解决方案1】:

CHAR 列是否“自动”将零填充为一个值?

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

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

由于隐式类型转换。系统正在将 char 转换为 numeric 或将 numeric 转换为 char,在这种情况下,它要么删除前导零并比较数值,要么填充为相同的数据类型然后进行比较。我很确定它会从字符到数字,因此在比较时会删除前导零。

有关数据类型比较和隐式转换的更多详细信息,请参阅:https://docs.oracle.com/cd/B13789_01/server.101/b10759/sql_elements002.htm

更多的:

  • 在这种情况下:SELECT * FROM TABLE_A WHERE COLUMN_1='18';我 认为 18 已经是一个字符数据,所以它变成“18”(注意 18 之后的 2 个空格) 与“0018”相比
  • SELECT * FROM TABLE_A WHERE COLUMN_1=18; columN_1 被强制转换为数字,因此 18=18
  • SELECT * FROM TABLE_A WHERE COLUMN_1='0018'; column_1 已经是一个 char(4) 所以 '0018' = '0018'

【讨论】:

【解决方案2】:

CHAR 列是否“自动”将零填充为一个值?

编号From the documentation

如果您插入一个比列长度短的值,那么 Oracle 会用空白填充该值到列长度。

因此,如果您插入数字 18,它将隐式转换为字符串 '18 ',并带有两个尾随空格。你可以看到in this fiddle,它也显示了比较。

这意味着其他东西正在对您的数据进行零填充 - 插入之前的应用程序/代码,或者可能在触发器中。

我还注意到,在编写 SQL 时,如果我不在我的 where 子句中使用引号,它会返回结果,但如果我使用引号,它不会

数据类型比较和转换规则也显示在in the documentation

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

当你这样做时:

SELECT * FROM TABLE_A WHERE COLUMN_1=18;

字符串 '0018' 被隐式转换为数字 18 以便它可以与您的数字文字进行比较。转换后,前导零将毫无意义,因此 '0018''018 '18 ' 将全部匹配。

这意味着每一个表中的值必须进行转换才能进行比较;这也意味着如果您在 column_1 上有一个正常的索引,那么它就不会被用于该比较。

当你这样做时:

SELECT * FROM TABLE_A WHERE COLUMN_1='18';

列和文字是相同的数据类型,因此无需应用转换(因此可以使用普通索引)。 Oracle 将在此处使用blank-padded comparison semantics,因为该列是char,将较短的文字值填充到列大小为'18 ',然后只有在字符串完全匹配时才会匹配 - 所以'18 '会匹配但是@ 987654338@ 或 ' 18 ' 或其他任何东西都不会。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多