rod*_*063 1 sql oracle char oracle11g oracle-sqldeveloper
我正在使用 Oracle DB 11g
我有一个数据库表,其主键是 CHAR(4) - 尽管该列仅使用数字。
我注意到有些记录显示“0018”或“0123”。
我注意到很少有奇怪的事情并且需要一些帮助
- CHAR 列是否“自动”将零填充到某个值?
-我还注意到,在编写 SQL 时,如果我不在 where 子句中使用引号,它会返回结果,但如果我使用引号,它不会返回结果?例如
DB CHAR(4) 列的键为“0018”
我用这个查询
SELECT * FROM TABLE_A WHERE COLUMN_1=18;
Run Code Online (Sandbox Code Playgroud)
我按预期得到了行。
但是当我尝试以下操作时
SELECT * FROM TABLE_A WHERE COLUMN_1='18';
Run Code Online (Sandbox Code Playgroud)
这不起作用,但它又起作用了
SELECT * FROM TABLE_A WHERE COLUMN_1='0018';
Run Code Online (Sandbox Code Playgroud)
所以我有点困惑第一个查询如何在没有引号的情况下按预期工作?
CHAR 列是否“自动”将零填充到某个值?
否。来自文档:
如果插入的值短于列长度,则 Oracle 会将该值空白填充到列长度。
因此,如果您插入数字,18它将隐式转换为字符串'18 ',并带有两个尾随空格。您可以在这个小提琴中看到这一点,它也显示了比较。
这意味着其他东西正在对您的数据进行零填充 - 要么是插入之前的应用程序/代码,要么可能是在触发器中。
我还注意到,在编写 SQL 时,如果我不在 where 子句中使用引号,它会返回结果,但如果我使用引号,它不会返回结果
数据类型比较和转换规则也在文档中显示:
当比较字符值和数值时,Oracle 会将字符数据转换为数值。
当你这样做时:
SELECT * FROM TABLE_A WHERE COLUMN_1=18;
Run Code Online (Sandbox Code Playgroud)
该字符串'0018'会隐式转换为数字18,以便可以将其与数字文字进行比较。一旦转换后,前导零就毫无意义,因此'0018','018 '和18 ' 都会匹配。
使用匹配的零填充列值,您确实会得到结果:(18转换'0018'为数字)=18
这意味着表中的每个值都必须先进行转换才能进行比较;这也意味着,如果您有一个正常的索引,那么column_1它就不会用于该比较。
当你这样做时:
SELECT * FROM TABLE_A WHERE COLUMN_1='18';
Run Code Online (Sandbox Code Playgroud)
列和文字是相同的数据类型,因此无需应用转换(因此可以使用普通索引)。Oracle 将在这里使用空白填充比较语义,因为列是char,将较短的文字值填充为列大小'18 ',然后只有当字符串完全匹配时才会匹配 - 所以会匹配,'18 '但'0018'或' 18 '或其他任何东西都不会匹配。
如果零填充的列值不匹配,则不会得到结果:'0018'!= '18 '('18'填充到长度 4)
当你这样做时:
SELECT * FROM TABLE_A WHERE COLUMN_1='0018';
Run Code Online (Sandbox Code Playgroud)
列和文字是相同的数据类型,因此没有转换,没有应用填充,因为文字已经与列值的长度相同,并且只有在字符串完全匹配时它才会匹配 - 所以会'0018'匹配 but'18 '或' 18 '或其他任何内容不会。
使用匹配的零填充列值,您确实会得到结果:'0018'='0018'