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ą Walidacja PESEL REGEXP. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą Walidacja PESEL REGEXP. Pokaż wszystkie posty

środa, 24 listopada 2010

Walidacja PESEL z wykorzystaniem wyrażeń regularnych

Prosta walidacja numeru PESEL z wykorzystaniem wyrażeń regularnych
Przyjmijmy następujące założenia dla funkcji sprawdzającej:
  • korzystamy z bazy w wersji 11g lub  nowszej
  • parametr funkcji powinien składać się z 11 cyfr dowolnie porozdzielanych dowolną ilością spacji i myślników oraz dowolnych znaków nie będących cyframi. Wielkość parametru może obejmować maksymalną wielkość dopuszczalną przez typ VARCHAR2 w języku PL/SQL
  • funkcja zwraca 1 jeśli PESEL jest poprawny, 0 jeśli jest niepoprawny. Celowo nie wybrałem zwracania wartości BOOLEAN, gdyż takowa nie jest obsługiwana w zapytaniach SQL
Typ SIMPLE_INTEGER został zastosowany ze względu na szybkie maszynowe rozwinięcie na poziomie kodu interpretowanego i natywnego i uniknięcie niepotrzebnych konwersji.W jaki sposób można poniższą funkcję jeszcze przyśpieszyć. Widzę następującą możliwość: opakowując w pakiecie, wówczas można inicjalizację tabeli wag umieścić w części inicjalizacyjnej pakietu oraz kompilację natywną...
Zamieszczony kod może być dowolnie wykorzystywany i przerabiany.

CREATE OR REPLACE FUNCTION FDB_Validate_PESEL(pc_PESEL VARCHAR2) RETURN INTEGER
IS
    type t_Weights is varray(11) OF SIMPLE_INTEGER;
    vt_Weights t_weights := t_weights(1, 3, 7, 9, 1, 3, 7,9,1,3,1);
    vn_CheckSum SIMPLE_INTEGER := 0;
    vc_PESEL VARCHAR2(11) ;
BEGIN
--           
    IF NVL(REGEXP_COUNT( pc_PESEL, '[[:digit:]]'),0)  <> 11 THEN
        RETURN 0;
    END IF;
----
    vc_PESEL := REGEXP_REPLACE( pc_PESEL, '[^[:digit:]]', '');
    FOR i IN 1..vt_Weights.COUNT
        LOOP
            vn_CheckSum := vn_CheckSum + TO_NUMBER(SUBSTR( vc_PESEL, i,1)) * vt_Weights(i);
        END LOOP;
    IF MOD(vn_CheckSum, 10) = 0 THEN
        RETURN 1;
    ELSE
        RETURN 0;
    END IF;
EXCEPTION WHEN OTHERS THEN
    RETURN 0;
END;