似乎无法通过简单的ID查询找到记录

时间:2012-05-16 17:51:13

标签: sql oracle oracle10g

我有一些表格的观点:

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)字段,但填充了所有数字数据。 (我知道 - 糟糕的设计,但它是第三方产品。)

我感谢任何人都可以提供的任何见解。

2 个答案:

答案 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