2017-04-12 11 views
0

Ich versuche, diese Abfrage execut, die ein Teil meines Verfahrens ist, und die eine Erstellung der probleme:PLSQL Fehler: ungültige Nummer

select SUM(
       CASE --DT007 
       WHEN PRO.Sens_Mnt_Brut = 'D' 
       THEN '-' || TO_CHAR(PRO.Mnt_Brut,'99999999999,99') 
       WHEN PRO.Sens_Mnt_Brut = 'C' 
       THEN '' || TO_CHAR(PRO.Mnt_Brut,'99999999999,99') 
       END) OVER(PARTITION BY PRO.Num_Est_Remise) - SUM(TO_CHAR(PRO.Mnt_Comm_Tot_Ope,'99999999999,99')) OVER(PARTITION BY PRO.Num_Est_Remise))--DT015 

From dlc_pr_operation pro; 

Nach der Ausführung Ich erhalte diese Fehlermeldung:

ORA-01722: invalid number 
01722. 00000 - "invalid number" 
*Cause:  
*Action: 

ist es wegen der Umwandlung von Char in Zahl und die Kommas, die ich der Abfrage hinzufügen oder ist es etwas anderes.

Vielen Dank im Voraus für Ihre Hilfe.

+0

Was ist der Datentyp von PRO.Mnt_Brut? Ist es möglich, Beispieldaten zu teilen? – tilper

+0

es ist eine Zahl (16.0), aber ich möchte ein Komma vor den 2 letzten Zahlen setzen –

+2

'SUM (TO_CHAR (...))' ergibt überhaupt keinen Sinn. –

Antwort

3

Sie machen eine Menge explizite und implizite Konvertierung zwischen Zahlen und Strings, und Inkonsistenzen und Annahmen stolpern Sie. Aber sie sind sowieso alle unnötig - Sie müssen überhaupt nicht zu Strings konvertieren. Ihre Abfrage könnte neu geschrieben werden als:

select SUM(
    CASE PRO.Sens_Mnt_Brut WHEN 'D' THEN -1 ELSE 1 END * PRO.Mnt_Brut 
) OVER (PARTITION BY PRO.Num_Est_Remise) 
    - SUM(PRO.Mnt_Comm_Tot_Ope) OVER(PARTITION BY PRO.Num_Est_Remise) 
From dlc_pr_operation pro; 

die gerade entscheidet, basierend auf den Sens_Mnt_Brut Flags, ob Mnt_Brut verwendet werden soll, wie sie ist oder negiert werden soll, und multipliziert sie mit 1 oder -1 entsprechend.


Sie haben mindestens zwei Probleme mit Ihrem Ansatz. Sie konvertieren Zahlen in Zeichenfolgen mit einem expliziten Formatmodell und konvertieren sie anschließend implizit in Zahlen zurück, um sie zu summieren. Das bedeutet, (a) Sie verlassen sich auf Ihre NLS-Einstellungen für die implizite Konvertierung und (b) die Strings, die Sie bilden, können auf keinen Fall mit Ihrem expliziten Modell zurückkonvertiert werden.

wir mit einigen Dummy-Daten starten, die in den ersten Zweig gehen würde:

with dlc_pr_operation (Sens_Mnt_Brut, Mnt_Brut, Mnt_Comm_Tot_Ope, Num_Est_Remise) as (
    select 'D', 1234.56, 1, 2 from dual 
) 
select to_number('-' || TO_CHAR(PRO.Mnt_Brut,'99999999999,99')) from dlc_pr_operation pro; 

ORA-01722: invalid number 

Wenn Sie die Zeichenfolge zu buchen, es bilden Sie werden sehen:

with dlc_pr_operation (Sens_Mnt_Brut, Mnt_Brut, Mnt_Comm_Tot_Ope, Num_Est_Remise) as (
    select 'D', 1234.56, 1, 2 from dual 
) 
select '-' || TO_CHAR(PRO.Mnt_Brut,'99999999999,99') from dlc_pr_operation pro; 

'-'||TO_CHAR(PRO 
---------------- 
-   12,35 

Die Umwandlung dieser Zeichenfolge scheitert an all dem Leerraum.

with dlc_pr_operation (Sens_Mnt_Brut, Mnt_Brut, Mnt_Comm_Tot_Ope, Num_Est_Remise) as (
    select 'D', 1234.56, 1, 2 from dual 
) 
select to_number('-' || TO_CHAR(PRO.Mnt_Brut,'FM99999999999,99')) from dlc_pr_operation pro; 

TO_NUMBER('-'||TO_CHAR(PRO.MNT_BRUT,'FM99999999999,99')) 
-------------------------------------------------------- 
-12,35             

aber nur, wenn die NLS-Einstellung und besonders NLS_NUMERIC_CHARACTERS, richtig ist: Man könnte das mit einem leicht modifizierten Format Modell vermeiden. Wenn ich dieselbe Abfrage ausführen würde, nachdem ich alter session set nls_numeric_characters = '.,' getan habe, würde dies auch ORA-01722 erhalten, weil Sie ein festes Komma verwendet haben. Sie können entweder ändern explizit die Sitzung, oder wechseln Sie von einer festen , die Ober D Dezimaltrennzeichen:

alter session set nls_numeric_characters = '.,'; 

with dlc_pr_operation (Sens_Mnt_Brut, Mnt_Brut, Mnt_Comm_Tot_Ope, Num_Est_Remise) as (
    select 'D', 1234.56, 1, 2 from dual 
) 
select to_number('-' || TO_CHAR(PRO.Mnt_Brut,'FM99999999999,99')) from dlc_pr_operation pro; 

ORA-01722: invalid number 

with dlc_pr_operation (Sens_Mnt_Brut, Mnt_Brut, Mnt_Comm_Tot_Ope, Num_Est_Remise) as (
    select 'D', 1234.56, 1, 2 from dual 
) 
select to_number('-' || TO_CHAR(PRO.Mnt_Brut,'FM99999999999D99')) from dlc_pr_operation pro; 

TO_NUMBER('-'||TO_CHAR(PRO.MNT_BRUT,'FM99999999999D99')) 
-------------------------------------------------------- 
               -1234.56 

Dies wird noch implizite Konvertierung zurück zu Zahlen natürlich tun, in Ihrer Abfrage.


die geänderte Abfrage von Anfang dieser Antwort (falls Sie so weit zurück erinnern kann) statt und einige weitere Dummy-Daten gibt die Ausgabe:

with dlc_pr_operation (Sens_Mnt_Brut, Mnt_Brut, Mnt_Comm_Tot_Ope, Num_Est_Remise) as (
    select 'D', 1234.56, 1, 2 from dual 
    union all select 'X', 123.45, 2, 4 from dual 
    union all select 'Y', 456.78, 3, 4 from dual 
) 
select SUM(
    CASE PRO.Sens_Mnt_Brut WHEN 'D' THEN -1 ELSE 1 END * PRO.Mnt_Brut 
) OVER (PARTITION BY PRO.Num_Est_Remise) 
    - SUM(PRO.Mnt_Comm_Tot_Ope) OVER(PARTITION BY PRO.Num_Est_Remise) as result 
From dlc_pr_operation pro; 

    RESULT 
---------- 
-1235,56 
575,23  
575,23  

Da es keine Umwandlung Ihre NLS Einstellungen sind jetzt nicht wichtig; Das endgültige Ergebnis wird jedoch vom Client formatiert, indem das Dezimaltrennzeichen der Sitzung automatisch verwendet wird. Daher wird in diesem Beispiel immer noch ein Kommatrennzeichen mit den numerischen Zeichen ',.' angezeigt.Wenn ich meine Sitzung '.,' stattdessen geändert würde ich sehen:

RESULT 
---------- 
    -1235.56 
    575.23 
    575.23 

Ob das das Ergebnis ist wollen Sie tatsächlich weniger klar. Es kann nützlich sein, andere Spalten einzubeziehen, aber Sie müssen auch prüfen, ob Sie wirklich die analytischen Funktionen, nicht nur Aggregate, wollen.


sagte Sie in einem Kommentar:

es ist eine Zahl (16,0), aber ich möchte vor den zwei letzten Ziffern ein Komma setzen

Das ist nicht wirklich Sinn macht , es sei denn, Sie speichern finanzielle Beträge als ganze Zahlen - im Wesentlichen als Cent/Cent statt Pfund/Euro/Dollar -, sondern möchten sie freundlicher zeigen; in dem Fall, dass Sie sie durch 100 dividiert werden sollen, Mangeln sie nicht als Strings:

with dlc_pr_operation (Sens_Mnt_Brut, Mnt_Brut, Mnt_Comm_Tot_Ope, Num_Est_Remise) as (
    select 'D', 123456, 100, 2 from dual 
    union all select 'X', 12345, 200, 4 from dual 
    union all select 'Y', 45678, 300, 4 from dual 
) 
select (SUM(
    CASE PRO.Sens_Mnt_Brut WHEN 'D' THEN -1 ELSE 1 END * PRO.Mnt_Brut 
) OVER (PARTITION BY PRO.Num_Est_Remise)/100) 
    - (SUM(PRO.Mnt_Comm_Tot_Ope) OVER(PARTITION BY PRO.Num_Est_Remise)/100) as result 
From dlc_pr_operation pro; 

    RESULT 
---------- 
    -1235.56 
    575.23 
    575.23 

... vorausgesetzt, (wieder), dass beiden Werte summiert werden, so gespeichert sind; Sie können auch die zwei Summen subtrahieren und die Summe durch 100 teilen, wenn Sie bevorzugen.

+1

Eine wirklich detaillierte Antwort. Ich hätte mit 'CASE PRO.Sens_Mnt_Brut WENN 'D' THEN -1 ELSE 1 END * PRO.Mnt_Brut 'geführt, was die richtige Lösung ist, und dann in die Datenkonversion mire gewatet :) – APC