Pokazywanie postów oznaczonych etykietą metadane. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą metadane. Pokaż wszystkie posty

środa, 7 lipca 2010

Wyciąganie informacji o schemacie bazy danych

Znalazłem w końcu trochę czasu, aby coś napisać na bloga. Ostatnio przeprowadzka trochę czasu z życia mi zabrała (koniec mieszkania w akademiku), przez co nie było jak pisać. Przygotowuję obecnie jakieś artykuły na bloga, ale będzie to kilkuczęściowa seria wpisów i chcę poczekać do jej ukończenia. Tymczasem opowiem o wydobywaniu metadanych (czy też metainformacji) z baz danych.

Czym są metadane? Są to "dane o danych". Innymi słowy są to informacje o sposobie przechowywania danych, ich strukturze itp. W przypadku baz danych chodzi tu o schemat bazy danych.

Tylko po co nam schemat bazy danych? Zazwyczaj jak tworzymy jakąś aplikację to bardzo dobrze znamy schemat bazy danych i na nim operujemy. Czasami jednak chcemy napisać narzędzie wspomagające prace z bazą danych, które będzie uniwersalne i działało niezależnie od schematu bazy. Może to być np. narzędzie do automatycznego generowania kodu klas persystętnych, na podstawie schematu bazy danych. O takim rozwiązaniu słyszałem na konferencji 4Developers podczas prezentacji Marka Berkana pt. Automatyczne generowanie kodu. Podobne rozwiązanie jak przedstawiane na prelekcji wykorzystuję obecnie w swoim pewnym projekcie.

Jako przykład bazy danych wykorzystam Oracle 10g XE. Chcąc się dowiedzieć, jakie tabele mamy zdefiniowane w bazie danych możemy wykorzystać następujące zapytanie:



Dostaniemy wówczas wszystkie tabele zdefiniowane przez zalogowanego użytkownika. Tabela USER_OBJECTS zawiera również wiele innych niekoniecznie dla nas ciekawych informacji o naszych tabelach.

Po pewnym czasie używania tego zapytania zauważyłem, że zaczęły pojawiać się w wynikach zapytania tabele o nazwie typu: BIN$m4Gt7PLlTv6r1dCsd2+ddA==$0. Próba uzyskania dostępu do takiej tabeli kończy się błędem ORA-00903: invalid table name. Skąd się więc bierze ta nazwa? A no z mechanizmu odzyskiwania usuniętych tabel. W Oracle mamy możliwość przywrócenia (przypadkiem) usuniętych tabel. Informacje o tych tabelach są również przechowywane w USER_OBJECTS, tylko że pod taką dziwaczną nazwą.

Chcąc się pozbyć usuniętych tabel z naszego zbioru wyników, możemy wykonać drugie zapytanie:



które zwróci nam nazwy tabel usuniętych. Wyniki wystarczy potem odfiltrować. Możemy to również scalić i wykonać w jednym zapytaniu:



Powyższe zapytania operowały na tabelach danego user'a. Chcąc dostać wszystkie tabele (wraz ze specjalnymi / systemowymi - nie wiem jak się je powinno nazwać) należy USER_OBJECTS zamienić na ALL_OBJECTS (lub DBA_OBJECTS) w powyższych zapytaniach. Tabela USER_OBJECTS jest widokiem tabeli ALL_OBJECTS - różni się tylko jedną kolumną.

Przygotowując ten artykuł znalazłem jeszcze inny, prostszy sposób na wydobycie nazw tabel w naszej bazie. Rozwiązanie poniżej:



To zapytanie zwraca tabele danego user'a. W wyniku zapytania nie ma już usuniętych tabel. Tutaj również mamy możliwość wyboru i zamiast USER_TABLES możemy użyć DBA_TABLES lub ALL_TABLES zależnie od naszych potrzeb.

No dobra, wiemy już jakie mamy tabele w bazie, czas na kolumny. O dostępnych kolumnach ich nazwach typach itp. możemy się dowiedzieć za pomocą:



Innym sposobem jest zapytanie:



jednak w tym przypadku nie dostajemy informacji o typie kolumny. Jeśli zależy nam na typie kolumny możemy użyć zapytania:



jednak znów dostaniemy (w gratisie) kolumny z tabel usuniętych. Wynik należało by więc odfiltrować.

Jeśli korzystamy z JDBC w naszej aplikacji mamy jeszcze inną możliwość. Wykonujemy dowolne zapytanie na interesującej nas tabeli (np. SELECT * FROM "NAZWA_TABELI") i otrzymujemy obiekt implementujący interfejs ResultSet. Udostępnia on metodę getMetaData(), która zwraca ResultSetMetaData. Wówczas nazwę kolumny możemy pobrać za pomocą:



Typ kolumny możemy pobrać za pomocą:



Metoda ta zwraca pełną nazwę klasy Javowej na którą może być zrzutowana dana kolumna. Tutaj co ciekawe, to to, że typy liczbowe, niezależnie czy zdefiniowane jako NUMBER(p, s), NUMBER(p), czy NUMBER w bazie Oracle, zawsze są rzutowane do typu java.math.BigDecimal. Jeśli chcemy rzutować do typów prymitywnych, musimy skorzystać z jednego powyższych zapytań i wydobyć dokładną precyzję liczby oraz odpowiednio zrzutować.

To tyle jeśli chodzi o wydobywanie metadanych z bazy Oracle. Jeśli znacie jeszcze inne, prostsze sposoby na wydobywanie informacji o tabelach i kolumnach z bazy danych to zachęcam do komentowania wpisu.