Rozważmy trzy przykłady:
1.Nie działa inicjalizacja dla typów zakotwiczonych w PL/SQL
CREATE TABLE TBL_TEST
(FIELD NUMBER DEFAULT 0 NOT NULL);
DECLARE
vn_Number TBL_TEST.FIELD%TYPE;
BEGIN
IF vn_Number IS NULL THEN
DBMS_OUTPUT.PUT_LINE('Inicjalizacja nie zadziałała');
END IF;
END;
Powyższy przypadek jest dość podstępny- zakotwiczenia pobierają tylko informację o typie bez checków...
2.Funkcje agregujące
CREATE TABLE TBL_TEST
(FIELD NUMBER );
ciąg instrukcji insert, takze z wartością NULL;
INSERT INTO TBL_TEST (FIELD) VALUES (NULL);
INSERT INTO TBL_TEST (FIELD) VALUES (1);
INSERT INTO TBL_TEST (FIELD) VALUES (8);
COMMIT;
Wykonajmy teraz zapytanie:
SELECT SUM(FIELD), AVG(FIELD), AVG(NVL(FIELD,0)) FROM TBL_TEST
Otrzymane wyniki to
9 4.5 3
Powyższy wynik świadczy o tym, że funkcja AVG do liczenia średniej wybiera wartości tylko NOT NULL. Dlatego warto dokładnie przestudiować dokumentację opisującą działanie funkcji agregujących..
3. Operatory arytmetyczne
DECLARE
vn_A NUMBER(2) :=1;
vn_B NUMBER(2) ;
vn_C NUMBER(3);
BEGIN
vn_C := vn_A + vn_B;
IF vn_C IS NULL THEN
DBMS_OUTPUT.PUT_LINE('RESULT IS NULL');
END IF;
END;
Dla operatorów arytmetycznych i wbudowanych funkcji matematycznych np. ABS i SIN, jeśli co najmniej jeden parametr jest NULL, to zwracana jest także wartość NULL..
Rozpatrując powyższe przykłady, nasuwa się oczywisty wniosek - należy unikać wartości NULL w algorytmach obliczeniowych.... są one źródłem bardzo złośliwych i podstępnych błędów
Proponuję zastosowanie poniższych zaleceń:
- na etapie projektowania struktury baz danych dla pól tabel wykorzystywanych w algorytmach numerycznych powinno się wymuszać wartość NOT NULL. Wartość domyślna jest niekonieczna, niech lepiej zostanie bezpośrednio zainicjowana w kodzie
- należy zamiast zmiennych typu NUMBER, BINARY_INTEGER stosować zmienne typu SIMPLE_DOUBLE, SIMPLE_INTEGER, SIMPLE_FLOAT oraz inne z przedrostkiem SIMPLE, które wymagają inicjacji na poziomie deklaracji.. Wykonanie poniższego bloku
vn_Test SIMPLE_INTEGER;
BEGIN
vn_Test := 0;
END;
zakończy się błędem: PLS-00218: a variable declared NOT NULL must have an initialization assignment. oprócz tego jakiekolwiek przypisanie wartości NULL do zmiennej vn_Test też wygeneruje wyjątek... Wyjątki wyłowią niebezpieczne fragmenty kodu w algorytmach..
- Jeśli musimy użyć typu NUMBER(12,2) to wówczas najlepiej stworzyć nagłówek pakietu do definicji własnych typów
SUBTYPE t_Number_12_2 IS NUMBER(12,2) NOT NULL;
END;
wówczas wykonanie poniższego bloku
DECLARE
vn_Test PCKG_MyTypes.t_Number_12_2;
BEGIN
vn_test := 0;
END;
także zakończy się wyjątkiem : PLS-00218: a variable declared NOT NULL must have an initialization assignment