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

niedziela, 29 maja 2011

Trzy pułapki w PL/ SQL

1. Modyfikator result_cache dla funkcji niedeterministycznych przekształca je na deterministyczne
Funkcja deterministyczna jest to funkcja zwracająca dla takiego samego zbioru parametrów identyczny  wynik. Deterministyczności wymaga sie  od wyrażeń w indeksach  funkcyjnych i polach wyliczeniowych dla tabel.. Deterministyczność wyklucza użycie funkcji SYSDATE, funkcji losowych...

Rozważmy poniższy przykład:
 Skompilujmy poniższą funkcję:
 CREATE OR REPLACE FUNCTION Fdb_Test RETURN DATE
RESULT_CACHE
    IS
BEGIN
    RETURN SYSDATE;
END;




Następnie wywołajmy pięć  razy w odstępach kilkusekundowych:
SELECT Fdb_Test  FROM DUAL
O ile bufor dla result cache jest nieprzepełniony, to funkcja zwróci nam za każdym wywołaniem taką samą wartość. Poniższe sprawdzenie pokaże czterokrotne użycie bufora(za pierwszym razem rzeczywiście wywoła się SYSDATE):
SELECT SCAN_COUNT
   FROM  V$RESULT_CACHE_OBJECTS WHERE  NAMESPACE ='PLSQL' AND NAME LIKE '%FDB_TEST%'

2. Struktury zakotwiczone %ROWTYPE zapewniają uproszczenie wstawiania..
I z reguły jest to prawda
Stwórzmy tabelę:
CREATE TABLE TBL_TEST
      (ID NUMBER(4),
        OPIS VARCHAR2(50 CHAR)
       )
Można wówczas dokonać wstawiania w bardzo elegancki sposób bez podawania listy kolumn...
DECLARE
  vr_Test TBL_TEST%ROWTYPE;
BEGIN
  vr_Test.ID  := 1;
  vr_Test.Opis := 'Opis';
  INSERT INTO TBL_TEST VALUES vr_Test;
  COMMIT;
END;Zakotwiczenie przy wstawianiu będzie  dalej działało  przy dodaniu nowych pól, chyba, że to będą pola obliczeniowe..

Po dodaniu formuły
ALTER TABLE TBL_TEST  ADD FORMULA VARCHAR2(100 CHARGENERATED ALWAYS  AS ( TO_CHAR(ID) || ' ' || OPIS)
przy próbie wykonania powyższego bloku pojawi się komunikat
ORA-54013: INSERT operation disallowed on virtual columns
Szkoda, że obie możliwości nie mogą działać jednocześnie (:

3, Triggery DML blokują jedynie operacje DML
Jeśli chcemy zablokować  w sposób dynamiczny np. usuwanie z tabel, to nie można użytkownikom końcowym nadawać żadnych uprawnień DDL do tabeli..
Poniższy trigger
CREATE OR REPLACE TRIGGER .TRG_TBL_TEST__NO_DELETE
BEFORE DELETE
ON
TBL_TEST
--w celu lepszej wydajności powinien to być triger  on statement, a nie FOR EACH ROW
BEGIN
  IF EXTRACT
( HOUR FROM LOCALTIMESTAMP ) BETWEEN 8 AND 18 THEN
    RAISE_APPLICATION_ERROR (- 20100, 'Usuwanie w godzinach pracy z tabeli jest niedozwolone' );
  END IF;
END TRG_TBL_TEST__NO_DELETE;
nie zabezpieczy przed instrukcją DDL 
 TRUNCATE TABLE TBL_TEST
jeśli użytkownik końcowy posiadać będzie bezpośrednio nadane uprawnienie ALTER TABLE