0

私はいくつかのテーブルからの眺めを持っています:

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_TYPENULLABLECOLUMNT_IDコメントINSERTABLEUPDATEABLE
INDEX1 NUMBER(14,0)いいえ1はいはいはい
INDEX2 VARCHAR2(81)はい2いいえいいえいいえ
INDEX3NUMBERはい3NONO NO
INDEX4 VARCHAR2(0)はい4 NO NO NO
GROUPNAME CHAR(10)はい5いいえいいえいいえ

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)フィールドですが、すべての数値データが入力されています。(私は知っています-悪いデザインですが、それはサードパーティ製品です。)

誰もが提供できる洞察に感謝します。

4

2 に答える 2

1

ここで起こっているのは暗黙の変換です。これは、where 句の条件で、列 INDEX3 を数値と比較していることを意味します。

INDEX3 は CHAR 列であるため、暗黙的な変換に関して適用される Oracle ドキュメントからの次の抜粋:

文字データ型と非文字データ型の算術演算および比較中に、Oracleは任意の文字データ型から数値、日付またはROWIDに適切に変換します。

これは、例で指定した数値と比較できるようにするために、INDEX3 のすべての値が NUMBER に変換されることを意味します。

これを回避する簡単な方法は、数値を引用符で囲み、文字列として扱うことです。

where INDEX3 = '524118914'

これは等値条件では機能しますが、先頭にゼロが埋め込まれていない限り、>= および <= を使用する範囲ではうまく機能しない可能性があります。正しいデータ型を使用することは、この列のすべてのインデックスが使用されることも意味します。

これが数値フィールドであると思われる場合は、数値以外のデータを含む行が少なくとも 1 行あります。これを追跡するには、次の条件を使用してデータをチェックしてみてください。

where regexp_like(INDEX3, '[^[:digit:]]')

これは数字のみをチェックするため(小数点などはチェックしません)、要件に合わせて調整する必要がある場合があります。

データベースが列に数値データ型があると言っている理由について少し混乱しました。これは、デフォルトの引数が CHAR 型であるにもかかわらず、DECODE ステートメントが評価され、データ型が最初の結果引数に由来する方法に関連しているようです。

于 2012-05-16T19:26:14.397 に答える
0

文字フィールドに数値を格納するのは常に面倒です...

ビューに対して次の SQL を試してください - デコードは PERSON_ID_CUSTOM の数値をチェックします。そうである場合は変換し、そうでない場合は 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
于 2012-05-16T19:16:37.800 に答える