- 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.
- 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.
- Myślisz że wiesz coś na pewno? Poczytaj standardy - zapewne zmienisz zdanie. Poczytaj standardy - warto.
- Jeśli coś robisz - staraj się to robić dobrze. Nie najlepiej jak jest to możliwe - ale najlepiej jak możesz w danej sytuacji.
- 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ć.
- Nie traktuj tych porad jako wiedzy absolutnej - ja się ciągle uczę nowych rzeczy.
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.
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)
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.
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.
Subscribe to:
Comments (Atom)