2009-01-20 11 views
5

Tony Andrews innym question dała przykład:Czy ta implementacja jest zgodna z SQL-92?

IF p_c_courtesies_cd 
    || p_c_language_cd 
    || v_c_name 
    || v_c_firstname 
    || v_c_function 
    || p_c_phone 
    || p_c_mobile p_c_fax 
    || v_c_email is not null 
THEN 
    -- Do something 
END IF; 

jako mądry (jeśli nie jest odrobinę niejasne) alternatywnie do funkcji Oracle koalescencji. Oczywiście, działa, jeśli dowolny argument nie jest pusty, test IF jest prawdziwy. Moje pytanie: Czy implementacja Oracle powyższej operacji konkatenacji SQL-92 jest zgodna? Czy nie powinno się wyrażać wartości NULL w wyrażeniu NULL? Jeśli nie uważasz, to dlaczego wyrażenie 1 + NULL ma wartość NULL?

Odpowiedz

3

Nie, traktowanie przez Oracle wartości zerowych jest specyficzne, odmienne od wszystkich innych i niezgodne ze standardami ANSI. Jednak w obronie Oracle prawdopodobnie się to udało i było zaangażowane w to leczenie na długo zanim standard ANSI był zgodny z tym!

Wszystko zaczyna się od tego, że Oracle przechowuje ciągi znaków z liczbą znaków, po której następuje ciąg danych. Wartość NULL jest reprezentowana przez liczbę znaków równą zeru bez żadnych kolejnych danych ciągu - która jest dokładnie taka sama, jak pusty ciąg ("'). Oracle po prostu nie ma sposobu na ich rozróżnienie.

Prowadzi to do dziwnych zachowań, takich jak ten przypadek konkatenacji. Oracle ma także funkcję LENGTH, która zwraca długość łańcucha znaków, ale zostało to zdefiniowane w odwrotny sposób, więc LENGTH ('') zwraca NULL, a nie zero. A więc:

LENGTH('abc') + LENGTH('') IS NULL 

LENGTH('abc' || '') = 3 

co wydaje mi się naruszać podstawowe zasady matematyczne.

Oczywiście deweloperzy Oracle tak się do tego przyzwyczaili, że wielu z nas nie widzi w tym nic złego ani dziwnego - niektórzy twierdzą, że reszta świata jest zła, a pusty ciąg i NULL to to samo!

+0

+1, ciekawe dodatkowe informacje. – DCookie

1

Cóż COALESCE jest jawnie zdefiniowany przez standard SQL-92, aby zwrócić pierwszą wartość nie-NULL na liście; więc z definicji implementacja Oracle zachowuje się poprawnie.

EDYCJA: The SQL-92 spec; wyszukaj COALESCE, aby zobaczyć jego definicję.

To powiedziawszy, nie ma nic szczególnego w NULL, który stwierdza, że ​​każda operacja z udziałem NULL musi mieć wartość NULL. Bardziej dokładnym ograniczeniem jest to, że NULL nie jest ani fałszem, ani 0, ani równym innemu NULL (np. NULL == NULL jest fałszywe, ponieważ jedna NULL nie jest równa innej NULL). Nie znaczy to jednak, że nie mogą być logicznie spójne sposoby pracy z NULL, które nie zawsze zwracają NULL.

EDYCJA: Więc NULL + 1 ma wartość NULL w taki sam sposób, jak NaN + 1 jest nadal NaN; to efektywnie niezdefiniowana operacja.

+0

+1 za link. Jednak standard, tak jak go czytam, wyraźnie stwierdza, że ​​wynik połączenia wartości pustej z cokolwiek powinien być zerowy. – DCookie

+0

@DCookie: ah, myślałem, że pytasz, czy implementacja COALESCE była standardowa. Jednak zgadzam się, ich implementacja CONCATENATION NIE jest standardowa, jeśli wraca do niej nie-NULL. – nezroy

+0

Przepraszam, że nie wymawiając tego, domyślam się, że przyjąłem z przykładu, który podałem, że miałem na myśli operację konkatenacji :-( – DCookie

0
SQL> select 'something'||null from dual; 

'SOMETHIN 
--------- 
something 

Łączenie ciągów z wartością zerową nie daje wartości zerowej. Myślę, że to normalne zachowanie, jestem do tego przyzwyczajony. Nie wiem, co jeszcze powiedzieć.

+0

Tylko dlatego, że Oracle zaimplementował go w ten sposób, nie czyni go poprawnym. – DCookie

+0

Coś jest poprawnego, gdy działa zgodnie z instrukcjami w instrukcjach. – tuinstoel

+0

Jako przykład, Oracle równające pusty ciąg do NULL nie jest przez wielu postrzegane jako poprawne. – DCookie

2

@Nezroy: Dzięki za link. Jednak, jak czytałem ten standard, uważam, że stwierdza on, że wdrożenie Oracle jest w rzeczywistości nieprawidłowe. Sekcja 6.13, Zasady ogólne, poz 2a:

 2) If <concatenation> is specified, then let S1 and S2 be the re- 
     sult of the <character value expression> and <character factor>, 
     respectively. 

     Case: 

     a) If either S1 or S2 is the null value, then the result of the 
      <concatenation> is the null value. 
+0

Początkowo myślałem, że pytasz, czy implementacja COALESCE była standardowa. Jednak zgadzam się, ich implementacja CONCATENATION NIE jest standardowa, jeśli wraca do niej nie-NULL. – nezroy

+0

Tak, moje pytanie nie było jasne. Przepraszam. Przynajmniej * I * wiedziałem co mam na myśli ;-) – DCookie

1

oparciu o części SQL-92 ciemno podświetlone DCookie i zachowania innych DB, powiedziałbym Oracle nie zachowuje się standardowo z ich operatorem konkatenacji.

Oracle (z odpowiedzią tuinstoel za):

SQL> select 'something'||null from dual; 

'SOMETHIN 
--------- 
something

MSSQL:

SELECT 'something'+NULL; 

NULL

PostgreSQL:

postgres=# \pset null '(null)' 
Null display is "(null)". 
postgres=# select 'something'||null as output; 
output 
-------- 
(null) 
(1 row) 

MySQL:

mysql> select concat('something',NULL) as output; 
+--------+ 
| output | 
+--------+ 
| NULL | 
+--------+ 
1 row in set (0.00 sec) 
Powiązane problemy