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

ś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;

3 komentarze:

  1. Nie sprawdzałem (pracuję na 10g aktualnie), ale wydaje mi się, że w 11g można zapisać (LENGTH(REGEXP_REPLACE() w taki sposób: REGEXP_COUNT() i usunąć negację z wyrażenia regularnego - powinno być równoważne i nieco krótsze.

    OdpowiedzUsuń
  2. Słuszna i trafna uwaga - zastosowałem. Cały kod na moim blogu powstał dla Oracle 11g, nie mam możliwości sprawdzenia na wersji 10

    OdpowiedzUsuń
  3. Sprawdzalem i na wersji Oracle 10g nie dziala. W 10 nie ma funkcji REGEXP_COUNT()

    Dla wersji Oracle 10 poprawilem nieco Twoj kod - http://pastebin.com/n8bVMDMe

    OdpowiedzUsuń