2012-06-08 2 views
2

Я создаю представление и тот же вид, преобразованный в материализованный вид в той же системе. Но делая то же самое в другой системе, я получил ошибку ORA-01722: invalid number при создании материализованного представления. Зачем?ORA-01722: неверный номер при создании материализованного представления

create materialized view MV_EMP_VALI 
refresh complete with rowid start with SYSDATE+1/24 AS 
(select * from V_CHA1); 

Вид: -

CREATE OR REPLACE VIEW V_CHA1 AS(SELECT EMPNO, 
     MONTHYEAR, 
     to_number(SUM(CPFEMO)) AS EMOLUMENTS, 
     to_number(SUM(CPEPF)) AS EMPPFSTATUARY, 
     to_number(SUM(AEMO)) AS AEMO, 
     to_number(SUM(APEPF)) AS APEPF, 
     MAX(recsts) AS recsts 
    FROM ((SELECT RECDATE, 
        (CASE WHEN (REPFEMOFLAG='N') THEN 
       round(NVL(trim(EMO), 0)) 
       ELSE 
       round(NVL(REVISEMO, 0)) END) as CPFEMO, 
       round(NVL(trim(EPF), 0)) AS CPEPF, 
       0 as AEMO, 
       0 as APEPF, 
       '' as recsts, 
       EMPNO 
      FROM EMP_VALI 
      WHERE EFLAG = 'Y' AND SFLAG = 'N' AND EMPNO IS NOT NULL and 
       RECDATE >'01-Apr-2011') 
     union all 
     (SELECT NDT.RECDATE AS RECDATE, 
       sum(round(NVL(trim(NDT.EMO), 0))) as CPFEMO, 
       sum(round(NVL(trim(NDT.EPF), 0))) as CPEPF, 
       0 as AEMO, 
       0 AS APEPF, 
       NDT.EMPNO 
      FROM EMP_VALI VAL, EMP_SUPP NDT 
      WHERE VAL.EMPNO = NDT.EMPNO AND VAL.EFLAG = NDT.EFLAG AND 
       VAL.EFLAG = 'Y' AND VAL.SFLAG = 'Y' AND 
       NDT.SLIFLAG='N' and 
       VAL.EMPNO is not null and 
       NDT.RECDATE = VAL.RECDATE 
      GROUP BY NDT.RECDATE, NDT.EMPNO) UNION ALL 
     (SELECT DT.RECPAIDDATE AS RECDATE, 
       0   as CPFEMO, 
       0   as CPEPF, 
       sum(round(NVL(trim(DT.EMO), 0))) as AEMO, 
       sum(round(NVL(trim(DT.EPF), 0))) AS APEPF, 
     max('') as recsts, 
       DT.EMPNO 
      FROM EMP_VALI VAL, EMP_SUPP DT 
      WHERE VAL.EMPNO = DT.EMPNO AND VAL.EFLAG = DT.EFLAG AND 
       VAL.EFLAG = 'Y' AND VAL.SFLAG = 'Y' AND 
       VAL.EMPNO IS NOT NULL and dt.RECDATE=val.RECDATE AND DT.SFLAG IS NOT NULL AND DT.SFLAG not in ('N','F') 
      GROUP BY DT.RECPAIDDATE, DT.EMPNO)UNION ALL 
     (SELECT DT.RECPAIDDATE AS RECDATE, 
     SUM((CASE 
      WHEN (DT.ECR4FLAG = 'C') then 
       round(NVL(trim(DT.EMO), 0)) 
      else 
      0 
      end)) as CPFEMO, 
     sum((CASE 
      WHEN DT.ECR4FLAG = 'C' then 
       round(NVL(trim(DT.EPF), 0)) 
      else 
       0 
      end)) as CPEPF, 
      sum((CASE 
      WHEN DT.ECR4FLAG = 'A' then 
       round(NVL(trim(DT.EMO), 0)) 
      else 
       0 
      end)) as AEMO, 
     sum((CASE 
      WHEN DT.ECR4FLAG = 'A' then 
       round(NVL(trim(DT.EPF), 0)) 
      else 
       0 
      end)) as APEPF, 
     max(EMPRECOVERYSTS) as recsts, 
     DT.EMPNO 
    FROM EMP_VALI VAL, EMP_SUPP DT 
WHERE VAL.EMPNO = DT.EMPNO AND VAL.EFLAG = DT.EFLAG AND 
     VAL.EFLAG = 'Y' AND VAL.SFLAG = 'Y' AND 
     VAL.EMPRECSTS = 'DEP' AND VAL.EMPNO IS NOT NULL and 
     dt.RECDATE = val.RECDATE AND DT.SFLAG IS NOT NULL AND 
     DT.SFLAG in ('F') 
GROUP BY DT.RECPAIDDATE, DT.EMPNO)) 
GROUP BY RECDATE, EMPNO) 
/

ответ

5

Это трудно сказать, из заявления, но если бы я должен был догадаться, я положил деньги на выражение:

RECDATE >'01-Apr-2011' 

предполагая столбец RECDATE действительно тип DATE. Поэтому Oracle пытается преобразовать значение символа '01-Apr-2011' в DATE. Поскольку вы не указали маску формата для этого, используются настройки NLS по умолчанию. Если они определяют число за месяц, то указанное выше значение приведет к отказу.

Вы должны никогда полагаться на неявное преобразование типа данных. В частности нет с датами. Используйте ANSI литерал вместо:

RECDATE > DATE '2011-04-01' 

или использовать функцию to_date() с маской формата:

RECDATE > to_date('01-Apr-2011', 'dd-mon-yyyy') 

Обратите внимание, что это может по-прежнему не для определенных настроек NLS_LANG. На французском языке вам нужно будет указать «Avr» вместо «Apr». Поэтому, если вы не уверены, что можете контролировать все настройки NLS_XXX все время, я настоятельно рекомендую вместо них использовать месячные номера. Если вы более комфортно, используя TO_DATE(), чем ANSI литералов, вы можете использовать:

RECDATE > to_date('01-04-2011', 'dd-mm-yyyy') 

Редактировать

, если это не столбец даты вам нужно проверить любой другой столбец для неявных преобразований данных.

Это выражение:

sum(round(NVL(trim(DT.EMO), 0))) 
round(NVL(trim(EMOLUMENTS), 0)) 
round(NVL(trim(DT.EMO), 0)) 
round(NVL(trim(DT.EPF), 0)) 

выглядеть подозрительно. Если в столбцах есть реальные числа, то trim() является недопустимым и бесполезным. Если это не номера, они могут вызвать эту ошибку в зависимости от содержимого столбца.

Это выражение to_number(SUM(CPFEMO)) также бесполезно, поскольку sum() уже вернет число, нет причин для вызова to_number на number(). Хотя я сомневаюсь, что это может поднять вашу ошибку, вы все равно должны ее избегать, поскольку это не имеет никакого смысла.

+0

Я изменил/изменил TO_DATE INSTEAD OF '01 -Apr-2011'. Но у меня такая же ошибка. Есть ли какие-либо возможности в characteret.One система с US7ASCII и anothere системы с WE8ISO8859P1.So есть ли какие-либо проблемы с этим набором символов , – user1357722

+0

@ user1357722: см. Мое редактирование. –