2009-07-10 10 views
2

kann nvl() Funktion kaskadiert werden, ... wurde mir im IBM Interview gefragt ..... und warum ????Kann die NVL-Funktion kaskadiert werden?

+0

Sind wir reden über Oracle NVL-Funktion (weil die implizite Konvertierung Versuch von 'etwas Text' zu einem Zeitpunkt ausgefallen ist)? Und was meinen sie, wenn sie "kaskadiert" sagen? –

+0

ja oracle nvl und cascade bedeutet nvl in nvl – hrishi

Antwort

14

Noch besser wäre es, verwenden COALESCE

+0

Ich stimme zu, Coalesce ist eine elegante Lösung für viele Situationen, wo mehrere NVL verwendet werden würde –

+1

Ich denke, dass der Befragte nach der Antwort suchte, "Ja ... aber ich würde nur verwenden COALESCE stattdessen ... " – Eric

+1

Ich erinnere mich, dass mir gesagt wurde, dass das zweite Argument für NVL immer ausgewertet wird, egal ob es benutzt wird oder nicht, was bei COALESCE nicht der Fall ist. Dies kann COALESCE in einigen Fällen zur leistungsstärkeren Option machen. –

3

Warum nicht? Zum Beispiel:

select NVL(null, NVL(null, 1)) from dual 

kann es sein, so etwas wie:

select NVL(delete_date, NVL(edit_date, create_date)) AS last_change 
from Table 

Kann sein, sie wollten Sie sagen, dass es deterministische Funktion ist. Es ist also wiedereintretend.

+0

Keine Notwendigkeit, es zu verschachteln, obwohl. 'NVL (delete_date, edit_date, create_date)' würde das Gleiche tun. – Thilo

+0

ORA-00909: ungültige Anzahl von Argumenten – cahen

8

Meine Antwort:

Ja, NVL kaskadiert werden. Es ist etwas, was ich auf Code sehen würde, der von Oracle-Versionen bis einschließlich 8i portiert wurde, weil COALESCE bis Oracle 9i nicht unterstützt wurde.

COALESCE ist ein ANSI SQL 99-Standard und funktioniert wie eine CASE/SWITCH-Anweisung in der Auswertung jedes Ausdrucks in der richtigen Reihenfolge und setzt die Auswertung von Ausdrücken nicht fort, wenn ein Nicht-Null-Ausdruck gefunden wird. Dies wird als Kurzschluss bezeichnet. Ein weiterer Vorteil der Verwendung von COALESCE ist, dass die Datentypen nicht übereinstimmen müssen, was bei der Verwendung von NVL erforderlich ist.

Dieses:

SELECT COALESCE(1.5/NULL, 
       SUM(NULL), 
       TO_CHAR(SYSDATE, 'YYYY')) abc 
    FROM DUAL 

... kehrt: 2009 (für die nächsten ~ 32 Tage, sowieso)

1

Der häufigste Grund, dass ich für kaskadierte NVL die gesehen haben, ist, dass Datenbanken ändern sich im Laufe der Zeit. Das ursprüngliche Design hatte eine Tabelle, die später geändert wurde, um mehr Spalten in der Tabelle zu haben. Alter-Anweisungen erstellt die neuen Spalten als NULL erlaubt und dies wurde Vorteil mit View, so dass der Code oben nicht geändert werden musste. Das Problem war, dass eine einzige Spalte, change_date, durch mehrere Spalten ersetzt wurde. Update_Date, Comment_Date und Approval_date. Jede der 3 neuen Spalten kombinieren jetzt bekommt ein „CHANGE_DATE“ in der Ansicht mit

create or replace view OldTableNmae as 
select other_columns 
    , nvl (update_date, nvl (comment_date, approval_date)) change_date 
    , more_columns 
from new_table 
/
1

Wie bereits gesagt, kann NVL kaskadiert werden, aber die bevorzugte Lösung wäre COALESCE zu verwenden, anstatt. Allerdings sind die beiden Funktionen nicht vollständig austauschbar:

1), wie an anderer Stelle erwähnt, COALESCE nur die Argumente aus dem ersten auswertet, bis es einen trifft, die nicht

2) jedoch auf null wertet, erfordert COALESCE alle Argumente vom gleichen Datentyp sein, also STRICTER als NVL, die zuerst eine implizite Konvertierung versuchen wird.

z.

SELECT COALESCE(1.5/NULL, 
      SUM(NULL), 
      TO_CHAR(SYSDATE, 'YYYY')) abc 
FROM DUAL 

wirft in der Tat den Fehler ORA-00932: inconsistent datatypes: expected NUMBER got CHAR

NVL würde das aktuelle Jahr statt zurückkehren

SELECT NVL(1.5/NULL, 
      NVL(SUM(NULL), 
       TO_CHAR(SYSDATE, 'YYYY'))) abc 
FROM DUAL 

Weitere Beispiele:

select coalesce('some text',sysdate) from dual; 

wirft ORA-00932: inconsistent datatypes: expected CHAR got DATE, während

select nvl('some text',sysdate) from dual; 

kehrt some text, aber

select nvl(sysdate,'some text') from dual; 

wirft ORA-01841: (full) year must be between -4713 and +9999, and not be 0

Verwandte Themen