Showing posts with label Oracle. Show all posts
Showing posts with label Oracle. Show all posts

Tuesday, December 30, 2008

Jak pisać dobre oprogramowanie?

Dziś troszkę o standardach i zasadach tworzenia dobrego oprogramowania. Zadziwiające jak niewielu ludzi je zna.
  1. Jeśli używasz daty - zawsze używaj formatu daty zgodnego z ISO-8601. Jeśli nie znasz normy to nie wiesz jak zapisywać daty. Norma podaje również powody dla których należy z niej korzystać. I jest międzynarodowa. Po prostu - przeczytaj, ucz się i nie popełniaj błędów które inni popełnili.
  2. Jeśli tworzysz programowanie w językach wysokiego poziomu - używaj wzorców projektowych. Nie wiesz czym one są? To jakby zasady gramatyczne. Możesz znać litery nie umiejąc pisać. Możesz nawet umieć pisać nie znając gramatyki/ortografii (i robić błędy). Możesz też używać wzorców programistycznych/projektowych.
  3. Myślisz że wiesz coś na pewno? Poczytaj standardy - zapewne zmienisz zdanie. Poczytaj standardy - warto.
  4. Jeśli coś robisz - staraj się to robić dobrze. Nie najlepiej jak jest to możliwe - ale najlepiej jak możesz w danej sytuacji.
  5. Myślisz że coś robisz dobrze... więc sprawdź czy ktoś nie robił tego tak samo przed tobą. I nie popełnił tych samych błędów, które właśnie zamierzasz popełnić.
  6. Nie traktuj tych porad jako wiedzy absolutnej - ja się ciągle uczę nowych rzeczy.

Sunday, December 21, 2008

Dynamiczne definiowanie typów w PL/SQL

Ostatnio natknąłem się na pewien paskudny problem. Chciałem zdefiniować procedurę korzystającą z DBMS_UTILITY.FORMAT_CALL_STACK. Ta funkcja stworzona przez Oracle zwraca typ VARCHAR2(2000) (przynajmniej tak mi się wydaje). Zgodnie z dokumentacją Oracle tak ma właśnie być.
A teraz zastanówmy się nad definicją typów jakiej powinno się używać w PL/SQL:
nazwa tabela.kolumna%TYPE;
Zapewnia to elastyczność jeśli typ tabela.kolumna się zmieni (np. zmienimy go z VARCHAR2(10) na CLOB). Ale... przecież nie wiemy jak się odwołać do tego typu - Oracle nie daje nam tej informacji!
Wniosek: Kod Oracle nie jest elastyczny. Każdy programista PL/SQL jest skazany na nieelastyczność ponieważ korzysta z nieelastycznej bazy danych.

Thursday, October 2, 2008

Oracle, cz. 2

Dzisiaj napiszę o czymś, co mnie nieco zakręciło i jest związane z agregacją.
Już jakiś czas temu korzystałem z funkcji MAX oraz GREATEST. Ale aż do dzisiaj nie miałem z nimi problemu.
W najprostszym przypadku można korzystać z nich zamiennie. Ale czasem różnice są znaczące.
Wyobraź sobie tabelę zawierającą pojedynczą kolumnę Col1 z liczbami od 1 do 9. Zapytanie SELECT MAX(Col1),GREATEST(Col1) FROM ... powinno zwrócić te same dane (ale nie sprawdzałem tego).
Jeśli chcesz znaleźć największą wartość w kolumnie - użyj MAX.
Jeśli chcesz dorzucić kolumnę zawierającą największą z wartości - użyj GREATEST.
Przykład:
INSERT INTO T VALUES (1,2,3),(5,6,2),(8,2,2)
SELECT Day1,Day2,Day3,GREATEST(Day1,Day2,Day3) FROM T
Otrzymasz wiersze (1,2,3,3),(5,6,2,6),(8,2,2,8)
SELECT MAX(Day1),MAX(Day2),MAX(Day3) FROM T
Otrzymasz wiersz (8,6,3)

A z czym miałem dzisiaj problem?
SELECT Col1, GREATEST(MAX(Day1), MAX(Day2), MAX(Day3)) Maximum FROM T GROUP BY Col1
Tutaj słowo wyjaśnienia: GROUP BY jest zbliżone do PARTITION BY (to drugie daje większe możliwości). Pozwala ono wykonać operację "SELECT Col1,MAX(Col2) FROM T GROUP BY Col1" - jak zapewne widzisz - chcę otrzymać wartości wkolumnie Col1. Dzięki GROUP BY otrzymam między 0 a n wierszy (gdzie n to ilość wierszy w tabeli T). Jeśli wartości w kolumnie Col1 się powtarzają - zostanie z nich wybrana największa. Inaczej mówiąc: podziel tabelę na grupy i wykonaj operację MAX/SUM/etc. na każdej grupie osobno.
Teraz wyjaśnienie mojego problemu: chciałem otrzymać kolumnę zawierającą największe z maksimów. Niestety Oracle nie poradzi sobie z tak nielogicznym zapytaniem: nie wiadomo czy do grupowania się tyczy funkcja MAX, czy też GREATEST (chciałem najpierw MAX a później GREATEST).
Rozwiązanie , które znalazłem, jest proste:
SELECT Col1, GREATEST(Max1,Max2,Max3) FROM ( SELECT Col1, MAX(Day1) Max1,MAX(Day2) Max2, MAX(Day3) Max3) FROM T GROUP BY Col1)

Tuesday, September 30, 2008

Wstęp do Oracle

Od kilku miesięcy pracuję z bazą danych Oracle, a dokładniej z danymi w niej gromadzonymi (w tym ładowanymi z plików .CSV za pomocą ORA*LOADERa) oraz procedurami składowanymi PL/SQL.
Moje początki były ciężkie. ALe uczę się szybko - zawsze się szybko uczyłem gdy mnie coś interesowało. Mam nadzieję, że poniższe wskazówki okażą się dla kogoś pomocnymi.

1. Nie bój się tworzenia nowych tabel. Oracle jest w stanie udźwignąć ich na prawdę wiele.

2. Nigdy nie twórz tabel typu "CREATE TABLE (AttributeName VARCHAR(100),AttributeValue(100)". Baza danych Oracle nie jest obiektem C++ - nie dodaje się do niego atrybutów. Jeśli myślisz na sposób C++ - to musisz się nauczyć myśleć inaczej aby sprawnie korzystać z Oracle.
Jeśli stworzysz taką tabelę to m.in. tracisz możliwość kontrolowania wartości, jakie są wpisywane do bazy (np. tylko dane numeryczne... albo ścieżki do plików... albo...).

3. Nie używaj typu VARCHAR - Oracle wyraźnie zachęca do używania typu VARCHAR2 i ostrzega, że VARCHAR zostanie za jakiś czas zmieniony.

4. Nigdy nie twórz zapytań rodzaju "SELECT 1 FROM AuthTable WHERE Username = 'zdzisiek' AND Password = 'ala ma kota'". Chyba, że chcesz stworzyć kod podatny na ataki typu SQL-iniection.
Poprawna forma to: "SELECT 1 FROM AuthTable WHERE UserName = :UserName AND PasswordHash = :PassHash" USING username,passHash.

5. Nigdy nie zapisuj w bazie danych haseł - co najwyżej ich hash. Chyba że masz do czynienia z jednym z tych nielicznych wyjątków, gdzie hasło trzeba zapisać.
Jeśli zapiszesz hasło i ktoś włamie się do bazy - pozyska hasła, które użytkownicy zapewne wykorzystali również w innych miejscach.

6. Metoda w 4. pozwala wykorzystać mechanizm cache bazy danych. Jeśl Oracle zobaczy 2 identyczne zapytania - wykorzysta jeden obiekt do ich obsłużenia - co jest szybsze niż tworzenie odrębnego obiektu.
Zapytania "SELECT 1 FROM Dual" i "SELECT 2 FROM Dual" są różne.
Zapytania "SELECT :1 FROM Dual" USING 1 oraz "SELECT :1 FROM Dual" USING 2 są "takie same".

7. Skoro już wspomniałem o tabeli Dual - jest to tabela stworzona po to, aby wyciągnąć jeden wiersz danych z bazy. Nie z tabeli - z bazy. Patrz na Dual jako na pustą skrzynkę z jednym pustym wierszem. Możesz w ten wiersz wrzucić dowolny inny wiersz - ale tylko jeden.
Przykład: SELECT SYSDATE FROM Dual"

8. Punkt 6. odnosi się do PL/SQL, PERL, Python, oraz wszelkich innych języków. ZAWSZE!

9. Oracle jest drogi. Jeśli nie masz kasy - wybierz PostGreSQL. Jeśli jednak cię na to stać - uderz w Oracle. To na prawdę fajna bazka - choć jak wszystko - tak i ona posiada pewne ograniczenia.

10. Oracle wprowadził typy BLOB i CLOB. Mogą one przechowywać duże ilości danych. Zanim jednak ich użyjesz przemyśl to 10x - korzystanie z nich jestdużo wolniejsze niż np. VARCHAR2.

To na tyle na dzisiaj.