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, 2 kwietnia 2017

Przykłady błędnych zapytań odnoszących sie do wartości NULL

Wartość  NULL oznacza , ze dane pole w bazie danych lub zmienna w kodzie PL/SQL nie zostały zainicjowane... O ile  powszechnie  przy porównaniach stosowane są operatory IS NULL lub IS NOT NULL,  inne ciekawsze przypadki nie zawsze są  prawidłowo obsługiwane.
 Zwróćmy uwagę że wartości NULL nie są porównywalne między sobą ani tez  z innymi niepustymi wartościami...  Oracle wg mnie powinien  potraktować   użycie NULL  w warunkach po klauzuli WHERE przy operatorach porównujących jako błąd , wszelkie warunki typu a  = NULL, a < NULL.

Dla operatorów arytmetycznych jest przyjęta zasada, jeśli co najmniej jeden argument  IS NULL, to wartość też jest NULL.  Dlatego zapytanie
  SELECT  1 + NULL FROM dual  zwróci wynik NULL
a zapytanie
  SELECT NULL/0   FROM dual zwróci też NULL bez generowania wyjątku.

Zatem też poniższe zapytanie  nie zwróci wyjątku, jeżeli co najmniej jeden ze składników  sumy  w mianowniku będzie  niezainicjowany, mimo, że pozostałe będą sumować się do 0

SELECT (a+b+c+d) / e FROM  tabela
jeśli  którekolwiek  z pól  bazie miało wartość NULL, wynik będzie także NULL.

W wyrażeniach  tekstowych należy zwrócić uwagę, że pusty tekst traktowany jest jako niezainicjowana wartość, co więcej długość takiego pola wynosi NULL, a nie zero
 SELECT NVL(LENGTH(''), -1) FROM DUAL --zwraca -1
Zatem wszystkie poniższe trzy zapytania nie zwrócą żadnego rekordu, w każdym mamy porównanie względem wartości NULL
     
SELECT * FROM HR.EMPLOYEES WHERE LAST_NAME = ''
SELECT * FROM HR.EMPLOYEES WHERE LENGTH(LAST_NAME) =0
SELECT * FROM HR.EMPLOYEES WHERE LENGTH(LAST_NAME)  < 1

Poniższe zapytanie nie pokaże rekordów,  dla których pole COMMISSION_PCT ma wartość NULL
SELECT * FROM HR.EMPLOYEES WHERE COMMISSION_PCT IN (0.1, 0.2, NULL)
Prawidłowe wygląda następująco
SELECT * FROM HR.EMPLOYEES WHERE COMMISSION_PCT IN (0.1, 0.2) OR COMMISSION_PCT IS NULL

Z operatorem NOT IN sprawa wygląda ciekawiej, jeśli jedna wartość na liście jest pusta, to zapytanie nic nie zwróci
SELECT * FROM HR.EMPLOYEES WHERE COMMISSION_PCT NOT  IN (0.1, 0.2, NULL)
Prawidłowe wygląda następująco
SELECT * FROM HR.EMPLOYEES WHERE COMMISSION_PCT NOT IN (0.1, 0.2) AND COMMISSION_PCT IS NOT  NULL 

Zgodnie z powyższą zasadą to zapytanie też nie zwróci rekordów - NULL został przemycony w pustym tekście
SELECT * FROM HR.EMPLOYEES WHERE LAST_NAME NOT IN ('Lorentz', '')


wtorek, 31 stycznia 2017

Ściągawka dla Kolegi - dyrektora handlowego w pewnej firmie IT - zastosowanie złączeń kartezjańskich

Zainspirowany bardzo bogatym korposłownictwem z zakresu prezentacji handlowych rozwiązań i usług postanowiłem  napisać ściągawkę do wykorzystania przez przesympatycznego prelegenta. Przykład też pokazuje w jaki sposób zamienić elementy listy na  kolejne wiersze w strukturze zbliżonej do tabeli. Świadome pominięcie warunków złączenia ma na celu wygenerowanie wszystkich możliwych  połączeń bardzo profesjonalnych sformułowań..

SELECT TABLE_1.COLUMN_VALUE || ' ' ||
     TABLE_2.COLUMN_VALUE  || ' ' ||
     TABLE_3.COLUMN_VALUE || ' ' ||
     TABLE_4.COLUMN_VALUE || ' ' || 
     TABLE_5.COLUMN_VALUE || ' ' ||
     TABLE_6.COLUMN_VALUE || ' ' ||
     TABLE_7.COLUMN_VALUE    
FROM
 TABLE(SYS.ODCIVARCHAR2LIST('Przestrzeganie najwyższych standardów podczas ',
    'Ciągłe doskonalenie procesu',
    'Wieloletnie doświadczenie w zakresie',
    'Unikalny zbiór kompetencji naszego zespołu w zakresie')) TABLE_1,
 TABLE(SYS.ODCIVARCHAR2LIST( 'analizy', 'tworzenia', 'projektowania', 'testowania', 'wdrażania' )) TABLE_2,
 TABLE(SYS.ODCIVARCHAR2LIST( 'skalowalnych ', 'wydajnych', 'niezawodnych' , 'optymalnie wspierających biznes') ) TABLE_3,
 TABLE(SYS.ODCIVARCHAR2LIST( 'aplikacji', 'systemów', 'kompleksowych rozwiązań') ) TABLE_4,
 TABLE(SYS.ODCIVARCHAR2LIST( 'w największych bankach', 'w kluczowych organach administracji państwowej', 'w największych zakładach produkcyjnych', 'w największych sieciach handlowych') ) TABLE_5,
 TABLE(SYS.ODCIVARCHAR2LIST( 'potwierdza', 'zapewnia', 'trafnie weryfikuje') ) TABLE_6,
 TABLE(SYS.ODCIVARCHAR2LIST( 'wybór naszej firmy jako gwarancję sukcesu ',
  'korzyści z długofalowej współpracy', 'terminowe wdrożenie systemu', 'uzyskanie przewagi technologiczną dzięki naszej firmie') ) TABLE_7