Blog programisty w Oracle PL/SQL

Jest to blog eksperymentatora programisty w PL/SQL dla Oracle. Wszystkie kody tutaj zamieszczone mogą być dowolnie wykorzystywane i zmieniane. A jeśli Ktoś z Gości znajdzie błąd, będę niezwykle wdzięczny...
Zapisz

Szukaj na tym blogu

Pokazywanie postów oznaczonych etykietą NULL. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą NULL. Pokaż wszystkie posty

środa, 27 kwietnia 2011

NULL a poprawnośc algorytmów obliczeniowych..

Wartość NULL bywa przyczyną wielu błędów w algorytmach  obliczeniowych - większość  z nich wynika  braku inicjacji zmiennych:
 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
       DECLARE
           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
     CREATE OR REPLACE PACKAGE PCKG_MyTypes IS
          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