Sign in Join
Wiki copytemporary

SQLite/pl: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11## Obsługa SQLite i FPC/Lazarus
22
33SQLite to wbudowana (nie serwerowa) baza danych dla jednego użytkownika, która może być używana w aplikacjach FPC i Lazarus. Aby uzyskać dostęp do SQLite z programów FPC/Lazarus, można użyć różnych sterowników. Wszystkie sterowniki do poprawnej pracy potrzebują biblioteki/dll SQLite umieszczonej w katalogu wykonywalnym (którym może być katalog projektu lub np. (katalog projektu)/lib/architecture/ w zależności od ustawień projektu Lazarus) (i dystrybuowane z plikiem wykonywalnym).
44
55Biblioteka ta może być również umieszona w twoim katalogu Lazarus IDE. Zobacz [1](https://forum.lazarus.freepascal.org/index.php?topic=46118.msg327940#msg327940) oraz czytaj dalej, szczególnie dla Zobacz poniżej
66
77Większość dystrybucji Linuksa ma domyślnie zainstalowany sqlite3 (np. libsqlite3.so.0), ale dystrybucje Ubuntu wymagają również odpowiedniego pakietu Dev. Oba powinny zostać zainstalowane za pośrednictwem menedżera pakietów systemowych i oznaczone jako zależność, a nie dystrybuowane z aplikacją.
88
99Win64: zobacz [[Windows Programming Tips|to]] ostrzeżenie o nieużywaniu niektórych wersji FPC/Lazarus Win64.
1010
1111### Bezpośredni dostęp do SQLite
1212
1313Możesz w prosty sposób połączyć SQLite z Lazarusem. Komponenty, które nazywasz LiteDAC. SQLite Data Access Components (LiteDAC) to biblioteka komponentów, która zapewnia natywną łączność z SQLite z Lazarus (i Free Pascal) w systemach Windows, macOS, iOS, Android, Linux i FreeBSD dla platform 32-bitowych i 64-bitowych. LiteDAC jest przeznaczony dla programistów do tworzenia prawdziwie wieloplatformowych aplikacji bazodanowych SQLite na komputery stacjonarne i mobilne bez konieczności wdrażania dodatkowych bibliotek. Wersję próbną tego komercyjnego produktu można pobrać na stronie [Komponenty Lazarusa](https://www.devart(dot)com/litedac/download.html). Uwaga, w linku zamień wyrażenie (dot) na kropkę.
1414
1515### Wbudowane komponenty SQLDB
1616
1717FPC/Lazarus oferuje wbudowane komponenty SQLDB, które obejmują obsługę baz danych SQLite ([[TSQLite3Connection]]) na zakładce [[SQLdb]] [[Component Palette|Palety Komponentów]], które pozwalają m.in. tworzyć GUI z komponentami bazy danych, takimi jak TDBGrids. Zaletą korzystania z komponentów baz danych SQLDB jest to, że dość łatwo jest przejść do innej bazy danych, takiej jak Firebird lub PostgreSQL, bez zbytniego zmieniania programu. Zobacz poniżej szczegóły.
1818
1919#### Wsparcie dla Spatialite
2020
2121Spatialite to rozszerzenia GIS do SQLite, których można używać z poziomu bazy danych SQL. Zobacz [[Spatialite]].
2222
2323#### Obsługa szyfrowania w SQLite
2424
2525W ostatnich wersjach FPC (wdrożonych w marcu 2012 r.) SQLDB zawierał obsługę niektórych rozszerzonych wersji SQLite3, które szyfrują plik bazy danych SQLite przy użyciu algorytmu AES. Użyj właściwości hasła, aby ustawić klucz szyfrowania.
2626
2727Przykłady:
2828
2929- [SQLCipher](http://sqlcipher.net/): open source, lecz nie darmowe, dostępne są m.in. pliki binarne Windows (jednak musisz je skompilować samodzielnie)
3030- [System.Data.SQLite](http://system.data.sqlite.org/): open source, dostępne są binaria Windows (32, 64, CE), pobierz np. jeden z prekompilowanych plików binarnych i zmień nazwę SQLite.Interop.dll na sqlite3.dll (jeśli używasz statycznie dołączanych bibliotek, prawdopodobnie musisz zmienić nazwę System.Data.SQLite.DLL na sqlite3.dll)
3131- [wxSQLite3](http://wxcode.sourceforge.net/docs/wxsqlite3/): open source
3232- [sqleet](https://github.com/resilar/sqleet): open source, brak zależności od innych bibliotek, łatwo kompiluje się za pomocą GCC do plików wykonywalnych i pliki bibliotek, wieloplatformowy. Mechanizmy szyfrowania są dostępne zarówno interaktywnie, jak i poprzez sqleet API.
3333
3434#### sqlite3backup
3535
3636sqlite3backup to jest moduł dostarczany z FPC (nie z Lazarus, ale może być w nim używany programowo), który zapewnia funkcje tworzenia kopii zapasowych/przywracania dla SQLite3. Wykorzystuje sqlite3conn bazy danych SQLDB.
3737
3838### Zeos
3939
4040[Zeos](https://sourceforge.net/projects/zeoslib/)
4141
4242### SQLitePass
4343
4444Komponenty [SQLitePass](http://source.online.free.fr/). Ostatnia aktualizacja kodu w 2010. Ostatnia aktywność na forum w 2011.
4545
4646### TSQLite3Dataset i TSQLiteDataset
4747
4848Istnieją również oddzielne pakiety TSQLiteDataset (moduł sqliteds) i TSQLite3Dataset (moduł sqlite3ds); poniżej znajdziesz opis, jak z nich korzystać. Odwiedź [stronę główną sqlite4fpc](http://sqlite4fpc.yolasite.com/), aby znaleźć informacje o interfejsie API i więcej samouczków.
4949
5050TSqliteDataset i TSqlite3Dataset są potomkami [[TDataSet/pl|TDataSet]], które uzyskują dostęp odpowiednio do baz danych sqlite 2.8.x i 3.x.x. W przypadku nowych projektów prawdopodobnie użyjesz TSQlite3Dataset, ponieważ SQLite 3.x jest aktualną wersją.
5151
5252Poniżej znajduje się lista głównych zalet i wad w porównaniu z innymi sterownikami/metodami dostępu FPC/Lazarus SQLite:
5353
5454Zalety:
5555
5656- Elastyczny: programiści mogą wybrać, czy chcą używać języka SQL, czy nie, co pozwala im pracować z prostymi układami tabel lub dowolnym złożonym układem, na który pozwala SQL/sqlite
5757
5858Wady:
5959
6060- Zmiana na inne bazy danych jest trudniejsza niż w przypadku korzystania z komponentów SQLDB lub Zeos
6161
6262> **Note:** Biorąc pod uwagę powyższe, wielu użytkowników będzie używać SQLDB lub Zeos ze względu na zalety, chyba że potrzebują dostępu niższego poziomu do biblioteki SQLite
6363
6464## Używanie komponentów SQLdb z SQLite
6565
6666Te instrukcje koncentrują się na specyfice SQLDB (TSQLite3Connection) dla SQLite. Aby uzyskać ogólny przegląd, spójrz na [[SqlDBHowto]], który zawiera przydatne informacje o komponentach SQLdb.
6767
6868Zobacz [[SQLdb Tutorial1]], aby zapoznać się z samouczkiem na temat tworzenia GUI programu obsługującego bazę danych, który jest napisany dla SQLite/SQLDB (jak również dla Firebird/SQLDB, PostgreSQL/SQLDB, w zasadzie wszystkich obsługiwanych przez RDBMS SQLDB).
6969
7070Wykorzystamy kombinację trzech komponentów z zakładki Lazarus SQLdb: TSQLite3Connection, TSQLTransaction oraz TSQLQuery. TSQLQuery działa jak nasz TDataSet; w najprostszym przypadku reprezentuje po prostu jedną z naszych tabel. Dla uproszczenia: upewnij się, że masz już istniejący plik bazy danych SQLite i nie musisz teraz tworzyć nowego. TSQLite3Connection można znaleźć w module *sqlite3conn*, ktory pownieneś zadeklarować samodzielnie jeśli pracujesz we FreePascalu.
7171
7272Te trzy komponenty łączy się ze sobą zwykle tak: W TSQLQuery ustaw właściwości Database i Transaction, a w TSQLTransaction ustaw właściwość Database. Nie ma wiele do zrobienia w komponentach Transaction i Connection, większość interesujących rzeczy zostanie zrobione w TSQLQuery. Skonfiguruj komponenty w następujący sposób:
7373
7474TSQLite3Connection:
7575
7676- DatabaseName: Ustaw tę właściwość na nazwę pliku (ścieżkę bezwzględną!) swojego pliku SQLite. Niestety, nie można po prostu użyć ścieżki względnej, która działa bez zmian w czasie projektowania i w czasie wykonywania ***czy to nadal prawda? Czy nie można po prostu skopiować plik db w skrypcie powłoki po kompilacji lub połączyć go symbolicznie?***. Należy upewnić się, że podczas uruchamiania aplikacji poprawna ścieżka do pliku jest zawsze ustawiana programowo, bez względu na to, co zawierała w czasie projektowania.
7777
7878Uwaga: Aby ustawić pełną ścieżkę biblioteki (jeśli umieścisz swoją bibliotekę sqlite dll/so/dylib w miejscu, w którym system operacyjny go nie znajdzie, na przykład w katalogu aplikacji w systemie Linux/OSX), możesz ustawić właściwość *SQLiteLibraryName* (PRZED nawiązaniem jakiegokolwiek połączenia, np. w zdarzeniu OnCreate formularza głównego), np.:
7979
8080``` pascal
8181SQLiteLibraryName:='./sqlite3.so';
8282```
8383
8484TSQLQuery:
8585
8686- SQL: Ustaw ją na proste zapytanie wybierające dane z jednej ze swoich tabel. Na przykład, jeśli masz tabelę „foo” i chcesz, aby ten zbiór danych reprezentował tę tabelę, użyj po prostu:
8787 ``` SQL
8888 SELECT * FROM foo
8989 ```
9090
9191- Active: Ustaw to na True z poziomu IDE, aby sprawdzić, czy wszystko jest poprawnie skonfigurowane. Spowoduje to również automatyczne aktywowanie transakcji i obiektów połączenia. Jeśli pojawi się błąd, oznacza to, że nazwa bazy danych połączenia jest niepoprawna lub zapytanie SQL jest nieprawidłowe. Później, gdy zakończymy dodawanie pól (patrz poniżej), ustaw je ponownie jako nieaktywne, nie chcemy, aby IDE blokowało bazę danych SQLite (pojedynczy użytkownik!) podczas testowania aplikacji.
9292
9393- *Prawdopodobnie nie jest to konieczne do poprawnego działania - będzie wymagało sprawdzenia (czerwiec 2012)* Teraz możemy dodać Pola do naszego TSQLQuery. Podczas gdy komponenty są nadal aktywne, kliknij prawym przyciskiem myszy i „edytuj pola...”. Kliknij przycisk „+” i dodaj pola. Wyświetli się lista wszystkich pól zwróconych przez Twoje zapytanie SQL. Dodaj wszystkie potrzebne pola, możesz również dodać tutaj pola wyszukiwania; w takim przypadku po prostu upewnij się, że zdefiniowałeś już wszystkie potrzebne pola w innych zestawach danych, zanim zaczniesz dodawać pola odnośników, które się do nich odwołują. Jeśli Twoja tabela ma wiele kolumn i nie potrzebujesz ich wszystkich, możesz je po prostu pominąć, możesz również nieco bardziej uszczegółowić swój kod SQL.
9494
9595- W swoim kodzie musisz wywołać zdarzenia SQLQuery.ApplyUpdates i SQLTransaction.Commit, TSQLQuery.AfterPost i AfterInsert, które są do tego dobrym miejscem, gdy używasz go z kontrolkami obsługującymi dane, ale oczywiście możesz również odłożyć te wywołania na później. Jeśli te wywołania nie zostaną wykonane, baza danych nie zostanie zaktualizowana.
9696
9797- „Baza danych jest zablokowana”: IDE może nadal blokować bazę danych (SQLite jest bazą danych jednego użytkownika), prawdopodobnie zapomniałeś ustawić komponenty jako nieaktywne i ponownie rozłączone po zakończeniu definiowania wszystkich pól obiektów TSQLQuery. Użyj zdarzenia OnCreate formularza, aby ustawić ścieżkę i aktywować obiekty tylko w czasie wykonywania. Większość rzeczy ustawianych w TSQLQuery z poziomu IDE nie wymaga (a niektóre nawet nie pozwalają) by były aktywne w czasie projektowania, jedynym wyjątkiem jest zdefiniowanie pól, z których chce się odczytać projekt tabeli, więc w czasie projektowania stan nieaktywny powinien być normalnym stanem.
9898
9999- Wszystkie Twoje tabele powinny mieć klucz podstawowy i musisz upewnić się, że odpowiednie pole ma pfInKey i nic więcej w swoich PoviderFlags (te flagi kontrolują, jak i gdzie pole jest używane podczas automatycznego tworzenia zapytań aktualizujących i usuwających).
100100
101101- Jeśli używasz pól wyszukiwania
102102 - upewnij się, że ProviderFlags dla pola wyszukiwania jest całkowicie pusty, aby nie próbowało użyć swojej nazwy w zapytaniu aktualizującym. Samo pole odnośnika nie jest polem danych, działa tylko na wartość innego pola, odpowiadającego pola klucza i tylko to pole klucza będzie później używane w zapytaniach aktualizujących. Możesz ustawić pole klucza na ukryte, ponieważ zwykle nie chcesz go widzieć w swoim DBGrid, ale należy je zdefiniować.
103103 - LookupCache musi być ustawiony na True. W chwili pisania tego tekstu z jakiegoś powodu pole odnośnika nie wyświetli nic innego (ale nadal będzie działać) i dziwnie dokładnie odwrotnie jest w przypadku pracy z TSQLite3Dataset lub innymi komponentami TXXXDataset, tutaj musi być ustawione na False. Nie jestem jeszcze pewien, czy jest to zamierzone zachowanie, czy błąd.
104104
105105- Zwykle w przypadku prostych tabel nie musisz ustawiać żadnych właściwości InsertSQL, UpdateSQL i DeleteSQL, po prostu zostaw je puste. Jeśli masz ustawione poprawnie flagi dostawcy wszystkich pól, to powinno być w stanie utworzyć potrzebny kod SQL w locie. Aby uzyskać więcej informacji na temat InsertSQL, UpdateSQL i DeleteSQL, zobacz [[Working With TSQLQuery|Working_With_TSQLQuery#InsertSQL.2C_UpdateSQL_and_DeleteSQL_-_Basic_use_of_parameters]].
106106
107107Po poprawnym skonfigurowaniu powyższego, powinieneś być teraz w stanie używać TSQLQuery jak każdego innego zestawu TDataset, manipulując jego danymi programowo lub umieszczając TDatasouce w formularzu, łącząc go z TSQLQuery, a następnie używając kontroli danych, takich jak TDBGrid itp.
108108
109109### Tworzenie bazy danych
110110
111111Metoda [TSQLite3Connection.CreateDB](http://www.freepascal.org/docs-html/fcl/sqldb/tsqlconnection.createdb.html) odziedziczona z klasy nadrzędnej w rzeczywistości nic nie robi; aby utworzyć bazę danych, jeśli jeszcze nie istnieje plik bazy, wystarczy zapisać dane tabeli, jak w poniższym przykładzie:
112112
113113(Kod wyodrębniony z przykładu sqlite_encryption_pragma, który jest dostarczany z Lazarus 1.3 i nowszymi)
114114
115115``` pascal
116116var
117117 newFile : Boolean;
118118begin
119119
120120 SQLite3Connection1.Close; // Upewnij się, że połączenie jest zamknięte, gdy zaczynamy
121121
122122 try
123123 // Ponieważ tworzymy tę bazę danych po raz pierwszy,
124124 // sprawdź, czy plik już istnieje
125125 newFile := not FileExists(SQLite3Connection1.DatabaseName);
126126
127127 if newFile then
128128 begin
129129 // Utwórz bazę danych i tabele
130130 try
131131 SQLite3Connection1.Open;
132132 SQLTransaction1.Active := true;
133133
134134 // Tutaj konfigurujemy tabelę o nazwie „DATA” w nowej bazie danych
135135 SQLite3Connection1.ExecuteDirect('CREATE TABLE "DATA"('+
136136 ' "id" Integer NOT NULL PRIMARY KEY AUTOINCREMENT,'+
137137 ' "Current_Time" DateTime NOT NULL,'+
138138 ' "User_Name" Char(128) NOT NULL,'+
139139 ' "Info" Char(128) NOT NULL);');
140140
141141 // Tworzenie indeksu na podstawie id w tabeli DATA
142142 SQLite3Connection1.ExecuteDirect('CREATE UNIQUE INDEX "Data_id_idx" ON "DATA"( "id" );');
143143
144144 SQLTransaction1.Commit;
145145
146146 ShowMessage('Pomyślnie utworzono bazę danych.');
147147 except
148148 ShowMessage('Nie można utworzyć nowej bazy danych');
149149 end;
150150 end;
151151 except
152152 ShowMessage('Nie można sprawdzić, czy plik bazy danych istnieje');
153153 end;
154154 end;
155155```
156156
157157### Tworzenie zestawień zdefiniowanych przez użytkownika
158158
159159``` pascal
160160// Funkcja daje wynik porównania z rozróżnianiem wielkości liter w utf8
161161function UTF8xCompare(user: pointer; len1: longint; data1: pointer; len2: longint; data2: pointer): longint; cdecl;
162162var S1, S2: AnsiString;
163163begin
164164 SetString(S1, data1, len1);
165165 SetString(S2, data2, len2);
166166 Result := UnicodeCompareStr(UTF8Decode(S1), UTF8Decode(S2));
167167end;
168168
169169// Funkcja daje wynik porównania bez rozróżniania wielkości liter w utf8
170170function UTF8xCompare_CI(user: pointer; len1: longint; data1: pointer; len2: longint; data2: pointer): longint; cdecl;
171171var S1, S2: AnsiString;
172172begin
173173 SetString(S1, data1, len1);
174174 SetString(S2, data2, len2);
175175 Result := UnicodeCompareText(UTF8Decode(S1), UTF8Decode(S2));
176176end;
177177
178178// zarejestruj porządek sortowania za pomocą SQLite3 API (wymaga modułu sqlite3dyn):
179179sqlite3_create_collation(SQLite3.Handle, 'UTF8_CI', SQLITE_UTF8, nil, @UTF8xCompare_CI);
180180// lub za pomocą metody TSQLite3Connection:
181181CreateCollation('UTF8_CI',1,nil,@UTF8xCompare_CI);
182182
183183// teraz możemy użyć porównania bez rozróżniania wielkości liter w SQL, takich jak:
184184// SELECT * FORM table1 WHERE column1 COLLATE UTF8_CI = 'ą'
185185
186186// ale to nie działa dla operatora LIKE
187187// w celu obsługi również operatora LIKE musimy przeciążyć domyślną funkcję LIKE za pomocą sqlite3_create_function()
188188// http://www.sqlite.org/lang_corefunc.html#like
189189```
190190
191191### Tworzenie funkcji zdefiniowanych przez użytkownika
192192
193193``` pascal
194194// przykład przeciążenia domyślnej funkcji LOWER() funkcją podaną przez użytkownika
195195// aby uruchomić to demo, musisz dodać moduły 'sqlite3dyn' i 'ctypes' do sekcji uses
196196// i dodać stałą 'SQLITE_DETERMINISTIC' o wartości $800
197197
198198procedure UTF8xLower(ctx: psqlite3_context; N: cint; V: ppsqlite3_value); cdecl;
199199var S: AnsiString;
200200begin
201201 SetString(S, sqlite3_value_text(V[0]), sqlite3_value_bytes(V[0]));
202202 S := UTF8Encode(AnsiLowerCase(UTF8Decode(S)));
203203 sqlite3_result_text(ctx, PAnsiChar(S), Length(S), sqlite3_destructor_type(SQLITE_TRANSIENT));
204204end;
205205
206206// rejestracja funkcji LOWER() przy użyciu SQLite3 API (wymaga modułu sqlite3dyn):
207207sqlite3_create_function(SQLite3.Handle, 'lower', 1, SQLITE_UTF8 or SQLITE_DETERMINISTIC, nil, @UTF8xLower, nil, nil);
208208```
209209
210210### SQLite3 i daty
211211
212212- SQLite 3 nie przechowuje dat jako specjalnej wartości typu DateTime. Może przechowywać je jako ciągi typu string, liczby typu doubles lub liczby całkowite typu integer - patrz <http://www.sqlite.org/datatype3.html#datetime>.
213213- W ciągach string separatorem daty jest „-”, zgodnie ze standardem SQL/ISO 8601. Tak więc, jeśli wykonasz INSERT za pomocą wbudowanej funkcji DATE, zostanie ona przechowana jako coś w rodzaju „RRRR-MM-DD”.
214214- Odczytywanie wartości DateTime może powodować problemy dla DataSet, jeśli są one przechowywane jako ciągi: kwalifikator .AsDateTime może zatrzymać się na takim „string date”, ale można to obejść, używając czegoś takiego jak `strftime(`*`%d/%m/%Y`*`,recdate) AS sqlite3recdate` w instrukcji SQL SELECT, co wymusza na SQLite3 zwrócenie rekordu daty w określonym formacie. (ciąg formatu %d/%m/%d odpowiada Twojemu regionalnemu formatowi daty, który .AsDateTime zrozumie) **==\> Otwórz zgłoszenie błędu z przykładową aplikacją demonstrującą problem, jeśli taki wystąpi**
215-- Podczas porównywania dat zapisanych jako ciągi (używając na przykład funkcji BETWEEN) pamiętaj, że porównanie będzie zawsze porównaniem <b>ciągu</b> i dlatego będzie zależeć od tego, jak zachowałeś wartość daty.
215+- Podczas porównywania dat zapisanych jako ciągi (używając na przykład funkcji BETWEEN) pamiętaj, że porównanie będzie zawsze porównaniem ciągu i dlatego będzie zależeć od tego, jak zachowałeś wartość daty.
216216
217217#### Wartości domyślne w czasie lokalnym zamiast UTC
218218
219219CURRENT_TIME, CURRENT_DATE i CURRENT_TIMESTAMP zwracają aktualną datę i/lub czas UTC. Dla lokalnej daty i/lub czasu możemy użyć:
220220
221221` DEFAULT (datetime('now','localtime')) dla sformatowanych wartości daty i godziny YYYY-MM-DD HH:MM:SS`\
222222` DEFAULT (date('now','localtime')) dla sformatowanej wartości daty YYYY-MM-DD`\
223223` DEFAULT (time('now','localtime')) dla sformatowanej wartości czasu HH:MM:SS`
224224
225225### Rozwiązywanie problemów z SQLDB i SQLite
226226
227227- Należy pamiętać, że aby wsparcie w czasie projektowania (pola itp.) mogło działać, Lazarus musi również znaleźć plik sqlite3.dll.
228228- To samo dotyczy nazwy pliku bazy danych. Zawsze używaj ścieżki bezwzględnej, jeśli używasz komponentów do wyodrębniania m.in. nazwy pól w czasie projektowania. W przeciwnym razie IDE utworzy pusty plik w swoim katalogu. W razie problemów sprawdź, czy w katalogu lazarus/ nie ma pustej kopii pliku bazy danych.
229229- Jeśli masz relację master/detail, musisz odświeżyć główny zestaw danych po każdym wstawieniu, aby uzyskać wartość pola klucza obcego podrzędnego zestawu danych. Możesz to zrobić w zdarzeniu AfterPost głównego zestawu danych, wywołując jedną z następujących przeciążonych procedur:
230230
231231``` pascal
232232interface
233233 procedure RefreshADatasetAfterInsert(pDataSet: TSQLQuery);overload;
234234 procedure RefreshADatasetAfterInsert(pDataSet: TSQLQuery; pKeyField: string);overload;
235235
236236implementation
237237
238238procedure RefreshADatasetAfterInsert(pDataSet: TSQLQuery; pKeyField: string);
239239//Ta procedura odświeża DataSet i ustawia kursor na ostatnim rekordzie
240240//Do użycia, jeśli nie ma gwarancji, że DataSet zostanie posortowany według klucza podstawowego z automatycznym przyrostem
241241var
242242 vLastID: Integer;
243243 vUpdateStatus : TUpdateStatus;
244244begin
245245 vUpdateStatus := pDataset.UpdateStatus;
246246 //Pobierz ostatnio wstawiony identyfikator w bazie danych
247247 pDataset.ApplyUpdates;
248248 vLastID:=(pDataSet.DataBase as TSQLite3Connection).GetInsertID;
249249 //Teraz wróć do odpowiedniego wiersza (rekordu)
250250 if vUpdateStatus = usInserted then begin
251251 pDataset.Refresh;
252252 //Odśwież i wróć do odpowiedniego wiersza
253253 pDataset.Locate(pKeyField,vLastID,[]);
254254 end;
255255end;
256256
257257procedure RefreshADatasetAfterInsert(pDataSet: TSQLQuery);
258258//Ta procedura odświeża DataSet i ustawia kursor na ostatnim rekordzie
259259//Do użycia tylko wtedy, gdy DataSet ma gwarancję, że zostanie posortowany według klucza podstawowego z automatycznym przyrostem
260260var
261261 vLastID: Integer;
262262 vUpdateStatus : TUpdateStatus;
263263begin
264264 vUpdateStatus := pDataset.UpdateStatus;
265265 pDataset.ApplyUpdates;
266266 vLastID:=(pDataSet.DataBase as TSQLite3Connection).GetInsertID;
267267 if vUpdateStatus = usInserted then begin
268268 pDataset.Refresh;
269269 //Niebezpieczny!
270270 pDataSet.Last;
271271 end;
272272end;
273273
274274procedure TDataModule1.SQLQuery1AfterPost(DataSet: TDataSet);
275275begin
276276 RefreshADatasetAfterInsert(Dataset as TSQLQuery); //Jeśli Twój DataSet jest posortowany według klucza podstawowego
277277end;
278278
279279procedure TDataModule1.SQLQuery2AfterPost(DataSet: TDataSet);
280280begin
281281 RefreshADatasetAfterInsert(Dataset as TSQLQuery, 'ID'); //Jeśli nie masz pewności, że DataSet jest zawsze posortowany według klucza podstawowego
282282end;
283283```
284284
285285### Vacuum i inne operacje, które należy wykonać poza transakcją
286286
287287Wydaje się, że baza danych SQLDB zawsze wymaga połączenia, ale niektóre operacje, takie jak Pragma i Vacuum, muszą odbywać się poza transakcją. Sztuka polega na tym, aby zakończyć transakcję, wykonać to, co musisz i zacząć ponownie przeprowadzić transakcję (aby sqldb się nie pomyliło :)
288288
289289``` pascal
290290 // commit any pending operations or use a "fresh" sqlconnection
291291 // zatwierdź wszelkie oczekujące operacje lub użyj „świeżego” sqlconnection
292292 Conn.ExecuteDirect('End Transaction'); // Zakończ transakcję rozpoczętą przez SQLdb
293293 Conn.ExecuteDirect('Vacuum');
294294 Conn.ExecuteDirect('Begin Transaction'); //Rozpocznij transakcję dla SQLdb
295295```
296296
297297## Używanie TSQLite3Dataset
298298
299299W tej sekcji szczegółowo opisano, jak używać komponentów TSQLite2Dataset i TSQLite3Dataset w celu uzyskania dostępu do baz danych SQlite. Luiz Américo luizmed(at)oi(kropka)com(kropka)br
300300
301301#### Wymagania
302302
303303- Dla baz danych sqlite2 (starsze):
304304 - FPC 2.0.0 lub nowszy
305305 - Lazarus 0.9.10 lub nowszy
306306 - Biblioteka uruchomieniowa SQLite 2.8.15 lub nowsza*
307307
308308- Sqlite2 nie jest już utrzymywany, a pliku binarnego nie można znaleźć na stronie sqlite
309309
310310- Dla baz danych sqlite3:
311311 - FPC 2.0.2 lub nowszy
312312 - Lazarus 0.9.11 (rewizja svn) lub nowszy
313313 - biblioteka uruchomieniowa sqlite 3.2.1 lub nowsza (pobierz ją ze strony [www.sqlite.org](http://www.sqlite.org))
314314
315315**Przed rozpoczęciem projektu Lazarus upewnij się, że:**
316316
317317- biblioteka sqlite jest albo
318318 - w katalogach systemowych lub
319319 - w katalogu plików wykonywalnych i katalogach Lazarus (lub bieżącego projektu) - ta opcja może działać tylko w systemie Windows
320320- pod Linuksem umieść cmem jako pierwszy moduł w sekcji uses programu głównego
321321 - W Debianie, Ubuntu i innych dystrybucjach podobnych do Debiana, aby zbudować Lazarus IDE, musisz zainstalować pakiety libsqlite-dev/libsqlite3-dev, nie tylko sqlite/sqlite3 (dotyczy również OpenSuSe)
322322
323323#### Jak używać (podstawowe użycie)
324324
325325Zainstaluj pakiet znaleziony w katalogu /components/sqlite (zobacz instrukcje [[Install Packages|tutaj]])
326326
327327W czasie projektowania ustaw następujące właściwości:
328328
329329- FileName: ścieżka do pliku sqlite \[wymagana\]
330330- TableName: nazwa tabeli użytej w instrukcji sql \[wymagana\]
331331- SQL: instrukcja SQL select \[opcjonalna\]
332332- SaveOnClose: Wartość domyślna to false, co oznacza, że ​​zmiany nie są zapisywane. Można to zmienić na true. \[opcjonalna\]
333333- Active: Należy ustawić w czasie projektowania lub podczas uruchamiania programu. \[wymagana\]
334334
335335**Tworzenie tabeli (DataSet)**
336336
337337Kliknij dwukrotnie ikonę komponentu lub użyj elementu „Utwórz tabelę” z menu kontekstowego, które pojawia się po kliknięciu prawym przyciskiem myszy. Zostanie wyświetlony prosty, samoobjaśniający się edytor tabel.
338338
339339Oto wszystkie typy pól obsługiwane przez TSqliteDataset i TSqlite3Dataset:
340340
341341- Integer
342342- AutoInc
343343- String
344344- Memo
345345- Bool
346346- Float
347347- Word
348348- DateTime
349349- Date
350350- Time
351351- LargeInt
352352- Currency
353353
354354**Pobieranie danych**
355355
356356Po utworzeniu tabeli lub na wcześniej utworzonej tabeli otwórz DataSet za pomocą metody Open. Jeśli właściwość SQL nie została ustawiona, zostaną pobrane wszystkie rekordy ze wszystkich pól, tak samo, jeśli ustawisz SQL na:
357357
358358``` pascal
359359SQL := 'Select * from TABLENAME';
360360```
361361
362362**Wprowadzanie zmian do bazowego pliku danych**
363363
364364Aby użyć funkcji ApplyUpdates, zbiór danych musi zawierać co najmniej jedno pole, które spełnia wymagania klucza podstawowego (wartości muszą być UNIQUE, a nie NULL)
365365
366366Można to zrobić na dwa sposoby:
367367
368368- Ustaw właściwość PrimaryKey na nazwę pola klucza podstawowego
369369- Dodaj pole AutoInc (jest to łatwiejsze, ponieważ TSqliteDataSet automatycznie obsługuje je jako klucz podstawowy)
370370
371371Jeśli spełniony jest jeden z dwóch warunków, po prostu wywołaj
372372
373373``` pascal
374374ApplyUpdates;
375375```
376376
377377> **Note:** Jeśli obydwa warunki są ustawione, pole odpowiadające PrimaryKey jest używane do zastosowania aktualizacji.
378378
379379> **Note:** Ustawienie klucza podstawowego na pole, które nie jest kluczem podstawowym, spowoduje utratę danych w przypadku wywołania funkcji ApplyUpdates, dlatego przed użyciem upewnij się, że wybrane pole nie zawiera wartości Null ani Unique.
380380
381381##### Przykład Master/detail
382382
383383Różne przykłady relacji master/detail (np. relacja pomiędzy klientem a zamówieniem):
384384
385385- ogólny sposób SQLDB na wykonanie tego przy użyciu właściwości `DataSource`:
386386- Konkretny przykład TSQLite3 używający lokalizację: [[TSqlite3 Przykład wzorca Master]].
387387
388388#### Uwagi
389389
390390- Chociaż TSqliteDataset został przetestowany dla 10 000 rekordów i działał dobrze, to przechowuje wszystkie dane w pamięci, więc pamiętaj, aby pobrać tylko niezbędne dane (zwłaszcza w przypadku pól Memo).
391391- Ten sam plik danych (właściwość Filename) może zawierać kilka tables/datasets
392392- Kilka DataDets (różne kombinacje pól) można utworzyć jednocześnie przy użyciu tej samej tabeli
393393- Możliwe jest filtrowanie danych za pomocą SQL-owej instrukcji WHERE, zamykanie i ponowne otwieranie DataSet (lub wywołanie metody RefetchData). Ale w tym przypadku kolejność i liczba pól muszą pozostać takie same
394394- Możliwe jest również użycie złożonych instrukcji SQL przy użyciu aliasów, złączeń, widoków w wielu tabelach (pamiętaj, że muszą one znajdować się w tym samym pliku danych), ale w tym przypadku ApplyUpdates nie zadziała. Jeśli ktoś chce używać skomplikowanych zapytań i zastosować aktualizacje do pliku danych, napisz do mnie, a dam kilka wskazówek, jak to zrobić
395395- Ustawienie nazwy pliku na plik danych sqlite nie utworzony przez TSqliteDataset i otwarcie go jest dozwolone, ale niektóre pola nie będą miały wykrytego prawidłowego typu pola. Będą one traktowane jako pola tekstowe.
396396
397397Ogólne przykłady można znaleźć w katalogu SVN fpc/fcl-db/src/sqlite
398398
399399## Zobacz także
400400
401401- [[SQLdb Tutorial1]] Samouczek do Sqlite
402402- [[SqlDBHowto]] Ogólne informacje o SQLDB
403403- [[Working With TSQLQuery]] Informacje o TSQLQuery bazy danych SQL
404404- [Witryna SQLite](http://www.sqlite.org)
405405
406406---
407407*From the Free Pascal wiki, page "SQLite/pl", as it stood on 2021-11-20 after a change by Slawek, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history