我有一些表格的观点:
SELECT UM00200M.ACCOUNT_NO AS INDEX1,
CONCAT (CONCAT (TRIM (UM00200M.PERSON_LNM), ' '),
TRIM (UM00200M.PERSON_FNM))
AS INDEX2,
DECODE (NVL (TRIM (SG00100M.PERSON_ID_CUSTOM), 0),
0, UM00200M.PERSON_NO,
SG00100M.PERSON_ID_CUSTOM)
INDEX3,
NULL AS INDEX4,
'CONS_ACCTG' AS GROUPNAME
FROM UM00200M, SG00100M
WHERE UM00200M.PERSON_NO = SG00100M.PERSON_NO
这给了我(对不起格式化):
Column_Name DATA_TYPE NULLABLE COLUMNT_ID COMMENTS INSERTABLE UPDATEABLE INDEX1 NUMBER(14,0) No 1 YES YES YES INDEX2 VARCHAR2(81) Yes 2 NO NO NO INDEX3 NUMBER Yes 3 NO NO NO INDEX4 VARCHAR2(0) Yes 4 NO NO NO GROUPNAME CHAR(10) Yes 5 NO NO NO
我正在寻找所有INDEX3 = 524118914
的记录--Looking for INDEX3 = 524118914
--Fails: 01722. 00000 - "invalid number"
Select *
from Cayenta.CAHeader
where INDEX3 = 524118914;
--Fails: 01722. 00000 - "invalid number"
Select *
from Cayenta.CAHeader
where INDEX3 > 524118000 and INDEX3 < 524118999;
--Works
Select *
from Cayenta.CAHeader
where INDEX3 > 524118000 and INDEX3 < 524999999;
--Fails: 01722. 00000 - "invalid number"
Select *
from Cayenta.CAHeader
where INDEX3 > 524118000 and INDEX3 < 524999999
ORDER BY INDEX3;
执行查询时,我没有得到我期望的结果。为什么我会收到“无效号码?”
我认为它与DECODE函数有关,而SG00100M.PERSON_ID_CUSTOM是一个CHAR(15 BYTE)字段,但填充了所有数字数据。 (我知道 - 糟糕的设计,但它是第三方产品。)
我感谢任何人都可以提供的任何见解。
答案 0 :(得分:1)
这里发生的是隐式转换。这意味着在where子句的条件中,您将列INDEX3与数字进行比较。
INDEX3是一个CHAR列,因此下面摘录了Oracle文档中关于隐式转换的内容:
在算术运算和字符与比较之间进行比较 非字符数据类型,Oracle从任何字符数据类型转换为 数字,日期或者rowid,视情况而定
这意味着INDEX3中的所有值都将转换为NUMBER,以便将它们与您在示例中给出的数字进行比较。
解决这个问题的简单方法是在数字周围使用引号并将其视为字符串。
where INDEX3 = '524118914'
这将适用于相等条件,但对于使用&gt; =和&lt; =的范围可能效果不佳,除非它们在开头用零填充。使用正确的数据类型也意味着将使用此列上的任何索引。
如果您认为这应该是一个数字字段,那么至少有一行中包含非数字数据。要跟踪此情况,您可以尝试使用以下条件检查数据:
where regexp_like(INDEX3, '[^[:digit:]]')
这只检查数字(不是小数点等),因此您可能需要根据您的要求进行定制。
我对数据库为何说该列具有数字数据类型感到有点困惑。看起来这与DECODE语句的计算方式有关,数据类型来自第一个结果参数,即使默认参数是CHAR类型。
答案 1 :(得分:0)
在角色字段中存储数字总是很痛苦......
请为View尝试以下SQL - 解码检查PERSON_ID_CUSTOM以获取Number。如果是,则转换它,如果不是 - 它将被替换为NULL:
SELECT UM00200M.ACCOUNT_NO AS INDEX1,
CONCAT (CONCAT (TRIM (UM00200M.PERSON_LNM), ' '),
TRIM (UM00200M.PERSON_FNM))
AS INDEX2,
DECODE (NVL (TRIM (SG00100M.PERSON_ID_CUSTOM), 0),
0, UM00200M.PERSON_NO,
decode((
REPLACE(
TRANSLATE(
TRIM(SG00100M.PERSON_ID_CUSTOM),'0123456789','00000000000'
),'0' ,NULL
)
),NULL,to_number(trim(SG00100M.PERSON_ID_CUSTOM)))
) INDEX3,
NULL AS INDEX4,
'CONS_ACCTG' AS GROUPNAME
FROM UM00200M, SG00100M
WHERE UM00200M.PERSON_NO = SG00100M.PERSON_NO