Zawartość: FAQ grupy dyskusyjnej pl.comp.bazy-danych (Frequently
Asked Questions, czyli Często Zadawane Pytania)
Wersja: 0.94
Data modyfikacji: 01-12-2011
URL: http://www.dbf.pl/faq/
Koordynator FAQ: Sławomir Szyszło szysla(at)zadnegospamu.icpnet.pl.invalid
FAQ jest wysyłany co na dwa tygodnie na grupy pl.comp.bazy-danych oraz pl.answers. FAQ swoją lokalizację zawdzięcza Arkowi Sucheckiemu z http://www.konar.pl
Wersja tekstowa znajduje się tutaj (kodowanie Win-1250) i tutaj (kodowanie ISO-8859-2).
0. Wstęp |
3. Clipper |
6. InterBase |
9. Oracle |
12. (Visual) FoxPro |
4. DB2 |
10. PostgreSQL |
13. Inne źródła |
||
2. Język SQL |
5. Informix |
8. MySQL |
11. Sybase |
Dokument ten zawiera często zadawane pytania (i odpowiedzi) dotyczące tematyki baz danych, a także informacje ułatwiające zadawanie i nie zadawanie pytań na grupie pl.comp.bazy-danych.
Najnowsza wersja FAQ wysyłana jest co dwa tygodnie na grupy news:pl.comp.bazy-danych oraz news:pl.answers, dostępna jest również (w formatach txt i
html) pod adresem http://www.dbf.pl/faq/.
Propozycje zmian proszę przysyłać na grupę pl.comp.bazy-danych z kopią BCC: na adres szysla@zadnegospamu.icpnet.pl.invalid.
Grupa pl.comp.bazy-danych służy do dyskusji na temat systemów baz danych. Można tu poruszać zarówno problemy teoretyczne, jak i praktyczne. Grupa nie służy do dyskusji dotyczących wyłącznie systemu MS Access - do tego służy grupa pl.comp.bazy-danych.msaccess. Sprawy związane z oprogramowaniem baz danych w języku Delphi powinno omawiać się na grupie pl.comp.lang.delphi.bazy-danych. Istnieje także grupa pl.comp.www.server-side, na którą powinno się kierować pytania związane ze skryptami wykonywanymi po stronie serwera, także tymi operującymi na bazach danych (CGI, PHP, ASP itp.).
Poniżej znajduje się oficjalny opis grupy ze strony http://www.usenet.pl/opisy/pl.comp.bazy-danych
Nazwa grupy: pl.comp.bazy-danych
Krotki opis: Wszystko o bazach danych.
Moderowana: NIE
Opis: Grupa pl.comp.bazy-danych służy do dyskusji na temat systemów baz danych. Można tu poruszać zarówno problemy teoretyczne, jak i praktyczne.
Tematyka grupy obejmuje m.in.: języki (obsługi|programowania) baz danych (np. SQL), ich implementacje oraz rozszerzenia, konfigurację serwerów baz danych, teorię baz danych (np. relacyjnych czy obiektowych), literaturę nt. systemów baz danych oraz wszelkie problemy i pytania związane z bazami danych. Niedopuszczalne jest także pisanie wyłącznie o bazach danych, dla których w hierarchii pl.* istnieją wydzielone, nie wymienione tu grupy.
Przed zadaniem pytania zaleca się lekturę archiwum grupy i zapoznanie się z FAQ, gdzie być może jest już rozwiązanie danego problemu.
Dopuszczalne jest cytowanie w tekście fragmentów listingów programów, o ile są skrócone do minimum i niezbędne dla zilustrowania problemu. Muszą być spełnione wszystkie występujące tu warunki - cytowanie w tekście, a nie załącznik, wyłącznie fragment listingu, wyłącznie skrócony do minimum i wyłącznie jako niezbędny argument w dyskusji. W innych przypadkach należy podać link do omawianego pliku.
Tematy zabronione: Dyskusje dotyczące *wyłącznie* systemu MS Access (właściwa grupa: pl.comp.bazy-danych.msaccess), sprawy związane z oprogramowaniem baz danych w języku Delphi (właściwa grupa: pl.comp.lang.delphi.bazy-danych), pytania związane ze skryptami wykonywanymi po stronie serwera, także tymi operującymi na bazach danych, czyli CGI, PHP, ASP itd. (właściwa grupa: pl.comp.www.server-side i pokrewne w hierarchii pl.comp.lang.*).
Ponadto zabronione jest wysyłanie postów zawierających jakiekolwiek binaria (programy, pliki formularzy czy raportów, zdjęcia itp.) lub napisanych w HTML, jakikolwiek spam oraz dyskusje nie związane z tematem grupy. Nie jest to także miejsce na ogłoszenia reklamowe, nawet jeśli są związane z tematem grupy. Zabronione są crossposty z innymi grupami w hierarchii pl.*, chyba że artykuł ma ustawione pole Followup-to:.
Uprasza się o wysyłanie postów z oznaczeniem w temacie wiadomości środowiska, którego dotyczy dany problem. Skróty są podane poniżej.
| Tematyka | Oznaczenie w temacie (subject) postu |
| SQL | [SQL] |
| Clipper | [Clipper] |
| IBM DB2 | [DB2] |
| Informix | [Informix] |
| InterBase | [IB] |
| Microsoft SQL Server | [MSSQL] |
| MySQL | [MySQL] |
| Oracle | [Oracle] |
| PostgreSQL | [PGSQL] |
| Sybase | [Sybase] |
| VisualFoxPro (VFP) | [VFP] |
Archiwum tej grupy dostępne jest
Pytania:
1.1 Co to jest baza danych?
1.2 Co to jest system zarządzania bazą danych SZBD (ang. DBMS - Database
Management System)?
1.3 Co to jest system bazy danych?
1.4 Spójność bazy danych
1.5 Transakcja
1.6 Języki baz danych
1.7 Encja
1.8 Relacyjny model danych
1.9 Jak zaprojektować tabele do bazy, gdzie relacje 1:wielu mogą się zagłębiać w nieskończoność?
1.10 Szukam modelu danych dla...
1.11 Gdzie znajdę porównania baz danych?
Literatura
Linki
Odpowiedzi:
W ogólności bazą danych nazywamy pewien uporządkowany zbiór danych. Precyzyjniej będzie jednak powiedzieć, że baza danych jest informatycznym odwzorowaniem danego fragmentu rzeczywistości, odzwierciedlającym stan tego fragmentu w postaci danych komputerowych.
1.2 Co to jest system zarządzania bazą danych SZBD (ang. DBMS - Database Management System)?
Jest to oprogramowanie umożliwiające tworzenie, eksploatację bazy danych oraz obsługujące użytkowników bazy.
1.3 Co to jest system bazy danych?
Jest to, w uproszczeniu, baza danych plus system zarządzania bazą danych.
Ponieważ baza danych jest logicznie spójnym modelem fragmentu obserwowanej przez nas rzeczywistości, ważne jest, aby baza danych nie przyjęła stanu, którego nie da się osiągnąć w modelowanej rzeczywistości. Jeśli baza jednak osiągnie taki stan, to mówimy, że jest ona w stanie niespójnym.
Transakcja jest pewną sekwencją instrukcji, po wykonaniu której baza danych z jednego stanu spójnego przechodzi w inny stan spójny (zgodny z modelowaną rzeczywistością). Innymi słowy, jeśli transakcja zostanie wykonana w spójnej bazie danych, to po jej zakończeniu baza nadal powinna być spójna.
Transakcja jest operacją atomową, co oznacza, że SZBD powinien wykonać wszystkie instrukcje wchodzące w jej skład lub żadną. W praktyce SZBD wykonuje instrukcje transakcji po kolei, a w przypadku niepowodzenia którejś z nich wycofuje poprzednio wykonane instrukcje (jest to tzw. wycofanie transakcji, ang. rollback).
Do operowania na bazach danych służą następujące języki:
W praktyce te cztery języki są ze sobą zintegrowane. Takim zintegrowanym językiem jest m.in. SQL (ang. Structured Query Language).
Do listy języków można tu jeszcze dodać rozszerzenia proceduralne stosowane przez różne firmy produkujące SZBD: pl/pgsql w PostgreSQL, PL/SQL w Oracle i inne.
Encja (ang. entity) to pewna rzecz (obiekt materialny lub niematerialny, pojęcie, fakt, zdarzenie itp.), o której chcemy przechowywać informacje. Encja posiada pewne charakterystyczne dla siebie cechy. Przykładem encji będącej obiektem materialnym może być np. samochód (wraz z cechami, np.: model, numer fabryczny, kolor, zużycie paliwa), osoba (imię, nazwisko, adres, numer PESEL), a niematerialnym np. konto bankowe (numer, posiadacz, dopuszczalny debet, saldo), zdarzeniem - wysłanie towaru (data wysłania, nazwa towaru, symbol, nazwa i adres odbiorcy), faktem - znajomość języka (nazwa języka, czas nauki, stopień znajomości).
Relacyjny model danych posiada trzy podstawowe składowe:
1.9 Jak zaprojektować tabele do bazy, gdzie relacje 1:wielu mogą się zagłębiać w nieskończoność?
Opracował: hubert depesz lubaczewski
*** Dane testowe *** We wszystkich przykładach będę się odwoływał do poniższego drzewa: (jeśli poniższy graf masz przekoszony użyj czcionki nieproporcjonalnej, np.courier).
sql
/ \
postgresql oracle-----__
| / | \
linux solaris linux windows
/ \
glibc1 glibc2
*** Metoda 1 ***
Oddzielne table na każdy poziom zagnieżdżenia danych. W tym przypadku byłoby to:
tree_level_1 (id, name) :
(1,sql);
tree_level_2 (id, parent_id, name) :
(1, 1, postgresql),
(2, 1, oracle);
tree_level_3 (id, parent_id, name) :
(1, 1, linux),
(2, 2, solaris);
(3, 2, linux);
(4, 2, windows);
tree_level_4 (id, parent_id, name) :
(1, 3, glibc1),
(2, 3, glibc2);
Metoda ta wybierana jest najczęściej przez początkujących programistów.
Bardziej doświadczeni bazo-danowcy, odrzucają ją ze względu na
koniecznośc modyfikowania *struktury bazy danych* przy zmianie danych!!!
Praktycznie rzecz biorąc nie powinna być nigdy stosowana.
Cechy:
+ trywialne w implementacji
+ dosyć szybkie tworzenie pełnej nazwy (z zastrzeżeniem o znajdywaniu danych konkretnego (początkowego) ID)
- skomplikowane wyszukiwanie danych na podstawie konkretnego "ID"
- ograniczona ilość poziomów zagnieżdżeń
- bardzo wolne znajdowanie np. wszystkich książek w kategorii "informatyka" i podkategoriach informatyki (dowolnie głęboko)
- wolne wyszukiwanie podkategorii niebezpośrednich.
*** Metoda 2 ***
Tabela typu:
create table kategorie (
id serial,
parent_id int8,
name text not null default '',
primary key (id)
);
create unique index ui_kategorie_pin on kategorie (parent_id, name);
alter table kategorie add foreign key (parent_id) references kategorie (id);
Cechy:
+ trywialne w implementacji
+ nieograniczona ilość poziomów zagnieżdżeń
+ błyskawiczne wyszukiwanie podkategoriii danej kategorii
- wolne tworzenie pełnej nazwy (chyba, że przechowujesz ją w polu name, ale to marnotrawstwo miejsca)
- bardzo wolne znajdowanie np. wszystkich książek w kategorii "informatyka" i podkategoriach informatyki (dowolnie głęboko)
- wolne wyszukiwanie podkategorii niebezpośrednich.
*** Metoda 3 ***
Układ typu nested sets (vide książka "SQL - zaawansowane programowanie", autor:
Joe Celko).
Tabela plus minus jak wyżej, ale zamiast parent_id jest left_mark i right_mark.
Left_mark i right_mark są wyliczane.
Przykład (w nawiasach przy nazwie odpowiednio: left_mark, right_mark).
(1, 18) sql (2, 5) sql/postgresql (6, 17) sql/oracle (3, 4) sql/postgresql/linux (7, 8) sql/oracle/solaris (9, 14) sql/oracle/linux (15, 16) sql/oracle/windows (10, 11) sql/oracle/linux/glibc1 (12, 13) sql/oracle/linux/glibc2
Wartości left/right mark są nadawane w następujący sposób: zaczynając od
konkretnego miejsca w drzewie, nadajemy mu kolejny numer (np. 1), i znajdujemy
pierwsze "dziecko". "Pierwsze" definiujemy w dowolny sposób - tu akurat użyłem
odwzorowania graficznego.
Jeśli dany element nie posiada "dzieci", zwiekszam licznik o jeden, ustawiam
right-mark oraz wraz z numerowaniem jeden poziom w górę.
Przykład:
Zaczynam od "sql". Ustawiam mu left-mark na 1, znajduję pierwsze "dziecko" -
czyli postgresql, ustawiam mu left-mark na 2, znajduję kolejne pierwsze "dziecko"
czyli "linux", ustawiam mu left-mark na 3.
Ponieważ "linux" nie ma "dzieci", ustawiam mu right-mark na 4, po czym wracam
poziom wyżej.
"postgresql" nie ma innych dzieci, więc dostaje right-mark 5 i idę do kolejnego
"dziecka" sql -> czyli "oracle".
Proces powtarzam, aż wrócę do "sql" i nadam mu right-marka.
Cechy:
+ niesamowicie szybkie wyszukiwanie w dół drzewa od określonego elementu (zakładając wyszukiwanie bez limitu głębokości)
+ nieograniczona ilość poziomów zagnieżdżeń
- nietrywialne w implementacji
- dużo więcej pracy przy wstawianiu i usuwaniu elementów
- utrudnione wyszukiwanie bezpośrednich podkategorii danej kategorii.
*** Metoda 4 ***
Metoda 1 + metoda 2, czyli wykorzystanie i parent_id i left/right mark-ów. Opisu nie będę robił, bo jest oczywisty.
Cechy:
+ nieograniczona ilość poziomów zagnieżdżeń
+ błyskawiczne wyszukiwanie podkategoriii danej kategorii
+ niesamowicie szybkie wyszukiwanie w dół drzewa od określonego elementu (zakładając wyszukiwanie bez limitu głębokości)
- sporo pracy przy wstawianiu i usuwaniu elementów
- nietrywialne w implementacji
- nadmiarowość informacji (choć w bazach danych to raczej standard)
*** Metoda 5 ***
Wymyśliliśmy ją z współpracownikami w trakcie pracy nad jednym z magicznych projektów.
2 tabele:
create table kategorie (
id serial,
name text,
primary key (id)
);
-- ważne: name nie jest unique !!!!
create table powiazania (
first_id int8,
second_id int8,
depth int8,
primary key (first_id, second_id)
);
alter table powiazania add foreign key (first_id) references kategorie (id);
alter table powiazania add foreign key (second_id) references kategorie (id);
Pole depth oznacza, o ile poziomów "głębiej" jest kategoria second od first. Np. dla sytuacji z metody 2:
kategorie:
id | name
----+------------
1 | sql
2 | postgresql
3 | oracle
4 | linux
5 | solaris
6 | linux
7 | windows
8 | glibc1
9 | glibc2
powiązania:
first_id | second_id | depth
----------+-----------+-------
1 | 2 | 1
1 | 3 | 1
1 | 4 | 2
1 | 5 | 2
1 | 6 | 2
1 | 7 | 2
1 | 8 | 3
1 | 9 | 3
2 | 4 | 1
3 | 5 | 1
3 | 6 | 1
3 | 7 | 1
3 | 8 | 2
3 | 9 | 2
6 | 8 | 1
6 | 9 | 1
Ze względów wydajnościowych oraz ułatwiajacych programowanie polecam dopisywanie dodatkowo powiazań z głębokością 0, czyli w naszym przypadku 9 rekordów:
first_id | second_id | depth
----------+-----------+-------
1 | 1 | 0
2 | 2 | 0
3 | 3 | 0
4 | 4 | 0
5 | 5 | 0
6 | 6 | 0
7 | 7 | 0
8 | 8 | 0
9 | 9 | 0
Może nie wydaje się to bardzo potrzebne, ale wiele razy okazało się, że taka dodatkowa ilość danych bardzo ułatwia późniejsze oprogramowywanie.
Zwrócić należy uwagę, że ilość dodatkowych danych jakie trzeba przechowywać
jest zależna od maksymalnej głębokości zagnieżdżenia drzewa.
W skrajnym przypadku ilość danych które trzeba zapisać jest zbliżona do
(n^2)/2 * wielkość rekordu w tablicy powiązania.
W praktyce jednak zazwyczaj nie przekracza się wartości 2n do 3n, co oznacza,
że do zapisania drzewa ze 100 elementami potrzebujemy (zazwyczaj) około
200-300 rekordów w tablicy powiązania. A dzięki temu, że dane tam są proste
(3 pola typu INT), wielkość pojedyńczego rekordu wynosi 12 (lub 24 dla INT8)
bajtów - co nie jest wielką wartością.
Cechy:
+ relatywnie proste w implementacji
+ nieograniczona ilość poziomów zagnieżdżeń
+ błyskawiczne wyszukiwanie podkategoriii danej kategorii
+ niesamowicie szybkie wyszukiwanie w dół drzewa od określonego elementu
(niezależnie od tego, czy z limitem, czy bez limitu głębokości)
+ proste wstawianie i usuwanie rekordów
+ szybkie (dużo szybsze niż w jakiejkolwiek innej implementacji) tworzenie pełnych nazw
+ szybkie wyszukiwanie kategorii niebezpośrednich (np. znajdź wszystkie podkategorie
podkategorii "informatyki". czyli np. informatyka/podręczniki/sql tak, ale informatyka/sql już nie)
- nadmiarowość informacji (choć w bazach danych to raczej standard).
1. zakładamy, że X to id elementu który przenosimy
2. zakładamy, że Y to id elementu pod który przenosimy X
3. zakładamy, że nie powstaje pętla: not exists (select * from tree
where parent_id = X and child_id = Y);
Dwa zapytania:
DELETE FROM tree WHERE id in (
SELECT r2.id FROM tree r1 join tree r2 on r1.child_id = r2.child_id
WHERE r1.parent_id = X AND r2.depth > r1.depth
);
INSERT INTO tree (parent_id, child_id, depth)
SELECT r1.parent_id, r2.child_id, r1.depth + r2.depth + 1
FROM
tree r1,
tree r2
WHERE
r1.child_id = Y AND
r2.parent_id = X;
Więcej o drzewach w SQL:
1.10 Szukam modelu danych dla...
Zajrzyj na http://www.databaseanswers.com/data_models/
1.11 Gdzie znajdę porównania baz danych?
webresource.net : Database Center
Bazy danych - wprowadzenie teoretyczne
Tu jest komplet wykladów o bazach, takie tam podstawy
Pytania:
2.1 Jak to jest z limitem?
2.2 Jak przenumerować pole typu "autoincrement"?
2.3 Jak zapisać dane polecenie SQL w bazie ...?
2.4 Jak znaleźć luki w numeracji?
Literatura
Linki
Odpowiedzi:
2.1 Jak to jest z limitem? Mam bazę danych z milionem elementów, a chcę wyświetlić pierwszych 10, które spełniają określony warunek. Chyba baza nie będzie niepotrzebnie szukać pozostałych, nie? Na początku wydawało mi się to logiczne, ale zaczynam się nad tym zastanawiać...
Relacyjna baza danych zakłada nieuporządkowaną kolejność rekordów, czyli dwa identyczne zapytania z identycznym limitem, ale bez sortowania (order by) mogą dać dwa różne wyniki. Zdarza się to relatywnie rzadko, ale tak już jest i np. używanie takiego zapytania bez sortowania do wyświetlania "po kawałku" wyników wyszukiwania jest pomyłką.
2.1.1 To znaczy, że gdy mówimy o pierwszych 10 osobach stojących w kolejce to znaczy, że muszą one być "posortowane"? Chyba pierwsze 10 znaczy pierwsze 10 rekordów spełniających określony warunek i nie potrzeba tutaj sortowania. Czy nie wystarczy select blabla from tabelka where warunek limit 0,10; ?
Taka komenda jest równoważna "wybierz losowo dziesięć osób spośród stojących w kolejce". Natomiast powiedzenie "wybierz pierwszych 10 osób stojących w kolejce" zakłada konkretną kolejność - właśnie kolejność osób w kolejce. Dlatego też wybranie 10 rekordów bez posortowania zwykle zwraca losowe 10 rekordów, które za każdym razem mogą być inne (tzn. teoretycznie - w praktyce zmiana nie będzie częsta).
2.2 Jak przenumerować pole typu "autoincrement"? Mam w tabeli pole typu autoincrement. Jeżeli usunę jakiś rekord, to ta liczba pózniej nie będzie wykorzystana - zrobi się "dziura". Czy można jakoś automagicznie przenumerowac pozostałe elementy albo przynajmniej zrobić tak, by następny element miał id równe temu brakującemu, a nie większe o 1 od największego?
Sposób być może jest, ale mija się to z ideą takiego pola. Pole typu autoincrement z założenia ma mieć wartości unikalne i ma służyć do jednoznacznego identyfikowania rekordów. Pole typu autoincrement może być wykorzystywane jako klucz obcy w innej tabeli, a po przenumerowaniu rekordów powiązania pomiędzy rekordami z obu tabel znikną lub staną się nieprawidłowe. Przykład:
Tabela pracownicy (id_wydzialu to klucz obcy z tabeli wydzialy (id_w)): id_p nazwisko id_wydzialu 1 Kowalski 2 2 Nowak 3 3 Iksiński 3 4 Masztalski 1 Tabela wydzialy id_w nazwa 1 Produkcja 2 Księgowość 3 Magazyn 4 Marketing
Jeśli usuniemy wydział nr 3 i przenumerujemy rekordy tak, że Marketing będzie miał numer 3, to okaże się, że Nowak i Iksiński nie pracują w Magazynie, tylko w Marketingu, co jest oczywiście błędne.
2.3 Jak zapisać dane polecenie SQL w bazie ...?
Tabela odpowiedników najczęściej używanych poleceń SQL w popularnych bazach danych znajduje się tu: http://sqlzoo.net
2.4 Jak znaleźć luki w numeracji?
Mając tabelę TAB1 z polem numerycznym NUMER i chcąc znaleźć luki w numeracji należy:
- znaleźć wartość minimalną X
SELECT MIN(numer) FROM TAB1;- znaleźć wartość maksymalną Y
SELECT MAX(numer) FROM TAB1;- utworzyć tabelę pomocniczą TMP_NUMERACJA i wypełnić ją numerami od X do Y
SELECT numer FROM TMP_NUMERACJA MINUS SELECT numer FROM TAB1 ORDER BY numer;
Interactive/On-line SQL Tutorial with SQL Interpreter
Introduction to Structured Query Language
Aktualna wersja jest dostępna pod adresem: http://www.harbour.pl.eu.org/clipper/clipper_mini_faq.html
Pytania:
3.1 Skąd wziąć?
3.2 Jaką polecacie wersję i dlaczego?
3.3 Gdzie jest FAQ?
3.4 Co to jest "Runtime error 6003"? Dlaczego nie działa _wait_4.obj?
3.5 Co to jest "Internal error 8002"?
3.6 Jak ustawić FILES= i SET CLIPPER= w Windows ME/NT/2000?
3.7 Mój program nic nie robi, a pochłania 100% zasobów systemu. Co z tym zrobić?
3.8 Jak drukować na drukarkę nie obsługiwaną przez DOS (GDI-windrukarkę lub USB)?
3.9 Czy z mojego programu mogę wysyłać/odbierać pocztę elektroniczną?
3.10 Muszę odzyskać kod źródłowy programu. Czy jest jakiś dekompilator?
3.11 Chcę przenieść aplikację, czyli co dalej po Clipperze?
3.12 Gdzie mogę znaleźć jakąś bibliotekę do Clippera?
3.13 Windows Me nie pozwala na zmiany w CONFIG.SYS i AUTOEXEC.BAT. Jak przywrócić możliwość zmian?
3.14 Jak wyświetlić/wydrukować znak euro?
3.15 Mam jakieś pliki baz danych. Chyba to dbfy, chyba są uszkodzone...
Literatura
Linki
Odpowiedzi:
Firma Computer Associates zaprzestała produkcji Clippera w drugiej połowie 2000 roku. 22 kwietnia 2002 r. firma GrafXSoft z Florydy na mocy porozumienia z Computer Associates faktycznie przejęła Clippera. Szczegóły na stronie http://www.grafxsoft.com/pr.htm. Przez cały czas firma GrafXSoft http://www.grafxsoft.com/ prowadzi sprzedaż programu i inych narzędzi do Clippera. Obecnie żaden z polskich dystrybutorów nie ma w magazynie ani Clippera, ani pakietu narzędziowego CA-Tools. Można ewentualnie szukać w serwisie Allegro http://www.allegro.pl/search.php?str=clipper&opisy=y, czy ktoś nie wystawił pakietu na sprzedaż.
3.2 Jaką polecacie wersję i dlaczego?
Do wyboru są dwie wersje Clippera:
- 5.2e - posiada najwięcej rozszerzeń;
- 5.3b - ostatnia dostępna w sprzedaży.
W obu przypadkach najlepiej używać indeksów CDX.
Poza tym są różne konsolidatory:
* dostępne z Clipperem
- 5.2e - RTLink (tryb rzeczywisty) i Exospace (tryb chroniony)
- 5.3b - Blinker v.1.0 (tryb rzeczywisty) i Exospace (tryb chroniony)
* komercyjne (właściwie tylko jeden)
- Blinker v.3.30, v.5.10, teraz już v.6.0
Oczywiście, przydadzą się też narzędzia CA-Tools (patrz p.3.4.)
W wersji polskiej - dopiero powstaje.
W wersji angielskiej - mini http://www.davep.org/clipper/VFAQ/
i pełne http://www.davep.org/clipper/FAQ/
lub http://www.the-oasis.net/clipper.html
3.4 Co to jest "Runtime error 6003"? Dlaczego nie działa _wait_4.obj?
Polecam lekturę http://www.harbour.pl.eu.org/clipper/r6003.html lub http://www.davep.org/clipper/FAQ/clipper-5.html#ss5.7
Problem rozwiązuje pobranie nowej wersji CA-Tools: ftp://ftp.ca.com/pub/clipper/tools3.zip
Jeśli brak źródeł, można ręcznie załatać program używając poprawki http://www.harbour.pl.eu.org/clipper/div0pl.zip lub edytora heksadecymalnego. Trzeba znaleźć w pliku exe sekwencję B8 52 17 8B CA 33 D2 F7 F1 i zamienić końcowe F7 F1 na 90 90.
3.5 Co to jest "Internal error 8002"?
Polecam lekturę: http://www.davep.org/clipper/FAQ/clipper-5.html#ss5.8
Problem rozwiązuje ściągnięcie aktualizacji do Clippera 5.3 i używanie programu OPTEDIT.EXE.
3.6 Jak ustawić FILES= i SET CLIPPER= w Windows ME/NT/2000?
W Windows NT/2000/XP trzeba znaleźć i zmodyfikować odpowiedniki plików
CONFIG.SYS - %windir%\SYSTEM32\CONFIG.NT i AUTOEXEC.BAT - %windir%\SYSTEM32\AUTOEXEC.NTgdzie
%windir% - to najczęściej C:\WINNTMOJPROG.EXE //E:0 //TEMPPATH:'%TEMP' //SWAPPATH:'%TEMP%'
3.7 Mój program nic nie robi, a pochłania 100% zasobów systemu. Co z tym zrobić?
Podzielić się zasobami z systemem, korzystając z funkcji OL_Yield() lub OL_AutoYield() w bibliotece OSLib http://www.davep.org/clipper/#OSLib
Ewentualnie skorzystać z MULTI102.ZIP http://www.the-oasis.net/files/general/multi102.zip
3.8 Jak drukować na drukarkę nie obsługiwaną przez DOS (GDI-windrukarkę lub USB)?
Najprościej - używając programu PageScript http://www.abeelabs.com/. Można w ten sposób drukować grafikę i wysyłać faksy! Polecam też lekturę http://www.dse.nl/~tmk/clipper/clpwinprint.htm
3.9 Czy z mojego programu mogę wysyłać/odbierać pocztę elektroniczną?
Tak, oczywiście. Wystarczy skorzystać z dowolnego programu do wysyłania/odbioru poczty z wiersza poleceń. Pod Windows dostępny jest darmowy program BLAT do wysyłania i GETMAIL do odbioru poczty http://www.interlog.com/~tcharron/
3.10 Muszę odzyskać kod źródłowy programu. Czy jest jakiś dekompilator?
Jest Rescue5 (słabszy) i Valkyrie. Ten drugi ma wersję dla Clippera Summer'87 i Clippera 5.0x-5.2x, ale nie dekompiluje programów konsolidowanych nowszymi wersjami Blinkera (powyżej 3.3). Valkyrie powinna być dostępna w firmie GrafXSoft (patrz p.3.1). Profesjonalną (tzn. płatną) pomoc można uzyskać od Rossa McKenzie z ValuSoft - valusoft(at)mbox.com.au
3.11 Chcę przenieść aplikację, czyli co dalej po Clipperze?
Odpowiedzi jest wiele. Niektóre proponują zastosowanie rozszerzeń
do Clippera, inne próbują przenieść kod do nowego środowiska.
Wymienię najbardziej znane rozwiązania w kolejności alfabetycznej:
3.12 Gdzie mogę znaleźć jakąś bibliotekę do Clippera?
Większość bibliotek komercyjnych można kupić w firmie GrafXSoft (patrz p.3.1). Wersji demonstracyjnych/testowych tych bibliotek należy szukać na stronach www ich producentów. W ostatnich latach wielu autorów zmieniło status swych bibliotek/programów na freeware czy public domain i przekazało je do udostępnienia w największej kolekcji oprogramowania Clipperowego - prowadzonej przez Phila Barnetta Oasis http://www.the-oasis.net/. Od tego adresu należy zacząć poszukiwania.
3.13 Windows Me nie pozwala na zmiany w CONFIG.SYS i AUTOEXEC.BAT. Jak przywrócić możliwość zmian?
Przeszukać grupę dyskusyjnš pl.comp.os.ms-windows.win9x
Zajrzeć na Windows Online http://windows.online.pl/
Przeczytać artykuł http://www.computerhope.com/issues/ch000361.htm
Polecam też lekturę na temat przywracania Dosa w Windows ME:
http://www.geocities.com/mfd4life_2000/
http://www.sgmvp.freewebsites.com/WinME_DOS/WinME.htm
http://www.overclockers.com.au/techstuff/a_dos_me/
3.14 Jak wyświetlić/wydrukować znak euro?
Polecam lekturę http://www.sysmod.com/eurosoft.htm
3.15 Mam jakieś pliki baz danych. Chyba to dbfy, chyba są uszkodzone...
Opisy struktur wielu różnych typów plików sš zebrane na http://www.wotsit.org. Artykuł http://www.e-bachmann.dk/docs/xbase.htm zawiera opis plików dbf, plików pól memo dbt i fpt, plików zmiennych pamięciowych mem oraz indeksów ndx, mdx, ntx, idx i cdx. Najprostsze narzędzie do naprawy plików DBF to FILEFIX z dosowego pakietu Norton Utilities. Naprawia pliki dBase i Clippera (z polami memo *.DBT). Do zaawansowanej naprawy plików służy program Recover firmy Abri http://www.abri.com/recover.html
Clipper - komunikaty błędów, system rozszerzeń lub Clipper - komunikaty błędów, system rozszerzeń
CA-Clipper - opis, procedury, recenzje książek
Clipper...Clipper...Clipper - historia wersji, narzędzia, tips & tricks
Pytania:
6.1 Skąd wziąć?
6.2 Dokumentacja
6.3 Polskie znaki w InterBase
6.4 Narzędzia do zarządzania bazą danych
Literatura
Linki
Odpowiedzi:
Zamiast InterBase polecam jego ulepszony klon: FireBird. FireBird ma poprawione wszystkie błędy InterBase (m.in. dziurę w bezpieczeństwie) oraz zawiera kilka rozszerzeń SQLa w stosunku do InterBase.
FireBirda mozna ściągnąć ze strony: http://firebird.sourceforge.net
InterBase ze strony http://www.borland.pl z działu "do pobrania".
6.1.1 Instalacja
Bardzo prosta,
w przypadku Linuxa: z RPM-a, zalecam architekturę ClassicServer,
w przypadku Windows: zalecam architekturę SuperServer.
Bogata dokumentacja InterBase w formacie PDF jest do ściągnięcia ze strony ftp://ftp.borland.pl/ibase/final6/ib_b60_doc.zip
CREATE DATABASE 'mojadb.gdb' [inne opcje] DEFAULT CHARACTER SET WIN1250CREATE TABLE TEST (TEKST VARCHAR(1024) CHARACTER SET WIN1250 COLLATE PXW_PLK)SET NAMES WIN1250;lub
SET NAMES ISO8859_2; (jeżeli masz wersję FireBirda która obsługuje ten charset).
6.4 Narzędzia do zarządzania bazą danych
IMHO najlepsze narzędzie to IBExpert - odwiedź http://www.ibexpert.com/
Strona domowa developerów FireBirda, zawierająca najnowsze informacje i zasoby
InterBase product documentation
Pytania:
7.1 Skąd wziąć?
7.2 Aktualne wersje oprogramowania
7.2.1 Co zostało istotnie ulepszone w wersji 2000 ? Czy warto dokonać aktualizacji ?
7.3 Edycje SQL Servera
7.3.1 Jakie edycje mogę zainstalować na Windows 2000 Prof.?
7.3.2 Jakie edycje mogę zainstalować na Windows 98 ?
7.3.3 Jakie edycje mogę zainstalować na Windows CE ?
7.3.4 W jaki są sposób są licencjonowane poszczególne edycje ?
7.4 Narzędzia do zarządzania bazą danych
7.5 Czy przy pomocy Microsoft Access można tworzyć bezpośrednio bazy danych na SQL Serverze?
7.6 Czy mogę zainstalować SQL Server 2000 na maszynie na której jest zainstalowany SQL Server 7.0 ?
7.7 Czy mogę odłączyć bazę danych w wersji 7.0 i następnie załączyć w wersji 2000?
7.8 Czy mogę odtworzyć kopię zapasową bazy danych z wersji 7.0 bezpośrednio na serwerze w wersji 2000?
7.9 Czy podczas upgrade do wersji 2000 mogę zaktualizować tylko niektóre bazy danych?
7.10 Czy można ustawić dla jednej bazy inny porządek sortowania?
7.11 Jak sprawdzić ile osób korzysta z bazy danych w danej chwili?
Literatura
Linki
Odpowiedzi:
Microsoft SQL Server jest produktem komercyjnym - należy go kupić.
Jeśli nie chcesz od razu wydawać pieniędzy możesz zamówić sobie wersję testową, działającą przez 120 dni pod adresem http://www.microsoft.com/poland/trial/ lub ściągnąć bezpośrednio z sieci pod adresem http://www.microsoft.com/sql/evaluation/trial/2000/default.asp.
Warto pamiętać, że edycja MSDE jest rozprowadzana także z najnowszymi wersjami Visual Studio oraz Office Proffesional.
7.2 Aktualne wersje oprogramowania
Aktualną wersją oprogramowania jest wersja 2000 z zainstalowanym Service Pack 2.
W celu sprawdzenia numeru wersji należy zadać zapytanie (np. w SQL Query Analyzer):
SELECT @@VERSION
Możesz także sprawdzić wersję bezpośrednio w Enterprise Managerze wybierając właściwości serwera.
W obu przypadkach powinieneś uzyskać numer wersji w jednej z postaci:
Dla poprzedniej wersji SQL Servera 7.0 wydano do tej pory trzy uaktualnienia serwisowe:
Jeżeli w systemie zainstalowano jedną z gorących poprawek (HotFix) to możesz uzyskać numer wersji różnych od wyżej wymienionych. Powinieneś zadbać jednak o to, aby numer wersji był jak najwyższy - dzięki temu unikniesz błędów w oprogramowaniu, które zostały już wykryte i naprawione. Z drugiej strony musisz pamiętać o tym, że wszelkie poprawki mogą także zawierać błędy. Zatem przed ich zainstalowaniem warto je samodzielnie przetestować.
7.2.1 Co zostało istotnie ulepszone w wersji 2000 ? Czy warto dokonać aktualizacji ?
Można wymienić wiele usprawnień, jednak o tym czy warto dokonać aktualizacji (i wydać na to pieniądze) będziesz musiał sobie odpowiedzieć sam. Najważniejsze (moim zdaniem) usprawnienia:
Jeśli jakieś funkcji spośród wyżej wymienionych brakuję Ci w wersji 7.0 to polecam aktualizację.
SQL Server 2000 został opracowany w siedmiu edycjach:
Poniżej przedstawiłem porównanie wybranych cech edycji (wszystkie parametry należy traktować pod warunkiem, że system operacyjny na to pozwala):
| Cecha | Ent | Srv | Per | Dev | MSDE | CE | EE |
| Maksymalna liczba procesorów | 32 | 4 | 2 | 32 | 2 | n/d | 32 |
| Max wielkość RAM | 64 GB | 2 GB | 2 GB | 64 GB | 2 GB | n/d | 64 GB |
| Max liczba instancji na jednej maszynie | 16 | 16 | 16 | 16 | 16 | n/d | 16 |
| Praca w klastrach | + | - | - | + | - | - | + |
| Zaawansowane techniki (np. Log Shipping, Indexed View, SAN Support, itd.) | + | - | - | + | - | - | + |
| Wyszukiwanie pełnotekstowe | + | + | + | + | - | - | + |
| Moduł analityczny (OLAP) | + | + | + | + | - | - | + |
| Data mining | + | + | + | + | - | - | + |
| English Query | + | + | + | + | - | - | + |
| Max. rozmiar bazy | 1 mln TB | 1 mln TB | 1 mln TB | 1 mln TB | 2 GB | 1 mln TB | 1 mln TB |
7.3.1 Jakie edycje mogę zainstalować na Windows 2000 Prof. ?
Developer, Personal, Desktop, Enterprise Evaluation.
7.3.2 Jakie edycje mogę zainstalować na Windows 98 ?
Personal, Desktop.
7.3.3 Jakie edycje mogę zainstalować na Windows CE ?
Jedynie SQL Server 2000 Windows CE.
7.3.4 W jaki są sposób są licencjonowane poszczególne edycje ?
Dla edycji Standard i Enterprise istnieją dwa modele licencjonowania: na procesor i na nazwanego użytkownika (CAL). W przypadku licencji na procesor wymaganej jest posiadanie licencji na każdy procesor w maszynie na której pracuje SQL Server. W przypadku wykorzystywania wielu instancji na jednej maszynie dla edycji Enterprise nie są wymagane dodatkowe licencji, dla edycji Standard musimy mieć licencję na każdy procesor oraz każdą instancję oddzielnie.
W modelu licencjonowania CAL musimy posiadać licencję na każdy serwer oraz dla każdego użytkownika korzystającego z zasobów serwera.
Edycję Personal może zainstalować każdy użytkownik, który posiada licencję na korzystanie z zasobów edycji Standard lub Enterprise.
Edycja Developer jest licencjonowana na pojedynczego programistę.
Edycja Desktop jest najczęściej rozprowadzana na z opracowanymi specjalnie dla SQL Servera aplikacjami. Zatem musisz posiadać licencję na taką aplikację. Warto zaznaczyć, że nie uprawnia to do korzystania z edycji Desktop w inny sposób (np. projektowania własnego oprogramowania).
Edycja Enterprise Evaluation upoważnia do zainstalowania i testowania serwera przez okres 120 dni. Nie wolno jej jednak wykorzystywać do zadań prodkcyjnych.
7.4 Narzędzia do zarządzania bazą danych
Zdecydowanie najlepszym i najbardziej popularnym jest Enterprise Manager dostarczany wraz z serwerem (oprócz wersji Desktop).
7.5 Czy przy pomocy Microsoft Access można tworzyć bezpośrednio bazy danych na SQL Serverze ?
Tak, posługując się tzw. projektami wprowadzonymi w Accessie od wersji 2000. Można utworzyć i modyfikować samą bazę danych, a także tabele, widoki, procedury, uprawnienia użytkowników, itd.
Przy tworzeniu baz dla SQL Servera w wersji 2000 zalecane jest używanie Accessa w wersji XP. W przypadku Access 2000 należy zainstalować dodatkowo aktualizację znajdującą się pod adresem: http://office.microsoft.com/downloads/2000/Accsql.aspx
7.6 Czy mogę zainstalować SQL Server 2000 na maszynie na której jest zainstalowany SQL Server 7.0 ?
Tak. Możesz zainstalować SQL Server 2000 jako nazwaną instancję, a następnie możesz uruchomić jednocześnie serwer 2000 wraz z działającym serwerem w wersji 7.0.
7.7 Czy mogę odłączyć bazę danych w wersji 7.0 i następnie załączyć w wersji 2000 ?
Tak. Możesz odłączyć (detach) bazę danych w wersji 7.0, a następnie załączyć ją (attach) w wersji 2000. Musisz pamiętać jednak o tym, że załączenie bazy danych w wersji 2000 powojuje jej taką modyfikację, że nie da się ponownie załączyć w wersji 7.0.
Tak. Możesz odtworzyć kopię zapasową bazy danych z wersji 7.0 bezpośrednio w wersji 2000. Niestety, odwrotna operacja (odtworzenia bazy 2000 na wersji 7.0) nie jest możliwa.
7.9 Czy podczas upgrade do wersji 2000 mogę zaktualizować tylko niektóre bazy danych ?
Nie. Jeśli dokonujesz procesu upgrade musisz zaktualizować wszystkie bazy danych.
Jeśli zależy Ci na aktualizacji tylko niektórych baz danych zainstaluj serwer 2000 jako dodatkową nazwaną instancję, następnie przenieść wybrane bazy danych. Na jednej maszynie będą wtedy działały dwie wersje SQL Servera: 7.0 oraz 2000.
7.10 Czy można ustawić dla jednej bazy inny porządek sortowania ?
W wersji 7.0 nie. W wersji 2000 tak - dla każdej bazy danych (a nawet pola w tabeli) możesz ustawić innym porządek sortowania.
7.11 Jak sprawdzić ile osób korzysta z bazy danych w danej chwili ?
Istnieje kilka sposobów, np.:
sp_who - informacje o użytkownikach.select * from sysprocesses -
informacje o procesach.Pytania:
8.1 Skąd wziąć?
8.2 Aktualna wersja?
8.3 Szukam kompletnego, darmowego tutoriala dla MySQL.
8.4 Czy możecie polecić mi dobrego klienta MySQL pod Windows?
8.5 Jak wyeksportować tabele/dane do pliku?
8.6 Czy MySQL obsługuje podzapytania?
8.7 Czy MySQL obsługuje procedury wbudowane, triggery i perspektywy?
8.8 Jak wygląda obsługa różnych kodowań znaków?
Literatura
Linki
Odpowiedzi:
Oficjalny serwis: http://www.mysql.com
Mirrory w Polsce, np.:
http://sunsite.icm.edu.pl/mysql/
ftp://sunsite.icm.edu.pl/pub/unix/mysql/
Na 30 września 2001: 3.23.42
http://sunsite.icm.edu.pl/mysql/Downloads/Manual/manual.pdf
8.4 Czy możecie polecić mi dobrego klienta MySQL pod Windows?
phpMyAdmin - zestaw skryptów PHP do zarządzania bazą MySQL przez WWW. Wymagany serwer http obsługujący PHP.
http://www.phpwizard.net/projects/phpMyAdmin/
MySQLWinAdmin - interfejs GUI do administracji.
http://www.mysql.com/Downloads/Contrib/mysqlwinadmn.zip
mysqlfront - klient dla Windows - oferuje dostęp i zarządzanie bazą, tabelami, danymi, indeksami, plikami importu i eksportu.
http://www.mysqlfront.de/
Dbtools - narzędzie do zarządzania bazą MySQL - oferuje zarządzanie serwerem, bazami, tabelami, kolumnami, indeksami i użytkownikami. Zawiera narzędzie do importu struktury i danych z MS Access, MS Excel, Dbase, FoxPro, Paradox i baz obsługiujących ODBC.
http://dbtools.vila.bol.com.br/
Więcej narzędzi do MySQL:
Spis: http://sunsite.icm.edu.pl/mysql/documentation/mysql/bychapter/manual_Contrib.html
Pobieranie: http://sunsite.icm.edu.pl/mysql/downloads/contrib.html
ftp://sunsite.icm.edu.pl/pub/unix/mysql/Downloads/Contrib/
8.5 Jak wyeksportować tabele/dane do pliku?
Służy do tego program mysqldump.
Import stworzonych danych z powrotem do bazy o nazwie "database":
shell> mysql database < nazwa_dumpa
Jeśli plik tekstowy zaczyna się od USE db_name
to w tym przypadku dane zostaną wczytane do bazy "db_name" i nie trzeba podawać tej
nazwy w linii komend:
shell> mysql < text_file
8.6 Czy MySQL obsługuje podzapytania?
W wersjach 4.x i niższych MySQL obsługuje podzapytania tylko w instrukcjach
INSERT ... SELECT ... oraz REPLACE ... SELECT .... Podzapytania są już w wersji 4.1.
8.7 Czy MySQL obsługuje procedury wbudowane, triggery i perspektywy?
Obsługa procedur wbudowanych i perspektyw jest dodana w wersji 5.0, w tejże wersji będą też triggery.
8.8 Jak wygląda obsługa różnych kodowań znaków?
Do wersji 4.0 serwer mógł być ustawiony na konkretny zestaw znaków.
W wersji 4.1 można korzystać z różnych zestawów na poziomie serwera, bazy danych, tabeli lub pola.
Są dostępne również możliwości konwertowania pomiędzy różnymi kodowaniami. Można też przechowywać
dane w formacie Unicode - są obsługiwane kodowania UCS2 i UTF8.
Pytania:
9.1 Skąd wziąć?
9.2 Jak zrobić automatyczną numerację rekordów?
9.3 Oracle FORMS - COMMIT problem.
9.4 Wyszukiwanie w polach znakowych zawierających znaki narodowe.
9.5 Czy można w procedurze PL/SQL wysłać komunikat na ekran?
9.6 Czy możliwe jest stworzenie procedury składowanej zwracającej zestaw rekordów?
9.7 Jak zlikwidować ograniczenie NOT NULL nie znając jego nazwy?
9.8 Jak ograniczyć ilość zwracanych wierszy z zapytania SELECT?
9.9 Jak zainstalować bazę Oracle i Developera na jednym komputerze? [wersja beta]
9.10 Jak znaleźć rekordy z konkretnego dnia?
9.11 Jak znaleźć wszystkie "foreign key" założone na innych tabelach i odnoszące się do kolumn w tabeli NAZWA_TABELI?
9.12 Instalacja Oracle pod Linuksem
9.13 Dlaczego podczas wykonywania triggera wyskakuje błąd "ORA-04091 table string.string is mutating, trigger/function may not see it"?
9.14 Mam problem z instalacją Oracle 8.1.x na komputerze z Pentium 4...
9.15 Poszukuję tutoriali do Forms i/lub innego oprogramowania Oracle
9.16 Jakie wybrać narzędzie zamiast SQL*Plus-a?
9.17 Jak sprawdzić, który element procedury/funkcji PL/SQL wykonuje się najdłużej?
Literatura
Linki
Odpowiedzi:
9.2 Jak zrobić automatyczną numerację rekordów?
Do autonumerowania slużą sekwencje. Można je tworzyć w następujący sposób:
create sequence [schemat.]nazwa_sekwencji [increment by x] [start withy]
[maxvalue max|nomaxvalue] [minvalue min|nominvalue]
[cycle|nocycle] [cache|nocache] [order|noorder];
Parametry podane w nawiasach kwadratowych są opcjonalne. Jeśli sekwencja zostanie stworzona bez żadnych parametrów:
create sequence test;
to zostaną przyjęte parametry domyślne:
increment by 1 nominvalue nomaxvalue nocycle cache 20 noorder
co oznacza, że sekwencja będzie zwiększana co 1, nie ma minimalnej i maksymalnej wartości, sekwencja nie będzie generować więcej wartości po osiągnięciu maksimum lub minimum. Dwadzieścia kolejnych wartości będzie przechowywanych w pamięci cache w celu szybszego dostępu; nie ma gwarancji, że liczby będą generowane w kolejności przychodzenia żądań. Jeśli sekwencja ma zmniejszać swoją wartość, należy zadeklarować ją w ten sposób:
create sequence seq_zmniejszajaca increment by -1 start with 10000000 maxvalue 10000000 minvalue 1;
Parametry sekwencji można obejrzeć poprzez perspektywę USER_SEQUENCES
SQL> SELECT * FROM user_sequences; SEQUENCE_NAME MIN_VALUE MAX_VALUE INCREMENT_BY C O CACHE_SIZE LAST_NUMBER --------------------- --------- --------- ------------ - - ---------- ----------- SEQ_ZMNIEJSZAJACA 1 10000000 -1 N N 20 10000000 TEST 1 1,000E+27 1 N N 20 1
Widać, że sekwencja utworzona z parametrami domyślnymi ma maksymalną wartość 1E+27, co wynika z maksymalnego rozmiaru liczby dla sekwencji, czyli 28 cyfr. Kolejne wartości z sekwencji pobieramy w ten sposób:
nazwa_sekwencji.nextval
a wartość bieżącą sekwencji:
nazwa_sekwencji.currval
SQL> SELECT test.nextval FROM dual;
NEXTVAL
---------
1
SQL> SELECT test.currval FROM dual;
CURRVAL
---------
1
Jak widać, pierwsze zwiększenie sekwencji po jej utworzeniu zwraca jej wartość początkową. Odwołanie do bieżącej wartości (CURRVAL) zwraca bieżącą wartość sekwencji, która jest wartością zwróconą przez ostatnie odwołanie do NEXTVAL. Przed użyciem CURRVAL dla danej sekwencji w danej sesji należy najpierw zainicjalizować sekwencję przy pomocy NEXTVAL. W innym wypadku wyniki mogą być niespodziewane. Można to przetestować tworząc nową sekwencję i sprawdzając jej wartość za pomocą CURRVAL. Przykładowe użycie sekwencji:
INSERT INTO emp VALUES (empseq.nextval, 'LEWIS', 'CLERK', 7902, SYSDATE, 1200, NULL, 20);
Wykorzystanie sekwencji do automatycznego numerowania rekordów przy wstawianiu:
create or replace trigger nadaj_id
before insert on tabela
for each row
begin
if :new.id is null then
select tab_seq.nextval into :new.id from dual;
end if;
end;
Jeśli nie będziemy sprawdzać, czy wstawiane pole id jest puste, to wtedy każdy wpisany rekord będzie posiadał numer nadany przez sekwencję. Spowoduje to niemożność wstawienia rekordu z zadanym numerem id - jeśli zaszłaby taka konieczność. Oczywiście zawsze warto, aby na polu id był założony klucz unikalny bądź główny - pozwoli to uniknąć ewentualnych duplikatów w tym polu.
Komunikat bierze się stąd, że nie było żadnych zmian na blokach w formie. Zamiast COMMIT; wpisz FORMS_DDL('commit'); To samo należy zastosować w przypadku błędu FRM-40401.
9.4 Wyszukiwanie w polach znakowych zawierających znaki narodowe.
Mamy takie dane:
[1] SELECT identyfikator FROM kontrahenci ORDER BY identyfikator; IDENTYFIKATOR ------------- (...) K014 K015 K015 L010 L011 L012 Ł001 M001 M001 (...)
Standardowo, ciągi znakowe w klauzuli WHERE są porównywane wg binarnych wartości poszczególnych znaków, co może powodować nieprawidłową kolejność ciągów znakowych - inną niż by to wynikało z kolejności znaków w alfabecie danego języka. Tak więc, zamiast zapytania
[2] SELECT identyfikator FROM kontrahenci WHERE identyfikator > 'K%' and identyfikator < 'N%' ORDER BY identyfikator;
które zwróci takie wyniki (nie pokaże się identyfikator 'Ł001'):
IDENTYFIKATOR ------------- (...) K015 K015 L010 L011 L012 M001 M001 M001 (...)
należy użyć takiego zapytania:
[3]
SELECT identyfikator FROM kontrahenci WHERE nlssort(identyfikator) >
nlssort('K%') and nlssort(identyfikator) < nlssort('N%')
ORDER BY identyfikator;
co spowoduje, że wyniki sortowania będą prawidłowe:
IDENTYFIKATOR ------------- (...) K014 K015 K015 L010 L011 L012 Ł001 M001 M001 (...)
Oczywiście należy mieć ustawione prawidłowe parametry sortowania w NLS_SESSION_PARAMETERS:
SQL> SELECT * FROM nls_session_parameters; PARAMETER VALUE ----------- ------ (...) NLS_SORT POLISH (...)
Jeśli parametr NLS_SORT jest bezpośrednio w bazie danych ustawiony na wartość POLISH, to:
NLS_SORT = POLISH znaki są prawidłowo sortowane; przy wyszukiwaniu w polach znakowych ze znakami narodowymi należy dodatkowo użyć funkcji nlssortNLS_SORT np. amerykańskie, to polskie znaki są sortowane niepoprawnie, nawet gdy używamy funkcji nlssort.alter session set nls_sort='POLISH'; wtedy proste sortowanie typu SELECT * FROM tabela ORDER BY pole_tekstowe;
jest wykonywane prawidłowo, ale gdy znaki narodowe występują w klauzuli WHERE należy pamiętać o użyciu funkcji nlssort.9.5 Czy można w procedurze PL/SQL wysłać komunikat na ekran?
Można, za pomocą procedur pakietu DBMS_OUTPUT, np.
dbms_output.put('Zmienna a = '||a);
dbms_output.put_line('Zmienna a = '||a);
Drugie polecenie powoduje wyświetlenie napisu z przejściem do nowej linii. W SQL*Plus trzeba ustawić wcześniej:
set serveroutput on;
9.6 Czy możliwe jest stworzenie procedury składowanej zwracającej zestaw rekordów?
Można to zrobić w ten sposób:
CREATE OR REPLACE PACKAGE PROBA_PCK IS
TYPE R IS RECORD
(
id NUMBER(15,0),
imie VARCHAR2(20), -- tutaj specyfikacje odpowiednich kolumn z tabeli pracownicy
nazwisko VARCHAR2(50)
);
TYPE kursor_r IS REF CURSOR RETURN R;
procedure Test(k_r IN OUT kursor_r,x number);
END PROBA_PCK;
/
CREATE OR REPLACE PACKAGE BODY PROBA_PCK IS
procedure Test(k_r IN OUT kursor_r,x number) is
begin
open k_r for SELECT id,imie,nazwisko FROM pracownicy WHERE wynagrodzenie > x;
end;
END PROBA_PCK;
/
Taki mechanizm jest wykorzystywany przez FORMSy, gdy blok jest oparty na procedurach składowanych (a nie standardowo na tabeli).
9.7 Jak zlikwidować ograniczenie NOT NULL nie znając jego nazwy?
alter table nazwa_tabeli modify (id NULL);
9.8 Jak ograniczyć ilość zwracanych wierszy z zapytania SELECT?
możesz użyć kursora:
declare
-- kursor pobierający dane z tabeli
cursor top is SELECT * FROM tabela ORDER BY pole1;
-- zmienna przechowująca zawartość bieżącego rekordu
top_zm top%rowtype;
ile_pobrac number(6) := 10;
l_pobranych number(6) := 0;
begin
open top;
while l_pobranych < ile_pobrac loop
fetch top into top_zm;
exit when top%NOTFOUND;
l_pobranych := l_pobranych + 1;
dbms_output.put_line(top_zm.pole1||top_zm.pole2||top_zm.pole3);
end loop;
close top;
end;
jeśli nie zależy ci na kolejności:
SELECT * FROM tabela WHERE rownum < 10;
jeśli zależy ci na kolejności (to działa dopiero od Oracle 8i):
SELECT * FROM (SELECT * FROM tabela ORDER BY jakaskolumna) WHERE rownum < 10;
Dla wersji wcześniejszych niż 8i:
SELECT * FROM tabela a WHERE 10 >=
(SELECT count(distinct maxcol) FROM my_table b WHERE b.maxcol >= a.maxcol)
ORDER BY maxcol;
9.9 Jak zainstalować bazę Oracle i Developera na jednym komputerze? [wersja beta]
[na podstawie instalacji Personal Oracle i Developer 6i w Windows 98] Co potrzebujemy? Jeśli posiadamy system Windows 98, to potrzebna jest baza Oracle8i Personal Edition Release 8.x.x for Windows 98. Jeśli naszym systemem jest Windows NT/2000, to potrzebna jest baza Oracle8i Personal Edition Release 8.x.x for Windows NT. Kolejność instalacji jest następująca: najpierw Developer w jednym katalogu ORACLE_HOME, a następnie baza w innym ORACLE_HOME. Konfiguracja przykładowej bazy:
Developer: DEV_HOME, d:\dev2000 Personal Oracle: ORACLE_HOME, d:\oracle GLOBAL_DBNAME = slawek SID = slawek ORACLE_HOME = d:\oracle DEV_HOME = d:\dev2000
Plik $ORACLE_HOME\network\admin\listener.ora:
# specyfikacja adresów, pod którymi listener "nasłuchuje"
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1))
(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
)
)
(DESCRIPTION =
(PROTOCOL_STACK =
(PRESENTATION = GIOP)
(SESSION = RAW)
)
(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 2481))
)
)
# lista serwisów, do których listener może łączyć klientów
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = PLSExtProc)(ORACLE_HOME = d:\Oracle)(PROGRAM = extproc)
)
(SID_DESC =
(GLOBAL_DBNAME = slawek)(ORACLE_HOME = d:\Oracle)(SID_NAME = slawek)
)
)
# gdzie logować działania listenera
LOG_FILE_LISTENER = lsnr
LOG_DIRECTORY_LISTENER = d:\oracle\network\log
Plik $ORACLE_HOME\network\admin\sqlnet.ora:
names.default_domain = world names.default_zone = world names.directory_path= (TNSNAMES, HOSTNAME)
Plik $ORACLE_HOME\network\admin\tnsnames.ora:
slawek.world =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS =
(COMMUNITY = tcp.world)(PROTOCOL = TCP)(Host = localhost)(Port = 1521)
)
(ADDRESS =
(COMMUNITY = tcp.world)(PROTOCOL = TCP)(Host = localhost)(Port = 1526)
)
)
(CONNECT_DATA = (SERVICE_NAME = slawek)(SID = slawek)
)
)
EXTPROC_CONNECTION_DATA =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1))
)
(CONNECT_DATA =
(SID = PLSExtProc)(PRESENTATION = RO)
)
)
Plik $DEV_HOME\net80\admin\sqlnet.ora:
names.directory_path = (TNSNAMES, HOSTNAME) names.default_domain = world name.default_zone = world
Plik $DEV_HOME\net80\admin\tnsnames.ora:
slawek.world =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS =
(COMMUNITY = tcp.world)(PROTOCOL = TCP)(Host = localhost)(Port = 1521)
)
(ADDRESS =
(COMMUNITY = tcp.world)(PROTOCOL = TCP)(Host = localhost)(Port = 1526)
)
)
(CONNECT_DATA = (SID = slawek)
)
)
W celu automatycznego startu listenera (procesu "nasłuchującego") zmieniamy w Rejestrze w HKEY_LOCAL_MACHINE\Software\ORACLE\HOME0 wartość ciągu LISTENER_STARTUP na AUTO.
Jeśli chcemy, aby w narzędziach Developera nie trzeba było wpisywać "connect string", należy dodać nową wartość ciągu w Rejestrze Windows:
LOCAL="slawek" w HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\HOME1. Oczywiście zamiast "slawek" wpisujemy nazwę aliasu, którą wpisaliśmy do TNSNAMES.ORA, a zamiast HOME1 wybieramy ten ORACLE_HOME, w którym jest zainstalowany Developer.
9.10 Jak znaleźć rekordy z konkretnego dnia?
Załóżmy, że w tabeli znajduje się pole data typu "date"; chcemy znaleźć rekordy np. z dnia 2001/05/21.
Należy wiedzieć, że data w bazie Oracle składa się z dnia i godziny, tak więc jeśli w warunku WHERE nie podamy godziny,
to baza domyślnie przyjmuje godzinę 0:00:00. Aby otrzymać prawidłowe wyniki należy więc albo podać godzinę albo usunąć
ją z pola data (za pomocą funkcji trunc).
[1 - obcinamy godzinę i zostają zwrócone rekordy tylko z żądaną datą]
select ... where trunc(data) = to_date('2001/05/21', 'YYYY/MM/DD');
[2 - pobieramy rekordy, w których data jest większa lub równa żądanej i jednocześnie mniejsza od następnego dnia]
select ... where data >= to_date('2001/05/21','YYYY/MM/DD') and data < to_date('2001/05/22','YYYY/MM/DD');
[3 - pobieramy rekordy, w których data jest równa żądanej; wykorzystujemy tu konwersję daty pobranej z rekordu na ciąg znaków; bez tej konwersji to zapytanie będzie zwracać nieprawidłowe wyniki!]
select ... where to_char(data, 'YYYY/MM/DD') = '2001/05/21';
Funkcja to_date jest potrzebna, gdy nie znamy formatu daty ustawionego u klienta. Należy zwrócić uwagę na to, że gdy
użyjemy pierwszego lub trzeciego sposobu, dla każdego rekordu pobranego z tabeli będzie wykonywana funkcja trunc lub to_char,
co przy większej liczbie rekordów może mieć ujemny wpływ na wydajność. W drugim zapytaniu funkcja konwersji będzie wykonana
tylko 2 razy.
Rozwiązania z użyciem godziny:
[4 - wybieramy daty z godziną większą lub równą godzinie 0:00 szukanego dnia oraz z godziną mniejszą lub równą godzinie 24:00 (czyli końcu doby) szukanego dnia]
select ... where to_char(data, 'YYYY/MM/DD, HH24:MI:SS') >= '2001/05/21, 00:00:00'
and to_char(data, 'YYYY/MM/DD, HH24:MI:SS') <= '2001/05/21, 24:00:00';
[5 - wybieramy daty z godziną większą lub równą godzinie 0:00 szukanego dnia oraz z godziną mniejszą niż godzina 0:00 następnego dnia]
select ... where to_char(data, 'YYYY/MM/DD, HH24:MI:SS') >= '2001/05/21, 00:00:00'
and to_char(data, 'YYYY/MM/DD, HH24:MI:SS') < '2001/05/22, 00:00:00';
Można tu wykorzystać następujące zapytanie:
SELECT c.owner,c.table_name "TABELA Z FK",
c.constraint_name "NAZWA FK",
ucc.table_name "TABELA Z PK",
ucc.column_name "KOLUMNA Z PK"
FROM user_constraints c, user_cons_columns ucc
WHERE c.r_constraint_name=ucc.constraint_name
AND ucc.table_name='NAZWA_TABELI';
Pokaże ono mniej więcej takie wyniki:
OWNER TABELA Z FK NAZWA FK TABELA Z PK KOLUMNA Z PK ------ ------------- ----------- ------------ ------------ PO8 PRACOWNICY SYS_C00926 NAZWA_TABELI ID PO8 PRACOWNICY2 SYS_C00931 NAZWA_TABELI ID
Mamy tutaj tabele, które zawierają klucze obce do tabeli NAZWA_TABELI i wiemy, której kolumny w tejże tabeli dotyczy klucz obcy. Jeśli chcemy wiedzieć, na jakich kolumnach są założone klucze obce, to trzeba wykorzystać takie zapytanie:
SELECT ucc.constraint_name "NAZWA FK",
ucc.owner,
ucc.table_name "TABELA Z FK",
ucc.column_name "KOLUMNA Z FK"
FROM user_cons_columns ucc where ucc.constraint_name IN
(
SELECT c.constraint_name
FROM user_constraints c, user_cons_columns cc
WHERE c.r_constraint_name=cc.constraint_name
AND cc.table_name='NAZWA_TABELI'
);
Wyniki powinny być podobne do tych:
NAZWA FK OWNER TABELA Z FK KOLUMNA Z FK ------------ ------ ------------ ------- SYS_C00926 PO8 PRACOWNICY ID_EMP SYS_C00931 PO8 PRACOWNICY2 ID_FK
Poniższe zapytanie również poda nam nazwy szukanych tabel i nazwy kluczy obcych:
SELECT c.owner,c.table_name "TABELA Z FK",
c.constraint_name "NAZWA FK"
FROM user_constraints c
WHERE c.constraint_type = 'R'
AND c.r_constraint_name IN
(SELECT uc.constraint_name FROM user_constraints uc WHERE uc.table_name = 'NAZWA_TABELI');
OWNER TABELA Z FK NAZWA FK
------ ------------ ----------
PO8 PRACOWNICY SYS_C00926
PO8 PRACOWNICY2 SYS_C00931
9.12 Instalacja Oracle pod Linuksem
Opracował Robert Diak
Najlepsze opracowania instalacji Oracla8i na platformę Linux znajdują się w nastepujących miejscach:
http://jordan.fortwayne.com/oracle/
http://www.zx81.org.uk/computing/oracle/
http://www.pawprint.net/linux/
http://linuxlab.dk/fcl/technotes/ora_817_3.html
http://staff.in2.hr/denis/oracle/
W tym opracowaniu skupię na opisie instalacji Oracla8i na systemie operacyjnym RedHat 6.2. Na wyżej wymienionych stronach znajdują się wyczerpujące opisy instalacji Oracla na innych wersjach tego systemu.
linux81701.tar. Zajmuje ona ponad 500MB więc trzeba się uzbroić w cierpliwość.
jdk118_v3-glibc-2.1.3.tar.bz2 oraz jre118_v3-glibc-2.1.3.tar.bz2
/usr/local i robimy odpowiednie dowiązania symboliczne (linki) nazywając je odpowiednio JAVA i JRE.4a) groupadd dba 4b) groupadd oper 4c) groupadd oinstall 4d) useradd oracle -g oinstall -G dba 4e) passwd oracle 4f) mkdir /u01 /u02 4g) chown oracle.oinstall /u01 /u02 4h) chmod 775 /u01 /u02
ORACLE_BASE=/u01/app/oracle
ORACLE_HOME=/u01/app/oracle/product/8.1.7
ORACLE_SID=MAP
PATH=$PATH:/u01/app/oracle/product/8.1.7/bin
CLASSPATH=.:/u01/app/oracle/product/8.1.7/jdbc/lib/classes111.zip
LD_LIBRARY_PATH=/u01/app/oracle/product/8.1.7/lib
ORA_NLS33=/u01/app/oracle/product/8.1.7/ocommon/nls/admin/data
NLS_LANG=polish
Zmienną ORACLE_SID możemy wybrać dowolnie.runInstaller.product/8.1.7 lub product/8.1.6 (w zależności od tego, jaką wersję bazy zainstalowaliśmy) znajduje się dowiązanie symboliczne JRE. Wskazuje ono na JRE dostarczane razem z dystrybucja Oracla. Należy tak zmienić ten link, aby wskazywał on na JRE które zainstalowaliśmy w punkcie 3.
MAP:/u01/app/oracle/product/8.1.7:Y
gdzie MAP to sid bazy bazy danych. Jeśli na końcu znajduje się literka N należy zmienić ją na Y.ps -aux | grep $ORACLE_SID) możemy odpalić sqlplus pisząc:
sqlplus system/manager
lub
sqlplus scott/tiger
dbstart
lsnrctl start
oczywiście jako użytkownik oracle a nie root.Skrypt do startowania i zatrzymania Oracle dla RedHat-a.
Przy opracowywaniu tego dokumentu korzystałem z nastepujących źródeł:
Trigger lub funkcja PL/SQL próbuje przeglądać/modyfikować tabelę, która jest w trakcie modyfikacji przez wyrażenie, które wywołało trigger-a. Jeśli tablica jest w trakcie modyfikacji (przed zatwierdzeniem zmian), to w ogólności nie wiadomo, jaki jest jej stan i które rekordy zostały już zmodyfikowane, a które jeszcze nie. Dlatego też trigger nie może przeglądać/modyfikować tabeli, na której jest założony.
9.14 Mam problem z instalacją Oracle 8.1.x na komputerze z Pentium 4...
Problem występuje na komputerach z procesorem Pentium 4 w instalatorze wykorzystującym Sun JRE i Symantec JIT (Oracle Universal Installer for RDBMS 8.1.x). Należy zainstalować odpowiedni patch z Metalink-a albo:
TEMP)symcjit.dll i zamienic rozszerzenie np. na symcjit.oldSETUP.EXE z: \TEMP\install\win32 i zainstalować.9.15 Poszukuję tutoriali do Forms i/lub innego oprogramowania Oracle
Proszę zajrzeć pod adresy:9.16 Jakie wybrać narzędzie zamiast SQL*Plus-a?
9.17 Jak sprawdzić, który element procedury/funkcji PL/SQL wykonuje się najdłużej?
Potrzebny do tego jest pakiet DBMS_PROFILER. Jeśli na twojej bazie jeszcze go nie ma, trzeba go zainstalować:
-- instalacja DBMS_PROFILER CONNECT sys/password@service AS SYSDBA @$ORACLE_HOME/rdbms/admin/profload.sql CREATE USER profiler IDENTIFIED BY profiler DEFAULT TABLESPACE users QUOTA UNLIMITED ON users; GRANT connect TO profiler; CREATE PUBLIC SYNONYM plsql_profiler_runs FOR profiler.plsql_profiler_runs; CREATE PUBLIC SYNONYM plsql_profiler_units FOR profiler.plsql_profiler_units; CREATE PUBLIC SYNONYM plsql_profiler_data FOR profiler.plsql_profiler_data; CREATE PUBLIC SYNONYM plsql_profiler_runnumber FOR profiler.plsql_profiler_runnumber; CONNECT profiler/profiler@service @$ORACLE_HOME/rdbms/admin/proftab.sql GRANT SELECT ON plsql_profiler_runnumber TO PUBLIC; GRANT SELECT, INSERT, UPDATE, DELETE ON plsql_profiler_data TO PUBLIC; GRANT SELECT, INSERT, UPDATE, DELETE ON plsql_profiler_units TO PUBLIC; GRANT SELECT, INSERT, UPDATE, DELETE ON plsql_profiler_runs TO PUBLIC;
Jak to uruchomić? Bardzo prosto:
DECLARE profiler_n BINARY_INTEGER; BEGIN profiler_n := DBMS_PROFILER.start_profiler(run_comment => 'procedura GRZEJ_PROCESOR: ' || SYSDATE); GRZEJ_PROCESOR; -- testowana procedura profiler_n := DBMS_PROFILER.stop_profiler; END;
W zmiennej profiler_n znajdzie się numer, dzięki któremu możemy zidentyfikować dane
w tabelach użytkownika PROFILER:
SELECT runid,
run_date,
run_comment,
run_total_time
FROM plsql_profiler_runs
WHERE runid = &p_runid
ORDER BY runid;
Szczegółowe wyniki wykonania procedury otrzymamy dzięki zapytaniu:
SELECT u.runid,
u.unit_number,
u.unit_type,
u.unit_owner,
u.unit_name,
d.line#,
d.total_occur,
d.total_time,
d.min_time,
d.max_time
FROM plsql_profiler_units u
JOIN plsql_profiler_data d ON u.runid = d.runid AND u.unit_number = d.unit_number
WHERE u.runid = &p_id
ORDER BY u.unit_number, d.line#;
Najbardziej interesująca jest kolumna TOTAL_TIME, a LINE# powie, który wiersz w procedurze
wykonywał się najdłużej:
RUNID UNIT_NU UNIT_TYPE UNIT_OWNER UNIT_NAME LINE# TOTAL_OCCUR TOTAL_TIME MIN_TIME MAX_TIME
----- ------- --------------- ----------- ------------ ----- ----------- ---------- -------- --------
1 1 ANONYMOUS BLOCK <anonymous> <anonymous> 4 1 0 0 0
1 1 ANONYMOUS BLOCK <anonymous> <anonymous> 5 1 0 0 0
1 1 ANONYMOUS BLOCK <anonymous> <anonymous> 6 1 0 0 0
1 2 PROCEDURE SCOTT GRZEJ_PROCESOR 4 101 0 0 0
1 2 PROCEDURE SCOTT GRZEJ_PROCESOR 5 100 5601000 0 6048000
Która to linia w naszej procedurze - łatwo sprawdzić zapytaniem:
SELECT line || ' : ' || text FROM all_source WHERE owner = &UZYTKOWNIK AND type = 'PROCEDURE' AND name = &NAZWA_PROC; -- tu: GRZEJ_PROCESOR
Oracle Underground Frequently Asked Questions
Designer/2000 i Developer/2000
SQL*Plus - interaktywny kurs języka
Oracle - sztuczki i niebezpieczeństwa
Oprogramowanie i dokumentacja do Oracle
Wprowadzenie do PL/SQL i jezyk PL/SQL
Oprogramowanie serwera Oracle7 (PL/SQL, procedury, wyzwalacze)
Materiały o Oracle (SQL, PL/SQL, wyzwalacze, indeksy, Oracle Forms)
Artykuły o optymalizacji, administracji, bezpieczeństwie i innych zagadnieniach związanych z Oracle
Serwis dla programistów i administratorów Oracle
PLOUG - Polish Oracle User Group
The Knowledge Center for Oracle Professionals
Zawsze aktualna wersja rozdziału o PostgreSQL: http://pgsql.spsk1.pl/
Pytania:
10.1 Skąd wziąć?
10.2 Aktualna wersja?
10.3 Co potrafi?
10.4 Jak usunąć pole/zmienić jego typ?
10.5 Co to są języki proceduralne?
10.6 Ile jest języków proceduralnych i czym się różnią?
10.7 Który z języków proceduralnych jest najlepszy
10.8 U mnie nie działają procedury plXXXXXXX. Dlaczego?
10.9 Gdzie znajdę dokumentację do pl/pgsql? To co jest w manualach to
za mało.
10.10 Czy postgres obsługuje bloby/duże pliki binarne?
10.11 W moim psql'u nie działają klawisze kursora. Czemu?
10.12 Jak wywołuję psql'a z konta roota dostaję informację: psql:
FATAL 1: Database "root" does not exist in the system catalog. Dlaczego?
10.13 Jak zrobić, żeby dostęp do bazy dla konkretnego użytkownika
wymagał podania hasła (domyślnie jest bez haseł)?
10.14 Co i jak z polskimi literami?
10.15 Jak zainstalować/uruchomić PostgreSQL pod
Windows?
10.16 Jak zrobić AUTO_INCREMENT i czym się różnią sekwencje od seriali?
10.17 Jak pobrać pierwsze/następne/kolejne 5/10/15/??? wartości?
10.18 Jak zapewnić całkowity brak dostępu do bazy użytkownika A użytkownikowi B?
10.19 Jak czytać/zapisywać timestamp w postaci unixowej?
10.20 Jak zwracać z funkcji pl/pgsql'owych recordsety?
10.21 Jak wylistować tabele lub ich strukturę?
10.22 Jak zmienić nazwę pola(kolumny) w tabeli?
10.23 Jak wyeksportować zawartość bazy danych do pliku SQL, żeby przenieść ją z jednego serwera na drugi?
10.24 Jak zmusić PostgreSQLa do użycia indeksów na polach INT2 i INT8?
10.25 Czy istnieje sposób na import tabeli dbf do postgresql?
10.26 Jak zapisać warunek by nie zwracał uwagi na wielkość liter?
10.27 Czy są jakieś narzędzia do wizualnego projektowania baz PostgreSQL'a?
10.28 Jak szybko zliczyć ilość rekordów w tabeli? select count(*) jest taki wolny...
10.29 Jak obciąć część danych z danej typu timestamp?
10.30 Co to jest i do czego używać contrib'a?
10.31 Co jest w contribie?
10.32 Jakiego programu użyć aby administrować PostgreSQL'em?
Literatura
Linki
Odpowiedzi:
Oficjalny site: http://www.postgresql.org
Mirror w Polsce, np.: http://pgsql.profnet.pl/ lub ftp://sunsite.icm.edu.pl/site/postgres
Na 10-10-2004: 7.4.5, wersja beta: 8.0
Bardzo dużo. Implementacja standardu SQL dużo pełniejsza niż w konkurencyjnym MySQL'u. Ciut wolniejszy przy prostych bazach i małej ilości jednoczesnych użytkowników, ale "dostaje skrzydeł" przy większej komplikacji danych (duża ilość joinów) i dużej ilości jednoczesnych połączeń.
10.4 Jak usunąć pole/zmienić jego typ?
Jednyną realna szansą na zrobienie czegoś takiego (w wersjach < 7.3) jest zamiana całej tabeli. Przykład:
CREATE TABLE t (a text, b int4, c int4);
aby pole (b) usunąć:
SELECT a,c into temp_table FROM t; drop table t; alter table temp_table rename to t;
W wersjach postgresql'a od 7.3 wzwyż jest już zaimplementowana składnia:
alter table tt drop column b;
aby zmienić typ pola (c):
select a, b, c::int8 as c into temp_table from t; drop table t; alter table temp_table rename to t;
10.5 Co to są języki proceduralne?
Języki proceduralne są to specjalne języki programowania w których można tworzyć funkcje rozszerzające standardową funkcjonalność PostgreSQL'a. Przykładem takich funkcji może być np. funkcja zamieniająca dowolny ciąg znaków na inny, licząca silnię czy dowolną inną rzecz.
Ze względu na fakt, że języki te umożliwiają korzystanie ze zmiennych, wyrażeń warunkowych czy pętli są nieocenionym narzędziem pracy każdego zawodowego bazo-danowca.
10.6 Ile jest języków proceduralnych i czym się różnią?
Na chwilę obecną w PostgreSQL'u są 4 języki proceduralne:
Różnią się głównie składnią - bazującą na perlu, pythonie, tclu czy rozszerzonej składni sql'a (plpgsql) - zbliżonej do składni języka pl/sql z baz danych Oracle.
Dodatkowo funkcje w PostgreSQL'u można tworzyć także w C (funkcje skompilowane do postaci bibliotek dzielonych .so dołącza się do postgresql'a w czasie pracy), czy w samym język SQL (choć tu pole manewru jest mocno ograniczone. W planach jest stworzenie dodatkowych języków, np. plphp.
10.7 Który z języków proceduralnych jest najlepszy?
To jest pytanie na które nie ma dobrej odpowiedzi. Każdy język wyewoluował z czego innego i do czego innego się najlepiej nadaje. Można założyć, że najlepszym językiem będzie ten który bazuje na czymś co sie najlepiej zna. Dlatego jeśli znasz Python'a - najlepiej będzie Ci się pisało w plpythonie, jak twoim ulubieńcem jest perl, to bez wątpienia polubisz plperla. itp. Sam osobiście piszę większość rzeczy w plpgsql'u, pewne rzeczy w plperlu (funkcje obróbki tekstu), a część w C (gdy potrzebuję wydajności).
10.8 U mnie nie działają procedury plXXXXXXX. Dlaczego?
Domyślnie żaden język proceduralny nie jest obsługiwany. Aby włączyć możliwość tworzenia w nim funkcji należy (wszędzie poniżej zamień plXXXXXXX na odpowiednią nazwę wybranego przez siebie języka):
Stworzyć tzw. handler języka. Robi się to w ten sposób:
CREATE OR REPLACE FUNCTION plXXXXXXX_call_handler () RETURNS language_handler AS '/usr/local/pgsql/lib/plXXXXXXX.so' LANGUAGE 'C';Ewentualnie zamiast
'/usr/local/pgsql/lib/plXXXXXXX.so' należy podać
właściwą ścieżkę do pliku plXXXXXXX.so.
CREATE TRUSTED PROCEDURAL LANGUAGE 'plXXXXXXX' HANDLER plXXXXXXX_call_handler LANCOMPILER 'PL/XXXXXXX';
I od tej pory można już korzystać z dodatkowej funkcjonalności jaką dają procedury składowane. Zaleca się użycie powyższych dwóch komend będąc przyłączonym do bazy "template1". Dzięki temu, każda następna stworzona baza będzie miała od razu zadeklarowany język plpgsql. Istotne jest to, że nowe wersje PostgreSQL'a przychodzą razem ze skryptem createlang (skrypt shella). wykonuje się go tak:
createlang plXXXXXXX template1
Oczywiście zamiast template1 może być jakaś inna baza, ale idea pozostaje ta sama. ten skrypt tworzy zarówno funkcję-handler jak i sam język.
10.9 Gdzie znajdę dokumentację do pl/pgsql? To co jest w manualach to za mało.
Niestety dokumentacji na razie nie ma. Można co najwyżej poczytać kody
funkcji pl/pgsql użyte do tzw. regression test. Kody te są w pliku plpgsql.sql w
katalogu "src/test/regress/sql/" względem głównego katalogu źródeł
postgresa - testy te nie są standardowo instalowane w procesie instalacji binarek!
10.10 Czy postgres obsługuje bloby/duże pliki binarne?
Częściowo tak: istnieje coś takiego jak "Large Object".
Każdy zapisany tak "blob" jest zapisywany na dysk do oddzielnego pliku a w
tabeli są tylko i wyłącznie odnośniki do plików.
Należy wziąć pod uwagę, że nie istnieje w tej chwili możliwość łatwego
przeszukiwania czy indeksowania zawartości blobów.
Od wersji 7.1 jest możliwość przechowywania w tabelach danych o dowolnej wielkości (technologia T.O.A.S.T.). Pozostaje tylko pytanie: czy na pewno przechowywanie dużych, nieindeksowalnych plików w bazie danych jest słusznym rozwiązaniem?
10.11 W moim psql'u nie działają klawisze kursora. Czemu?
Aby w psql'u działała obsługa klawiszy kursora musisz mieć bibliotekę readline. Jeśli dodatkowo samodzielnie kompilujesz PostgreSQLa ze źródeł to (przynajmniej w czasie kompilacji) musisz posiadać także readline-devel. Jeśli po dograniu biblioteki do systemu nadal nie możesz używać klawiszy kursora musisz przekompilować PostgreSQLa. Po samodzielnym kompilowaniu możesz zajrzeć do pliku config.cache, gdzie powinny być takie wpisy:
(pgdba@depeszws[tty4]) 10:31:15 [~/src] $ cat config.cache | grep readline
ac_cv_header_readline_history_h=${ac_cv_header_readline_history_h=yes} ac_cv_header_readline_readline_h=${ac_cv_header_readline_readline_h=yes} ac_cv_search_readline=${ac_cv_search_readline=-lreadline}
Podstawową sprawą jest to by nie korzystać z systemu z konta roota. To raz. Natomiast co do samego problemu. System kont PostgreSQLa jest całkowicie oddzielony od systemu kont maszyny na której baza danych pracuje. Najważniejszą sprawą jest, że "główne" - czyli administracyjne konto w PostgreSQLu to nie jest root tylko postgres lub pgdba lub podobnie - nazwa jest identyczna z nazwą użytkownika systemu z którego był uruchomiony initdb (zazwyczaj jest to ten sam użytkownik z którego działa proces postmastera). Czyli aby wejść do psql'a z konta roota musisz wydać polecenie:
(root@depeszws[tty4]) 10:40:54 [~] $ psql -U pgdba
Dodatkowo pamiętaj, że psql domyślnie stara się podłączyć do bazy o nazwie takiej samej jak baza użytkownika, a sam fakt założenia użytkownika nie oznacza, że istnieje już dla niego baza.
Sposób autoryzacji (czy ma pytać o hasła czy nie) jest definiowany w pliku pg_hba.conf znajdującym się w katalogu z danymi PostgreSQLa. Na końcu tego pliku znajdziecie dwie takie linie:
local all trust host all 127.0.0.1 255.255.255.255 trust
Oznaczają one, że:
- dla połączeń lokalnych (local) - czyli takich gdzie łączymy się nie korzystająć
z socketów tcp/ip, dla dowolnej bazy (all) system ma przyjąć regułę niepytania o
hasło (trust).
- dla połączeń zdalnych, ale tylko z maszyny o adresie 127.0.0.1 (czyli z tego samego
komputera, ale przez sockety tcp/ip), też będzie ta sama reguła.
Aby to zmienić należy zmienić ostatnie słowo (trust) na "password" lub
"crypt" (różnią się one metodą przesyłania hasła. Np. zapis:
host all 148.81.17.60 255.255.255.0 password
Oznacza, że osoby łączące się z serwera o ip 148.81.17.60 oraz z całej klasy C
(czyli naprawdę adres ip musi być 148.81.17.*) muszą podać hasło aby dostać się do
dowolnej bazy.
A zapis:
host template1 148.81.17.60 255.255.255.0 password
(oczywiście bez poprzedniego zapisu) oznacza, że te same osoby będą mogły teraz
dostać się tylko do bazy template1 i będą musiały podać hasło.
Przy pisaniu reguł dostępu należy pamiętać o kolejności. Użyta zostanie ta reguła
która jest pierwsza w pliku i pasuje do sytuacji. Dlatego zapis ten jest bez sensu:
local all trust host all 127.0.0.1 255.255.255.255 trust local template1 password host template1 127.0.0.1 255.255.255.255 password
a aby uzyskać to co się chce zapis powinien być taki:
local template1 password host template1 127.0.0.1 255.255.255.255 password local all trust host all 127.0.0.1 255.255.255.255 trust
10.14 Co i jak z polskimi literami?
Wbrew wszelkim obawom uzyskanie prawidłowej obsługi polskich liter jest trywialne. Aha. poniższy tekst tyczy się tylko i wyłącznie środowisk U*IX'owych - w windows jest to jakaś magia.
Przede wszystkim czego nie potrzebujesz:
Potrzebujesz za to:
Najprostszą i najskuteczniejszą metodą jest własnoręczna kompilacja. Czemu?
proste: nigdy nie mamy pewności z jakimi opcjami zostało skompilowane to co dostajemy w
paczce z binarkami. Przebiegu kompilacji nie będę opisywał (każdy chyba czytał plik
INSTALL???), ale:
na etapie kompilacji musimy włączyć locale. robi się to tak:
./configure --enable-locale
i to w zasadzie wszystko. oczywiście configre'owi można podać także stado innych parametrów, ale z punktu widzenia przeciętnego zjadacza ogonków to co powyżej jest tym najistotniejszym. Po kompilacji i zainstalowaniu czas na "initdb". już w tym momencie polecam mieć ustawione locale (do wersji 7.1 locale trzeba było mieć ustawione tylko w czasie uruchamiania postmastera, ale w 7.1 i później należy locale ustawiać przy initdb) czyli:
export LC_COLLATE=pl_PL export LC_CTYPE=pl_PL export LC_MESSAGES=pl_PL export LC_MONETARY=pl_PL export LC_NUMERIC=pl_PL export LC_TIME=pl_PL
Powyższe zadziała jak używasz bash'a lub czegoś kompatybilnego. Jeśli używasz
innego shella - poradź się swojego lokalnego guru jak się w nim ustawia zmienne
środowiskowe.
Ponieważ zmienne te się ogólnie rzecz biorąc przydają także po initdb polecam
wpisanie powyższego do pliku ~/.bash_profile lub ~/.bashrc lub odpowiedniego -
wywoływanego przy zalogowaniu się na konto.
Po wykonaniu initdb z ustawionymi zmiennymi LC_* i wystartowaniu postmastera (zmienne LC_*
nadal powinny być ustawione) wszystko powinno działać jak trzeba.
10.15 Jak zainstalować/uruchomić PostgreSQL pod Windows?
Pełno informacji na ten temat znajdziesz na
tej stronie. Sam Windows nie używam. Jak chcesz aby było tu coś więcej na ten temat - napisz i podeślij.
Możesz ściągnąć gotową, skompilowaną wersję PostgreSQL'a dla Windows (adres poniżej). Pliki tu umieszczone
są przygotowane przez Ronalda Kuczka.
http://www.depesz.pl/people/depesz/files/PostgreSQL-Windows/
10.16 Jak zrobić AUTO_INCREMENT i czym się różnią sekwencje od seriali?
Aby stworzyć pole typu AUTO_INCREMENT należy zastosować jedną z dwóch metod:
SERIAL
SEKWENCJA (SEQUENCE)
Jak się używa?
SERIAL:
depesz=# CREATE TABLE a (id serial, pole text);
NOTICE: CREATE TABLE will create implicit sequence 'a_id_seq' for SERIAL column 'a.id'
NOTICE: CREATE TABLE/UNIQUE will create implicit index 'a_id_key' for table 'a'
CREATE
depesz=# INSERT INTO a (pole) VALUES ('wartość pierwsza');
INSERT 529488 1
depesz=# INSERT INTO a (pole) VALUES ('wartość druga');
INSERT 529489 1
depesz=# SELECT * FROM a;
id | pole
---+------------------
1 | wartość pierwsza
2 | wartość druga
(2 rows)
SEQUENCE:
depesz=# CREATE SEQUENCE b_id;
CREATE
depesz=# CREATE TABLE b (id int4 not null default nextval('b_id'), pole text);
CREATE
depesz=# INSERT INTO b (pole) VALUES ('wartość pierwsza');
INSERT 529536 1
depesz=# INSERT INTO b (pole) VALUES ('wartość druga');
INSERT 529537 1
depesz=# SELECT * FROM b;
id | pole
---+------------------
1 | wartość pierwsza
2 | wartość druga
(2 rows)
Czyli jak widać obie metody dają mniej więcej to samo. W dodatku wewnętrznie użycie typu serial powoduje zdefiniowanie sekwencji i stworzenia bardzo podobnej struktury jak to co pokazałemw drugim przykładzie. Jakie są więc różnice? - serial definiuje automatycznie indeks unikalny na polu - w serialu nie mamy wpływu na nazwę utworzonej sekwencji - w serialu nie możemy wpływać na inne parametry sekwencji (skok, wartość początkowa czy końcowa) Tak więc: jeśli potrzebujesz tylko licznika od 1 do około 2 miliardów: używaj seriala. Jeśli jednak potrzebujesz czasem mieć licznik liczący w dół (od -1 do -dwóch miliardów), albo przeskakujący co dwie lub więcej liczb to używaj sekwencji. Nie zapomnij jednak, że niezależnie czego użyjesz w obu przypadkach powstaje sekwencja, która nie zniknie po usunięciu tabeli.
10.17 Jak pobrać pierwsze/następne/kolejne 5/10/15/??? wartości?
Zakładając, że jest SELECT typu:
SELECT * FROM tabela;
Aby móc pobierać wiersze porcjami należy po pierwsze zdefiniować sposób sortowania. W najprostszej wersji będzie to:
SELECT * FROM tabela ORDER BY OID;
w innych np.:
SELECT * FROM tabela ORDER BY pole;
Następnie definiujemy ile chcemy wierszy uzyskać:
SELECT * FROM tabela ORDER BY pole LIMIT 5;
Wyciągnie to z bazy 5 pierwszych rekordów. Aby wyciągnąć kolejne rekordy należy zrobić:
SELECT * FROM tabela ORDER BY pole LIMIT 5 OFFSET 5;
Wyświetli to pięć rekordów poczynając od rekordu o numerze 6 (pominie 5).
10.18 Jak zapewnić całkowity brak dostępu do bazy użytkownika A użytkownikowi B?
Bez stosowania żadnych sztuczek możliwe jest tylko i wyłączenie odebranie innym użytkownikom praw do odczytu, zapisu, itp. istniejących tabel, natomiast nie można zakazać im w ogóle dostępu do baz innych użytkowników - oraz np. zakładania tam własnych tabel.
O ile w/g mnie nie jest to problem, o tyle części ludzi to przeszkadza. Skonfigurowanie tego polega na zmianie zawartości pliku pg_hba.conf i pg_ident.conf.
Przykład (pg_hba.conf):
local all reject local sameuser password host sameuser 127.0.0.1 255.255.255.255 password host all 127.0.0.1 255.255.255.255 ident postgres
Przykład (pg_ident.conf):
#MAP IDENT POSTGRES USERNAME postgres postgres postgres
Po kolei (plik pg_hba.conf):
Wpis w pliku pg_ident.conf oznacza, że mapa postgres definiuje, że użytkownik łączący się z konta postgres będzie widziany wewnętrznie jako konto postgres.
I już. Powinno działać.
Powyższe rozwiązanie (nieprzetestowane przeze mnie) przetłumaczyłem (w skrócie) z listu na grupę pgsql-admin (autor: jkm(at)patriot.net (Kevin McFadden)).
10.19 Jak czytać/zapisywać timestamp w postaci unixowej?
Aby dostać czas w postaci unix-timestamp, należy odczytać go (czas) przez:
# select extract(epoch from now()); date_part ------------ 1003126751 (1 row)
Natomiast aby przekształcić z powrotem taki timestamp na timestamp postgresql'owy wystarczy wiedzieć (pamiętać), że unix-timestamp jest to po prostu liczba sekund od "epoch". czyli poniższe zapytanie zadziała dokładnie tak jak chcemy:
# select 'epoch'::timestamp + interval('999999999 seconds');
?column?
------------------------
2001-09-09 03:46:39+02
(1 row)
10.20 Jak zwracać z funkcji pl/pgsql'owych recordsety?
Do wersji 7.1.x jedyną możliwością było tworzenie tabeli tymczasowej, insert do niej i odczyt z zewnątrz. Brzydkie. Od wersji 7.2 istnieje możliwość zwracania z funkcji pl/pgsql'owych kursorów. Oczywiście wymaga to używania transakcji (kursory działają tylko wewnątrz transakcji), ale nie jest to przecież wielki problem. Czyż nie? Zaczynamy: robimy tabelę:
# CREATE TABLE tabela ( # id INT4, # name TEXT # ); CREATE
Wstawiamy tam kilka testowych rekordów:
# INSERT INTO tabela VALUES (1, 'bart'); INSERT 48525 1 # INSERT INTO tabela VALUES (2, 'lisa'); INSERT 48526 1 # INSERT INTO tabela VALUES (3, 'marge'); INSERT 48527 1 # INSERT INTO tabela VALUES (4, 'homer'); INSERT 48528 1 # INSERT INTO tabela VALUES (5, 'maggie'); INSERT 48529 1
No i nasza magiczna funkcja:
# CREATE FUNCTION funkcja(INTEGER) RETURNS REFCURSOR AS ' # DECLARE # num ALIAS FOR $1; # cur REFCURSOR; # BEGIN # cur:=''new_cursor''; # OPEN cur FOR SELECT * FROM tabela WHERE id >= num ORDER BY id; # RETURN cur; # END; # ' LANGUAGE 'plpgsql';
(oczywiście nazwa kursora (tu: new_cursor) może być dowolna). No to testujemy:
# BEGIN; BEGIN # select funkcja(3); funkcja ------------ new_cursor (1 row) # fetch from new_cursor; id | name ----+------- 3 | marge (1 row) # fetch from new_cursor; id | name ----+------- 4 | homer (1 row) # fetch backward 2 from new_cursor; id | name ----+------- 3 | marge (1 row) # fetch ALL from new_cursor; id | name ----+-------- 3 | marge 4 | homer 5 | maggie (3 rows) # close new_cursor; CLOSE # end; COMMIT
Działa. Oczywiście (jak już nadmieniałem) działa to tylko w postgresie 7.2 i wyższych. Powyższy kod jest autorstwa Tomka Zielonki - ja naniosłem tam tylko drobne poprawki (możliwość zwracania kursora bez przekazywania go jako parametru).
Począwszy od wersji 7.3 można już zwracać z funkcji bezpośrednio recordsety. Służy do tego konstrukcja return NEXT:
CREATE OR REPLACE FUNCTION test_srf() RETURNS SETOF RECORD AS '
DECLARE
temprec RECORD;
BEGIN
for temprec in SELECT oid, lanname FROM pg_language loop
RETURN next temprec;
END loop;
RETURN;
END;
' language 'plpgsql';
SELECT * FROM test_srf() x(pole1 oid, nazwa name);
Zwrócić należy uwagę na pusty RETURN kończący funkcję. Dodatkowo należy pamiętać, że select'y z funkcji muszą zawierać alias pod jakim dane z funkcji mają być widziane (x) oraz specyfikacje tabel (nazwy pól i typy danych).
10.21 Jak wylistować tabele lub ich strukturę?
Aby wylistować tabele (widoki, sekwencje, funkcje) należy użyć w psql'u komendy \d lub \d gdzie parametr to np. t, s, v, S, f czy inne. Jeśli natomiast potrzebujesz zrobić to ze swojego programu bez pośrednictwa psql'a, to uruchom psql'a z opcją -E po czym wydaj interesującą cię komendę. Poza wynikiem działania komendy dostaniesz także zapytanie jakie jest wysyłane do bazy aby pokazać ci te informacje. np:
$ psql template1 -E
Password:
********* QUERY **********
SELECT usesuper FROM pg_user WHERE usename = 'pgdba'
**************************
Welcome to psql, the PostgreSQL interactive terminal.
Type: \copyright for distribution terms
\h for help with SQL commands
\? for help on internal slash commands
\g or terminate with semicolon to execute query
\q to quit
template1=# \d
********* QUERY **********
SELECT c.relname as "Name",
CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'i' THEN 'index'
WHEN 'S' THEN 'sequence' WHEN 's' THEN 'special' END as "Type",
u.usename as "Owner"
FROM pg_class c LEFT JOIN pg_user u ON c.relowner = u.usesysid
WHERE c.relkind IN ('r','v','S','')
AND c.relname !~ '^pg_'
ORDER BY 1;
**************************
List of relations
Name | Type | Owner
------------+------+--------
hdl_custom | view | depesz
(1 row)
10.22 Jak zmienić nazwę pola(kolumny) w tabeli?
Należy użyć komendy
ALTER TABLE tabela RENAME COLUMN nazwa_pola TO nowa_nazwa_pola;
Aby wyeksportować bazę danych do pliku .sql wystarczy wydac polecenie:
pg_dump > dump.sql
Oczywiście w trakcie wykonywania tej operacji trzeba mieć dostęp do bazy danych na poziomie administratora.
Aby natomiast skopiować tak wyeksportowane dane do innej bazy wystarczy:
- stworzyć docelową bazę danych: CREATE DATABASE docelowa_baza;
- wykonać polecenie: psql -i dump.sql
To wszystko. Po tym baza powinna być już skopiowana.
10.24 Jak zmusić PostgreSQLa do użycia indeksów na polach INT2 i INT8?
Zakładając, że masz już indeks na polu które jest typu INT2 lub INT8, wykonujesz regularne vacuum analyze, danych w tabeli jest odpowiednio dużo i postgresql nadal nie wykorzystuje index scanów przy wyszukiwaniu:
SELECT * FROM tabela WHERE pole = 12;
musisz wymusić na nim odpowiednie rzutowanie podanej liczby (12). Robi się to tak:
SELECT * FROM tabela WHERE pole = 12::int8;
lub tak:
SELECT * FROM tabela WHERE pole = CAST(12 as int8);
Przyczyna takiego zachowania postgresa leży w fakcie, że domyślnym typem danych na jaki są rzutowane podane liczby jest int4. Przy polu typu int2 czy int8 musi zostać zrobiona później odpowiednia konwersja, a liczby skonwertowane nie są już indeksowane.
10.25 Czy istnieje sposób na import tabeli dbf do postgresql?
Poniższy tekst jest kompilacją wypowiedzi poniższych osób na grupie dyskusyjnej
pl.comp.bazy-danych w marcu 2002:
<newbie_2002 <at> poczta.onet.pl>
Sławomir Szyszło <slaszysz <at> poczta.onet.pl>
Ronald Kuczek <ronald <at> breitenbach.pl>
Sylwester Szady <sszady <at> zke.com.pl>
Aby przenieść dane z plików .dbf do PostgreSQL'a można się posłużyć jedną z poniższych metod:
10.26 Jak zapisać warunek by nie zwracał uwagi na wielkość liter?
Jeśli chcesz po prostu sprawdzić, czy dane pole jest równe jakiemuś stringowi, ale bez sprawdzania wielkości liter to zrób tak:
CREATE INDEX nazwa_indeksu ON nazwa_tabeli (upper(nazwa_pola));
i potem wyszukiwanie:
SELECT * FROM nazwa_tabeli WHERE upper(nazwa_pola) = upper('jakiś ciąg znaków');
Jeśli natomiast chcesz wyszukiwać używając operatorów LIKE lub ~ (tylda - do
wyrażeń regularnych); to użyj ich wersji odpornych na wielkość liter:
SELECT * FROM nazwa_tabeli WHERE nazwa_pola ILIKE 'jakiś%'; SELECT * FROM nazwa_tabeli WHERE nazwa_pola ~* '^jakiś';
Należy jedynie zwrócić uwagę, na to, że operator ILIKE pojawił się dopiero od
wersji 7.1 PostgreSQL'a, dla wersji wcześniejszych należy używać albo
operatora ~* lub funkcji upper/lower.
10.27 Czy są jakieś narzędzia do wizualnego projektowania baz PostgreSQL'a?
Pełną lista programów wspierających graficzne tworzenie baz danych (UML) można
znaleźć na techdocs'ach 10.28 Jak szybko zliczyć ilość rekordów w tabeli? select count(*) jest taki wolny... Pytanie wbrew pozorom nie jest trywialne. Jeśli zrobiłeś już vacuum tabeli
którą chcesz zliczyć i nadal jest to wolne to pora się rozejrzeć za dopalaczem.
Jedyną sensowną i realną metodą zrobienia takiego czegoś jest: Kodu przykładowych triggerów nie będę zamieszczał - można to potraktować
jako wprawkę z programowania w językach proceduralnych.
Zwrócić jednakże należy uwagę na 3 rzeczy: 10.29 Jak obciąć część danych z danej typu timestamp? Należy użyć wbudowanej funkcji to_char. np. tak: 10.30 Co to jest i do czego używać contrib'a? contrib jest to podkatalog w źródłach PostgreSQL'a. Zawiera on dodatkowe rozszerzenia
funkcji bazy danych. Standardowo w procesie kompilacji bazy danych, contrib nie
jest ruszany - jeśli coś stamtąd chcesz musisz to sobie skompilować samodzielnie.
W contribie znajduje się wiele bardzo przydatnych programów i rozszerzeń, w związku
z czym każdy kto chce robić coś poważnego z PostgreSQL'em powinien znać przynajmniej
częściowo to co contrib oferuje. W miarę możliwości postaram się tu opisać wszystkie moduły contriba. Na początek
te których sam używam:
depesz=# select now(), to_char(now(),'YYYY-MM-DD HH24:MI:SS'), to_char(now(),'Day, DD of Month YYYY BC, HH AM');
now | to_char | to_char
------------------------------+---------------------+-------------------------------------------
2002-09-10 10:09:05.15999+02 | 2002-09-10 10:09:05 | Tuesday , 10 of September 2002 AD, 10 AM
(1 row)
miscutil
3 drobne, ale użyteczne funkcje:
pgbench
Program do testowania wydajności postgresql'a. wielokrotnie krytykowany,
lecz w chwili obecnej jedyny *sensowny* test wydajnościowy postgresql'a (istnieje
jeszcze osdb, ale na razie do niczego się nie nadaje - może niedługo)
pgcrypto
Fenomenalna biblioteka dostarczająca funkcji szyfrujących, deszyfrujących i haszujących
przy użyciu wielu algorytmów. m.in. szyfrowanie haseł md5, haseł crypt.
pgstattuple
Jedna funkcja zwracająca w ultra-przejrzystej formie statystyki nt. danej tabeli.
Pozwala to np. podjąć decyzję czy tabelę warto już vacuumować, czy nie i co ogólnie w niej "siedzi". Przykład:
# select * from pgstattuple('bleble');
-[ RECORD 1 ]------+-------
table_len | 106496
tuple_count | 591
tuple_len | 87468
tuple_percent | 82.13
dead_tuple_count | 97
dead_tuple_len | 14356
dead_tuple_percent | 13.48
free_space | 1608
free_percent | 1.51
tablefunc
Kilka funkcji, które w założeniach miały pokazać do czego można używać srf'ów
(set returning functions).
ltree
Fenomenalnie szybka oraz posiadająca wiele możliwości biblioteka do zapisywania
drzew w sql'u. pozwala np. na *indeksowane* wyszukiwanie drzewa takim kluczem:
Top.*{0,2}.sport*@.!football|tennis.Russ*|Spain
co oznacza, że:
To jest akurat bardzo wydumany przykład, jednakże także standardowo potrzebne
rzeczy ltree załatwia prosto i co najważniejsze: bardzo szybko.
tsearch
Bardzo szybka (choć i tak wolniejsza niż kod rolanda) implementacja full text
indexing/searching w postgresql'u. Testy przeprowadzone przez ludzi z list
postgresql'owych dowodzą, że w niektórych przypadkach jest ona o 300 *razy*
szybsza niż drugi fti/s contribowy - fulltextsearch.
Jeśli potrzebujecie wyszukiwania w tekstach, a macie tych tekstów naprawdę dużo
- polecam tsearcha. Będziecie naprawdę zaskoczeni wydajnością.
dbsize
Proste narzędzie podające wielkość wskazanej tabeli lub całej bazy. Idealne np.
dla adminów, którzy w oparciu o to mogą zbudować system quoty dla postgresql'a.
Jakiego programu użyć aby administrować PostgreSQL'em?
Większość znanych mi zaawansowanych programistów i administratorów PostgreSQL'a
używa po prostu psql'a - dostarczanego wraz z bazą danych, tekstowego narzędzie
o naprawdę wielkich możliwościach.
Jeśli jednak potrzebujesz czegoś graficznego (klikalnego) to pozwolę sobie zwrócić
twoją uwagę na dwa produkty:
Oficjalna stron projektu PostgreSQL
DevShed - Instalacja PostgreSQL
Tutorial do PostgreSQL'a 7.1.3, przetłumaczony na polski przez A.L.E.C.'a.
Pytania:
11.1 Co to jest Sybase ASE i Sybase ASA?
11.2 Skąd wziąć?
11.3 Sybase ASE
11.3.1 Informacje o serwerze i bazach danych.
11.3.2 Informacje o kolumnach i ich typach w tabeli.
11.3.3 Dla zadanej nazwy zależności wskazuje tabela.klucz i tabreferencyjna.klucz
11.3.4 Wyszukiwanie w bazie tabel/kolumn o podanej nazwie.
11.4.5 Polecenia do usuwania zależności dla zadanej tabeli
11.3.6 Sprawdzanie logu transakcji.
11.3.7 Szybkie kasowanie logu transakcji.
11.3.8 Sprawdzanie procesów na serwerze.
11.3.9 Uruchamianie isql.
11.3.10 Kopiowanie zawartości tabel do/z pliku.
11.4 Sybase ASA
Odpowiedzi:
11.1 Co to jest Sybase ASE i Sybase ASA?
Najbardziej popularnymi serwerami baz danych są: Sybase ASE - Sybase Adaptive Server Enterprise, oraz Sybase ASA - Sybase Adaptive Server Anywhere (wchodzi w skład pakietu SQL Anywhere Studio). Ze strony11.3.1 Informacje o serwerze i bazach danych
-- Aktualnie wybrany serwer: 1> SELECT @@servername 2> go -- Informacja o wersji serwera: 1> SELECT @@version 2> go -- Aktualnie wybrana baza danych: 1> SELECT db_name() 2> go -- Informacja o dostępnych bazach danych na serwerze: 1> EXEC sp_helpdb 2> go
11.3.2 Informacje o kolumnach i ich typach w tabeli.
1> EXEC sp_columns TableName 2> go --lub 1> SELECT object_name(id)||'.'||name 2> FROM SysColumns 3> WHERE object_name(id) = 'TableName' 4> ORDER BY id,colid 5> go
11.3.3 Dla zadanej nazwy zależności wskazuje tabela.klucz i tabreferencyjna.klucz
SELECT object_name(SR.ConstrID) AS Referencja, object_name(SR.TableID)||'.'||SC.name AS Tabela, object_name(SR.RefTabID)||'.'||SC2.Name AS "Tabela Ref" FROM SysReferences SR INNER JOIN SysColumns SC ON SC.ID = SR.TableID INNER JOIN SysColumns SC1 ON SC1.ID = SR.RefTabID AND SC1.ColID = SR.KeyCNT INNER JOIN SysColumns SC2 ON SC2.ID = SR.RefTabID AND (SC2.ColID = SR.RefKey1 AND SC.ColID = SR.fokey1 OR SC2.ColID = SR.RefKey2 AND SC.ColID = SR.fokey2 OR SC2.ColID = SR.RefKey3 AND SC.ColID = SR.fokey3 OR SC2.ColID = SR.RefKey4 AND SC.ColID = SR.fokey4 OR SC2.ColID = SR.RefKey5 AND SC.ColID = SR.fokey5 OR SC2.ColID = SR.RefKey6 AND SC.ColID = SR.fokey6 OR SC2.ColID = SR.RefKey7 AND SC.ColID = SR.fokey7 OR SC2.ColID = SR.RefKey8 AND SC.ColID = SR.fokey8 OR SC2.ColID = SR.RefKey9 AND SC.ColID = SR.fokey9 OR SC2.ColID = SR.RefKey10 AND SC.ColID = SR.fokey10 OR SC2.ColID = SR.RefKey11 AND SC.ColID = SR.fokey11 OR SC2.ColID = SR.RefKey12 AND SC.ColID = SR.fokey12 OR SC2.ColID = SR.RefKey13 AND SC.ColID = SR.fokey13 OR SC2.ColID = SR.RefKey14 AND SC.ColID = SR.fokey14 OR SC2.ColID = SR.RefKey15 AND SC.ColID = SR.fokey15 OR SC2.ColID = SR.RefKey16 AND SC.ColID = SR.fokey16 ) WHERE object_name(SR.ConstrID) = '@CONSTRAINT_NAME'
11.3.4 Wyszukiwanie w bazie tabel/kolumn o podanej nazwie.
--Szukamy wszystkich tabel zawierajacych kolumn %KolumnaID% SELECT object_name(id)||'.'||name FROM SysColumns WHERE name LIKE '%KolumnaID%' ORDER BY object_name(id) --Szukamy wszystkich tabel/obiektow w bazie o nazwie %Tabela% EXEC sp_tables '%Tabela%' --lub SELECT name FROM SysObjects WHERE name like '%Tabela%' AND type = 'U' -- U = UserTables ORDER BY name
11.3.5 Polecenia do usuwania zależności dla zadanej tabeli @TableName
1> SELECT 'ALTER TABLE '||SO.name||' DROP CONSTRAINT '||object_name(SR.ConstrID)||'' from SysReferences SR 2> INNER JOIN SysObjects SO 3> ON SO.ID = SR.RefTabID 4> WHERE SO.name='@TableName' 5> go
11.3.6 Sprawdzanie logu transakcji
Istnieje wbudowana procedura sp_helpsegment, która dla parametru logsegment przedstawia aktualny stan logu transakcji:
1> EXEC sp_helpsegment logsegment 2> go
11.3.7 Szybkie kasowanie logu transakcji.
Jeżeli zdarzy się sytuacja, że log transakcji zostanie przepełniony, wówczas można (nie jest polecane)
wyczyścić log przy z opcją truncate_only:
1> DUMP TRANSACTION DatabaseName WITH truncate_only 2> go
11.3.8 Sprawdzanie uruchomionych procesów na serwerze.
1> SELECT spid,status,program_name,cmd,loggedindatetime,ipaddr,loginame=convert(char(12), 2> suser_name(suid)),hostname,dbname=convert(char(10),db_name(dbid)),cpu,physical_io,memusage 3> FROM master..sysprocesses 4> ORDER BY loggedindatetime desc -- sprawdzanie procesów, które uruchomione są przez wiecej niż podana wartość @Value (zadana w sekundach): 1> SELECT 2> 'TIMES',convert(varchar,datediff(hour,loggedindatetime,getdate()))|| 3> '.'||convert(varchar,(datediff(minute,loggedindatetime,getdate()))%60)|| 4> '.'||convert(varchar,(datediff(second,loggedindatetime,getdate()))%60) AS "Hours.Minutes.Seconds", 5> spid,status,program_name,cmd,loggedindatetime,ipaddr,loginame=convert(char(12), suser_name(suid)), 6> hostname,dbname=convert(char(10),db_name(dbid)),cpu,physical_io,memusage 7> FROM master..sysprocesses 8> WHERE datediff(second,loggedindatetime,getdate()) > @Value 9> ORDER BY loggedindatetime desc
11.3.9 Uruchamianie isql'a [unix].
isql (Interactive SQL) znajduje się w $SYBASE/OCS-12_5/bin/isql
Atrybuty przełączników są pisane dużymi literami.
-U USER
-P PASSWORD
-S SERVER
-D DATABASE
-E EDITOR
-c SEPARATOR
-p uaktywnia statystyki : Execution Time oraz Clock Time
-e Zawiera wszystkie polecenia isql w wynikach
-n Usuwa numerowania i znaki zachęty (zwykle używane w generowaniu wyników do pliku)
-i InputFile // lub < InputFile
-o OutputFile // lub > OutputFile
Uwaga 1 : Plik InputFile powinien zawierać separator(y) poleceń w nowych wierszach.
Uwaga 2 : Nie jest możliwe połączenie się isql'em bez podania nazwy serwera // :).
Uwaga 3 : Jeżeli isql zostanie wywołany bez określenia bazy danych, to domyślnie połączy się z domyślną bazą (zwykle jest to mater).
Uwaga 4 : Polecenie
1> use database_name 2> go
zmienia domyślnie używaną bazę danych.
Uwaga 5 : Czasy przy statystykach podawane są w ms.
Np.:
Uruchamia isql z włączonymi statystykami i edytorem joe
# $SYBASE/OCS-12_5/bin/isql -Uuser_name -Sserver_name -Ddatabase_name -p -Ejoe
Uruchamia isql dla poleceń(nia) z pliku InputFile.sql i generuje wyniki do pliku output.txt.
Plik wyjściowy zawiera poza wynikami, wszystkie komendy, statystyki oraz brak numerowania wierszy.
Oba poniższe wywołania są równoważne.
# $SYBASE/OCS-12_5/bin/isql -Uuser_name -Sserver_name -Ddatabase_name -i InputFile.sql -o output.txt -e -n -p
# $SYBASE/OCS-12_5/bin/isql -Uuser_name -Sserver_name -Ddatabase_name < InputFile.sql > output.txt -e -n -p
11.3.10 Kopiowanie zawartości tabel do/z pliku.
Za pomocą programu bcp możliwe jest kopiowanie danych z tabeli do zadanego pliku, w formacie określonym przez użytkownika.
-c uaktywnia tryb znakowy -t SEPARATOR
Np.:
Kopiuje tabelę TABELA z bazy danych BAZA na serwerze SERWER do pliku out_TABELA.txt, z separatorem %
# bcp BAZA.dbo.TABELA out out_TABELA.txt -SSERWER -Uvibart -c -t "%"
Aby uzyskać informację o danej tabeli w postaci database_name.owner.table_name, najlepiej wykorzystać poniższe zapytanie:
SELECT db_name()||"."||user_name(uid)||"."||name FROM SysObjects WHERE name = "ObjectName"
W celu importu danych do bazy z pliku wystarczy wydać polecenie:
# bcp BAZA.dbo.TABELA in out_TABELA.txt -SSERWER -Uvibart -c -t "%"
11.3.11 Sprawdzanie akutalnie wykonywanego polecenia SQL.
Dla procesu o ID = @SPID (w celu sprawdzenia procesu można wykorzystać zapytanie z punktu 11.3.8)
1> dbcc traceon(3604) 2> go 1> dbcc sqltext(@SPID) 2> go 1> dbcc traceoff(3604) 2> go
Informacje o produktach i oprogramowaniu do Sybase
ASE dla Linuxa FAQ (ASE on Linux FAQ)
Sybase ISUG FAQ (Intenational Sybase Users Group)
BDA Devil - zbior informacji i ciekawych tool'i
Blink Public Folder - Portal do informacji na temat Sybase
Sybase ASE Tools & Documentation by Rob Verschoor
Pytania:
12.1 Dlaczego nie działa SET COLLATE TO "POLISH"
12.2 Jak pozbyć się komunikatu "Source is out of date"?
12.3 Jak zamknąć program krzyżykiem bez komunikatu "Cannot quit Microsoft Visual FoxPro"?
12.4 Jak pozbyć się komunikatu "The control is read-only" przy wciśnięciu klawisza na gridzie ?
12.5 Jak sprawdzić ilość stron w raporcie?
12.6 Jak wyłączyć okienko z pytaniem o stronę kodową?
12.7 Jak sprawdzić, czy katalog istnieje?
12.8 Ile znaków dopuszcza polecenie "sqlexec"?
12.9 Jak uniknąć ostrzeżenia o istnieniu indeksu, tagu przy ponownym indeksowaniu INDEX ON ... TAG?
Odpowiedzi:
12.1 Dlaczego nie działa SET COLLATE TO "POLISH"
Należy zainstalować ServicePack co najmniej 3.
12.2 Jak pozbyć się komunikatu "Source is out of date"?
set development on
12.3 Jak zamknąć program krzyżykiem bez komunikatu "Cannot quit Microsoft Visual FoxPro"?
Znaleźć w dokumentacji "on shutdown"
12.4 Jak pozbyć się komunikatu "The control is read-only" przy wciśnięciu klawisza na gridzie?
set notify off
12.5 Jak sprawdzić ilość stron w raporcie?
Jest _PAGENO, która mówi na jakiej aktualnie jesteśmy stronie raportu. Jednak przed puszczeniem jej wartość końcowa nie jest znana. Jeżeli raport nie jest czasochłonny, to można puścić "w próżnię", przeczytać _PAGENO i puścić właściwy.
12.6 Jak wyłączyć okienko z pytaniem o stronę kodową?
SET CPDIALOG OFF
12.7 Jak sprawdzić, czy katalog istnieje?
W VFP3 lub fox for dos, za pomocą funkcji "adir". W wersjach > 3 : directory()
12.8 Ile znaków dopuszcza polecenie "sqlexec" ?
Co najmniej tyle ile ile zmieści zmienna znakowa, czyli 64kb. Jeśli pojawi się komunikat typu "command contains unrecognized phraze/keyword", zwykle pomaga "pocięcie" zapytania na kawałki (np. a=a+'...).
Jak uniknąć ostrzeżenia o istnieniu indeksu, tagu przy ponownym indeksowaniu INDEX ON ... TAG?
SET SAFETY OFF.
Polecenie to wyłącza również komunikaty przy próbie nadpisania pliku, zap-owania i paru innych operacjach.
Sporo materiałów w postaci plików PDF, niestety w języku angielskim
http://www.progress.com/v9/documentation/start.htm#dbcoll
Lista dyskusyjna Progress'a
http://www.zeto.bydgoszcz.pl/progress/
Polski Klub Użytkowników Systemu Progress
http://pluton.pol.lublin.pl/pugpl/
Na tychże stronach kurs PROGRESS od A do Z, czyli to co znajdziesz w książce
wymienionej poniżej.
Projekt possenet.org
http://www.possenet.org/
Literatura:
I. Relacyjne
II. Obiektowe
III. XML
eXist - Open Source native XML database
III. Embedded
V. Nieaktywne projekty
3. Gdzie mogę znaleźć bazę polskich kodów pocztowych?
Bazy kodów pocztowych, miejscowości, jednostek terytorialnych są oferowane przez:
- Hoga.pl: miejscowości, województwa, powiaty, gminy, kody pocztowe, ulice, liczba ludności,
numery kierunkowe, sądy powszechne, urzędy administracyjne (z numerami kont), numeracja NTS, współrzędne geograficzne
FAQ grupy pl.comp.www.server-side
Artykuły o bazach danych, certyfikaty, recenzje