Difference between revisions of "SQLite/pl"

From Lazarus wiki
Jump to navigationJump to search
(→‎See also: tłumaczenie na j. polski)
 
(7 intermediate revisions by the same user not shown)
Line 62: Line 62:
 
{{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}}
 
{{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}}
  
== Using the SQLdb components with SQLite ==
+
== Używanie komponentów SQLdb z SQLite ==
  
These instructions are focused on SQLDB (the TSQLite3Connection) specifics for SQLite. For a general overview, have a look at [[SqlDBHowto|SqlDBHowto]] which has some useful information about the SQLdb components.  
+
Te instrukcje koncentrują się na specyfice SQLDB (TSQLite3Connection) dla SQLite. Aby uzyskać ogólny przegląd, spójrz na [[SqlDBHowto|SqlDBHowto]], który zawiera przydatne informacje o komponentach SQLdb.
  
See [[SQLdb_Tutorial1]] for a tutorial on creating a GUI database-enabled program that is written for SQLite/SQLDB (as well as for Firebird/SQLDB, PostgreSQL/SQLDB, basically any RDBMS SQLDB supports).
+
Zobacz [[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).
  
We will use a combination of three components from the Lazarus SQLdb tab: TSQLite3Connection, TSQLTransaction and TSQLQuery. The TSQLQuery acts as our TDataset; in the simplest case it just represents one of our tables. For the sake of simplicity: make sure you already have an existing SQLite database file and don't need to create a new one now.  
+
Wykorzystamy 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 can be found in the ''sqlite3conn'' unit, if you want to declare it yourself or are working in FreePascal.
+
TSQLite3Connection można znaleźć w module ''sqlite3conn'', ktory pownieneś zadeklarować samodzielnie jeśli pracujesz we FreePascalu.
  
The three components are connected with each other as usual: In the TSQLQuery set the properties Database and Transaction, in the TSQLTransaction set the property Database. There is not much to do in the Transaction and Connection components, most of the interesting things will be done in the TSQLQuery. Configure the components as follows:
+
Te 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:
  
 
TSQLite3Connection:
 
TSQLite3Connection:
  
* DatabaseName: Set this property to the file name (absolute path!) of your SQLite file. Unfortunately, you cannot simply use a relative path that works unchanged at designtime and at runtime ***is this still true? Can't you just copy the db file in a post-build shell script or symlink it?***. You should make sure that at application start the correct path to the file is always set programmatically, no matter what it contained at designtime.
+
* 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.
  
Note: To set the full library path (if you place your sqlite dll/so/dylib in a place where the OS won't find it, like the application directory on Linux/OSX), you can set the ''SQLiteLibraryName'' property (BEFORE any connection is established e.g. in the OnCreate event of the main form), like this:
+
Uwaga: 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.:
  
 
<syntaxhighlight lang=pascal>
 
<syntaxhighlight lang=pascal>
Line 85: Line 85:
 
TSQLQuery:
 
TSQLQuery:
  
* SQL: Set it to some simple select query on one of your tables. For example, if you have a table 'foo' and want this dataset to represent this table then just use the following: <syntaxhighlight lang="SQL">SELECT * FROM foo</syntaxhighlight>
+
* 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: <syntaxhighlight lang="SQL">SELECT * FROM foo</syntaxhighlight>
  
* Active: Set this to True from within the IDE to test whether it is all set up correctly. This will also automatically activate the transaction and the connection objects. If you receive an error then either the DatabaseName of the connection is not correct or the SQL query is wrong. Later, when we are done adding the fields (see below) set them all to inactive again, we don't want the IDE to lock the SQLite database (single user!) when testing the application.
+
* 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.
  
* ''Probably not necessary for proper operation - will need to be checked (June 2012)'' Now we can add Fields to our TSQLQuery. While the components are still set to active do a right click and "edit fields...". Click the "+" button and add fields. It will list all fields your SQL query returned. Add every field you will need, you can also add lookup fields here; in this case just make sure you have already defined all needed fields in the other datasets before you start adding lookup fields that refer to them. If your table has many columns and you don't need them all you can just leave them out, you can also make your SQL a bit more specific.  
+
* ''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.
  
* In your code you need to call SQLQuery.ApplyUpdates and SQLTransaction.Commit, TSQLQuery.AfterPost and AfterInsert events are a good place for this when using it with data aware controls but of course you can also postpone these calls to a later time. If you don't call them, the database will not be updated.
+
* 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.
  
* "Database is locked": The IDE might still be locking the database (SQLite is a single user database), you probably forgot to set the components to inactive and disconnected again after you were done defining all the fields of your TSQLQuery objects. Use the Form's OnCreate event to set the path and activate the objects at runtime only. Most of the things you set in the TSQLQuery from within the IDE don't require (and some don't even allow) them to be active at design time, the only exception is defining the fields where it wants to read the table design, so inactive at design time should be the normal state.
+
* „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.
  
* Your tables should all have a primary key and you must make sure that the corresponding field has pfInKey and nothing else in its PoviderFlags (these flags control how and where the field is used when automatically constructing the update and delete queries).
+
* 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).
  
* If you are using lookup fields
+
* Jeśli używasz pól wyszukiwania
** make sure the ProviderFlags for the lookup field is completely empty so it won't attempt to use its name in an update query. The lookup field itself is not a data field, it only acts on the value of another field, the corresponding key field, and only this key field will later be used in the update queries. You can set the key field to hidden because usually you don't want to see it in your DBGrid but it needs to be defined.
+
** 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ć.
** LookupCache must be set to True. At the time of this writing for some reason the lookup field will not display anything otherwise (but still work) and strangely the exact opposite is the case when working with the TSQLite3Dataset or other TXXXDataset components, here it must be set to False. I'm not yet sure whether this is intended behavior or a bug.
+
** 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.
  
* Usually with simple tables you won't need to set any of the InsertSQL, UpdateSQL and DeleteSQL properties, just leave them empty. If you have the ProviderFlags of all your fields set correctly it should be able to create the needed SQL on the fly. For more details on InsertSQL, UpdateSQL and DeleteSQL, see [[Working_With_TSQLQuery#TSQLQuery.InsertSQL.2C_TSQLQuery.UpdateSQL_and_TSQLQuery.DeleteSQL:_Basic_Use_of_Parameters]].
+
* 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#InsertSQL.2C_UpdateSQL_and_DeleteSQL_-_Basic_use_of_parameters]].
  
After the above is all set up correctly, you should now be able to use the TSQLQuery like any other TDataset, either by manipulating its data programmatically or by placing a TDatasouce on the Form, connecting it to the TSQLQuery and then using data contols like TDBGrid etc.
+
Po 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.
  
===Creating a Database===
+
===Tworzenie bazy danych===
  
The [http://www.freepascal.org/docs-html/fcl/sqldb/tsqlconnection.createdb.html TSQLite3Connection.CreateDB] method inherited from the parent class actually does nothing; to create a database if no file exists yet, you simply have to write table data as in the following example:
+
Metoda [http://www.freepascal.org/docs-html/fcl/sqldb/tsqlconnection.createdb.html TSQLite3Connection.CreateDB] 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:
  
(Code extracted from sqlite_encryption_pragma example that ships with Lazarus 1.3 onwards)
+
(Kod wyodrębniony z przykładu sqlite_encryption_pragma, który jest dostarczany z Lazarus 1.3 i nowszymi)
  
 
<syntaxhighlight lang=pascal>
 
<syntaxhighlight lang=pascal>
Line 116: Line 116:
 
begin
 
begin
  
   SQLite3Connection1.Close; // Ensure the connection is closed when we start
+
   SQLite3Connection1.Close; // Upewnij się, że połączenie jest zamknięte, gdy zaczynamy
  
 
   try
 
   try
     // Since we're making this database for the first time,
+
     // Ponieważ tworzymy tę bazę danych po raz pierwszy,
     // check whether the file already exists
+
     // sprawdź, czy plik już istnieje
 
     newFile := not FileExists(SQLite3Connection1.DatabaseName);
 
     newFile := not FileExists(SQLite3Connection1.DatabaseName);
  
 
     if newFile then
 
     if newFile then
 
     begin
 
     begin
       // Create the database and the tables
+
       // Utwórz bazę danych i tabele
 
       try
 
       try
 
         SQLite3Connection1.Open;
 
         SQLite3Connection1.Open;
 
         SQLTransaction1.Active := true;
 
         SQLTransaction1.Active := true;
  
         // Here we're setting up a table named "DATA" in the new database
+
         // Tutaj konfigurujemy tabelę o nazwie „DATA” w nowej bazie danych
 
         SQLite3Connection1.ExecuteDirect('CREATE TABLE "DATA"('+
 
         SQLite3Connection1.ExecuteDirect('CREATE TABLE "DATA"('+
 
                     ' "id" Integer NOT NULL PRIMARY KEY AUTOINCREMENT,'+
 
                     ' "id" Integer NOT NULL PRIMARY KEY AUTOINCREMENT,'+
Line 137: Line 137:
 
                     ' "Info" Char(128) NOT NULL);');
 
                     ' "Info" Char(128) NOT NULL);');
  
         // Creating an index based upon id in the DATA Table
+
         // Tworzenie indeksu na podstawie id w tabeli DATA
 
         SQLite3Connection1.ExecuteDirect('CREATE UNIQUE INDEX "Data_id_idx" ON "DATA"( "id" );');
 
         SQLite3Connection1.ExecuteDirect('CREATE UNIQUE INDEX "Data_id_idx" ON "DATA"( "id" );');
  
 
         SQLTransaction1.Commit;
 
         SQLTransaction1.Commit;
  
         ShowMessage('Succesfully created database.');
+
         ShowMessage('Pomyślnie utworzono bazę danych.');
 
       except
 
       except
         ShowMessage('Unable to Create new Database');
+
         ShowMessage('Nie można utworzyć nowej bazy danych');
 
       end;
 
       end;
 
     end;
 
     end;
 
   except
 
   except
     ShowMessage('Unable to check if database file exists');
+
     ShowMessage('Nie można sprawdzić, czy plik bazy danych istnieje');
 
   end;
 
   end;
 
  end;
 
  end;
 
</syntaxhighlight>
 
</syntaxhighlight>
  
===Creating user defined collations ===
+
===Tworzenie zestawień zdefiniowanych przez użytkownika===
  
 
<syntaxhighlight lang=pascal>
 
<syntaxhighlight lang=pascal>
// utf8 case-sensitive compare callback function
+
// Funkcja daje wynik porównania z rozróżnianiem wielkości liter w utf8
 
function UTF8xCompare(user: pointer; len1: longint; data1: pointer; len2: longint; data2: pointer): longint; cdecl;
 
function UTF8xCompare(user: pointer; len1: longint; data1: pointer; len2: longint; data2: pointer): longint; cdecl;
 
var S1, S2: AnsiString;
 
var S1, S2: AnsiString;
Line 165: Line 165:
 
end;
 
end;
  
// utf8 case-insensitive compare callback function
+
// Funkcja daje wynik porównania bez rozróżniania wielkości liter w utf8
 
function UTF8xCompare_CI(user: pointer; len1: longint; data1: pointer; len2: longint; data2: pointer): longint; cdecl;
 
function UTF8xCompare_CI(user: pointer; len1: longint; data1: pointer; len2: longint; data2: pointer): longint; cdecl;
 
var S1, S2: AnsiString;
 
var S1, S2: AnsiString;
Line 174: Line 174:
 
end;
 
end;
  
// register collation using SQLite3 API (requires sqlite3dyn unit):
+
// zarejestruj porządek sortowania za pomocą SQLite3 API (wymaga modułu sqlite3dyn):
 
sqlite3_create_collation(SQLite3.Handle, 'UTF8_CI', SQLITE_UTF8, nil, @UTF8xCompare_CI);
 
sqlite3_create_collation(SQLite3.Handle, 'UTF8_CI', SQLITE_UTF8, nil, @UTF8xCompare_CI);
// or using method of TSQLite3Connection:
+
// lub za pomocą metody TSQLite3Connection:
 
CreateCollation('UTF8_CI',1,nil,@UTF8xCompare_CI);   
 
CreateCollation('UTF8_CI',1,nil,@UTF8xCompare_CI);   
  
// now we can use case-insensitive comparison in SQL like:
+
// teraz możemy użyć porównania bez rozróżniania wielkości liter w SQL, takich jak:
// SELECT * FORM table1 WHERE column1 COLLATE UTF8_CI = 'á'
+
// SELECT * FORM table1 WHERE column1 COLLATE UTF8_CI = 'ą'
  
// but this does not work for LIKE operator
+
// ale to nie działa dla operatora LIKE
// in order to support also LIKE operator we must overload default LIKE function using sqlite3_create_function()
+
// w celu obsługi również operatora LIKE musimy przeciążyć domyślną funkcję LIKE za pomocą sqlite3_create_function()
 
// http://www.sqlite.org/lang_corefunc.html#like
 
// http://www.sqlite.org/lang_corefunc.html#like
 
</syntaxhighlight>
 
</syntaxhighlight>
  
===Creating user defined functions ===
+
===Tworzenie funkcji zdefiniowanych przez użytkownika===
  
 
<syntaxhighlight lang=pascal>
 
<syntaxhighlight lang=pascal>
// example overloading default LOWER() function with user supplied function
+
// przykład przeciążenia domyślnej funkcji LOWER() funkcją podaną przez użytkownika
// to run this demo, you must add units 'sqlite3dyn' and 'ctypes' to your uses-clause
+
// aby uruchomić to demo, musisz dodać moduły 'sqlite3dyn' i 'ctypes' do sekcji uses
// and add a const 'SQLITE_DETERMINISTIC' with value $800
+
// i dodać stałą 'SQLITE_DETERMINISTIC' o wartości $800
  
 
procedure UTF8xLower(ctx: psqlite3_context; N: cint; V: ppsqlite3_value); cdecl;
 
procedure UTF8xLower(ctx: psqlite3_context; N: cint; V: ppsqlite3_value); cdecl;
Line 202: Line 202:
 
end;
 
end;
  
// register function LOWER() using SQLite3 API (requires sqlite3dyn unit):
+
// rejestracja funkcji LOWER() przy użyciu SQLite3 API (wymaga modułu sqlite3dyn):
 
sqlite3_create_function(SQLite3.Handle, 'lower', 1, SQLITE_UTF8 or SQLITE_DETERMINISTIC, nil, @UTF8xLower, nil, nil);
 
sqlite3_create_function(SQLite3.Handle, 'lower', 1, SQLITE_UTF8 or SQLITE_DETERMINISTIC, nil, @UTF8xLower, nil, nil);
 
</syntaxhighlight>
 
</syntaxhighlight>
  
=== SQLite3 and Dates ===
+
=== SQLite3 i daty ===
  
* SQLite 3 doesn't store dates as a special DateTime value. It can stores them as strings, doubles or integers - see
+
* 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.
http://www.sqlite.org/datatype3.html#datetime.  
+
* 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”.
* In strings, the  date separator is '-' as per SQL standard/ISO 8601. Thus, if you do an INSERT using the built-in DATE function, it will store it as something like 'YYYY-MM-DD'.
+
* 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 <tt>strftime(''%d/%m/%Y'',recdate) AS sqlite3recdate</tt> 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'''
* Reading a DateTime value can cause problems for DataSets if they are stored as strings: the .AsDateTime qualifier can stall on an SQLite 'string date' but this can be overcome by using something like <tt>strftime(''%d/%m/%Y'',recdate) AS sqlite3recdate</tt> in your SQL SELECT statement, which forces SQLite3 to return the date record in a specified format. (the format string %d/%m/%d corresponds to your locale date format which .AsDateTime will understand) '''==> Please open a bug report with an example application demonstrating the problemif this is the case'''
+
* 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.
* When comparing dates stored as strings (using for example the BETWEEN function) remember that the comparison will always be a <b>string</b> comparison, and will therefore depend on how you have stored the date value.
 
  
==== Default values in local time instead of UTC ====
+
==== Wartości domyślne w czasie lokalnym zamiast UTC ====
  
CURRENT_TIME, CURRENT_DATE and CURRENT_TIMESTAMP return current UTC date and/or time. For local date and/or times we can use:
+
CURRENT_TIME, CURRENT_DATE i CURRENT_TIMESTAMP zwracają aktualną datę i/lub czas UTC. Dla lokalnej daty i/lub czasu możemy użyć:
  
   DEFAULT (datetime('now','localtime')) for datetime values formated YYYY-MM-DD HH:MM:SS
+
   DEFAULT (datetime('now','localtime')) dla sformatowanych wartości daty i godziny YYYY-MM-DD HH:MM:SS
   DEFAULT (date('now','localtime')) for date value formated YYYY-MM-DD
+
   DEFAULT (date('now','localtime')) dla sformatowanej wartości daty YYYY-MM-DD
   DEFAULT (time('now','localtime')) for time value formated HH:MM:SS
+
   DEFAULT (time('now','localtime')) dla sformatowanej wartości czasu HH:MM:SS
  
===SQLDB And SQLite troubleshooting===
+
===Rozwiązywanie problemów z SQLDB i SQLite===
  
* Keep in mind that for designtime support to work (fields etc) Lazarus must find sqlite3.dll too.
+
* Należy pamiętać, że aby wsparcie w czasie projektowania (pola itp.) mogło działać, Lazarus musi również znaleźć plik sqlite3.dll.
* The same goes for the database filename. Always use absolute path if you use components to extract e.g. fieldnames at designtime. Otherwise the IDE will create an empty file in its directory. In case of trouble, check if the lazarus/ directory doesn't hold a zero byte copy of the database file.
+
* 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.
* If you have master/detail relationship, you need to refresh master dataset after each insert, in order to get value for slave dataset foreign key field. You can do that in AfterPost event of the master dataset, by calling one of the following overloaded procedures:
+
* 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:
  
 
<syntaxhighlight lang=pascal>
 
<syntaxhighlight lang=pascal>
Line 236: Line 235:
 
   
 
   
 
procedure RefreshADatasetAfterInsert(pDataSet: TSQLQuery; pKeyField: string);
 
procedure RefreshADatasetAfterInsert(pDataSet: TSQLQuery; pKeyField: string);
//This procedure refreshes a dataset and positions cursor to last record
+
//Ta procedura odświeża DataSet i ustawia kursor na ostatnim rekordzie
//To be used if Dataset is not guaranteed to be sorted by an autoincrement primary key
+
//Do użycia, jeśli nie ma gwarancji, że DataSet zostanie posortowany według klucza podstawowego z automatycznym przyrostem
 
var
 
var
 
   vLastID: Integer;
 
   vLastID: Integer;
Line 243: Line 242:
 
begin
 
begin
 
   vUpdateStatus := pDataset.UpdateStatus;
 
   vUpdateStatus := pDataset.UpdateStatus;
   //Get last inserted ID in the database
+
   //Pobierz ostatnio wstawiony identyfikator w bazie danych
 
   pDataset.ApplyUpdates;
 
   pDataset.ApplyUpdates;
 
   vLastID:=(pDataSet.DataBase as TSQLite3Connection).GetInsertID;
 
   vLastID:=(pDataSet.DataBase as TSQLite3Connection).GetInsertID;
   //Now come back to respective row
+
   //Teraz wróć do odpowiedniego wiersza (rekordu)
 
   if vUpdateStatus = usInserted then begin
 
   if vUpdateStatus = usInserted then begin
 
     pDataset.Refresh;
 
     pDataset.Refresh;
     //Refresh and go back to respective row
+
     //Odśwież i wróć do odpowiedniego wiersza
 
     pDataset.Locate(pKeyField,vLastID,[]);
 
     pDataset.Locate(pKeyField,vLastID,[]);
 
   end;
 
   end;
Line 255: Line 254:
 
   
 
   
 
procedure RefreshADatasetAfterInsert(pDataSet: TSQLQuery);
 
procedure RefreshADatasetAfterInsert(pDataSet: TSQLQuery);
//This procedure refreshes a dataset and positions cursor to last record
+
//Ta procedura odświeża DataSet i ustawia kursor na ostatnim rekordzie
//To be used only if DataSet is guaranteed to be sorted by an autoincrement primary key
+
//Do użycia tylko wtedy, gdy DataSet ma gwarancję, że zostanie posortowany według klucza podstawowego z automatycznym przyrostem
 
var
 
var
 
   vLastID: Integer;
 
   vLastID: Integer;
Line 266: Line 265:
 
   if vUpdateStatus = usInserted then begin
 
   if vUpdateStatus = usInserted then begin
 
     pDataset.Refresh;
 
     pDataset.Refresh;
     //Dangerous!
+
     //Niebezpieczny!
 
     pDataSet.Last;
 
     pDataSet.Last;
 
   end;
 
   end;
Line 273: Line 272:
 
procedure TDataModule1.SQLQuery1AfterPost(DataSet: TDataSet);
 
procedure TDataModule1.SQLQuery1AfterPost(DataSet: TDataSet);
 
begin
 
begin
   RefreshADatasetAfterInsert(Dataset as TSQLQuery); //If your dataset is sorted by primary key
+
   RefreshADatasetAfterInsert(Dataset as TSQLQuery); //Jeśli Twój DataSet jest posortowany według klucza podstawowego
 
end;   
 
end;   
  
 
procedure TDataModule1.SQLQuery2AfterPost(DataSet: TDataSet);
 
procedure TDataModule1.SQLQuery2AfterPost(DataSet: TDataSet);
 
begin
 
begin
   RefreshADatasetAfterInsert(Dataset as TSQLQuery, 'ID'); //if you are not sure that the dataset is always sorted by primary key
+
   RefreshADatasetAfterInsert(Dataset as TSQLQuery, 'ID'); //Jeśli nie masz pewności, że DataSet jest zawsze posortowany według klucza podstawowego
 
end;
 
end;
 
</syntaxhighlight>
 
</syntaxhighlight>
  
=== Vacuum and other operations that must be done outside a transaction ===
+
=== Vacuum i inne operacje, które należy wykonać poza transakcją ===
  
SQLDB seems to always require a connection, but some operations like Pragma and Vacuum must
+
Wydaje się, że baza danych SQLDB zawsze wymaga połączenia, ale niektóre operacje, takie jak Pragma i Vacuum, muszą
be done outside a transaction. The trick is to end transaction, execute what you must and start
+
odbywać się poza transakcją. Sztuka polega na tym, aby zakończyć transakcję, wykonać to, co musisz i zacząć
transaction again (so that sqldb doesn't get confused:)
+
ponownie przeprowadzić transakcję (aby sqldb się nie pomyliło :)
  
 
<syntaxhighlight lang=pascal>
 
<syntaxhighlight lang=pascal>
 
   // commit any pending operations or use a "fresh" sqlconnection
 
   // commit any pending operations or use a "fresh" sqlconnection
   Conn.ExecuteDirect('End Transaction');  // End the transaction started by SQLdb
+
  // zatwierdź wszelkie oczekujące operacje lub użyj „świeżego” sqlconnection
 +
   Conn.ExecuteDirect('End Transaction');  // Zakończ transakcję rozpoczętą przez SQLdb
 
   Conn.ExecuteDirect('Vacuum');
 
   Conn.ExecuteDirect('Vacuum');
   Conn.ExecuteDirect('Begin Transaction'); //Start a transaction for SQLdb to use
+
   Conn.ExecuteDirect('Begin Transaction'); //Rozpocznij transakcję dla SQLdb
 
</syntaxhighlight>
 
</syntaxhighlight>
  
== Using TSQLite3Dataset ==
+
== Używanie TSQLite3Dataset ==
  
This section details how to use the TSQLite2Dataset and TSQLite3Dataset components to access SQlite databases.
+
W 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
by Luiz Américo
 
luizmed(at)oi(dot)com(dot)br
 
  
 +
====Wymagania====
  
====Requirements====
+
* Dla baz danych sqlite2 (starsze):
 +
** FPC 2.0.0 lub nowszy
 +
** Lazarus 0.9.10 lub nowszy
 +
** Biblioteka uruchomieniowa SQLite 2.8.15 lub nowsza*
  
* For sqlite2 databases (legacy):
+
* Sqlite2 nie jest już utrzymywany, a pliku binarnego nie można znaleźć na stronie sqlite
** FPC 2.0.0 or higher
 
** Lazarus 0.9.10 or higher
 
** SQLite runtime library 2.8.15 or above*
 
  
* Sqlite2 is not maintained anymore and the binary file cannot be found in the sqlite site
+
* Dla baz danych sqlite3:
 +
** FPC 2.0.2 lub nowszy
 +
** Lazarus 0.9.11 (rewizja svn) lub nowszy
 +
** biblioteka uruchomieniowa sqlite 3.2.1 lub nowsza (pobierz ją ze strony [http://www.sqlite.org www.sqlite.org])
  
* For sqlite3 databases:
+
'''Przed rozpoczęciem projektu Lazarus upewnij się, że:'''
** FPC 2.0.2 or higher
+
* biblioteka sqlite jest albo
** Lazarus 0.9.11 (svn revision 8443) or higher
+
** w katalogach systemowych lub
** sqlite runtime library 3.2.1 or higer (get it from [http://www.sqlite.org www.sqlite.org])
+
** w katalogu plików wykonywalnych i katalogach Lazarus (lub bieżącego projektu) - ta opcja może działać tylko w systemie Windows
 +
* pod Linuksem umieść cmem jako pierwszy moduł w sekcji uses programu głównego
 +
** 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)
  
'''Before initiating a lazarus project, ensure that:'''
+
====Jak używać (podstawowe użycie)====
* the sqlite library is either 
 
** in the system PATH or
 
** in the executable output directory and Lazarus (or current project) directories - this option might work on Windows only
 
* under Linux, put cmem as the first unit in uses clause of the main program
 
** In Debian, Ubuntu and other Debian-like distros, in order to build Lazarus IDE you must install the packages libsqlite-dev/libsqlite3-dev, not only sqlite/sqlite3 (Also applies to OpenSuSe)
 
  
====How To Use (Basic Usage)====
+
Zainstaluj pakiet znaleziony w katalogu /components/sqlite (zobacz instrukcje [[Install_Packages|tutaj]])
  
Install the package found at /components/sqlite directory (see instructions [[Install_Packages|here]])
+
W czasie projektowania ustaw następujące właściwości:
  
At design time, set the following properties:
+
* FileName: ścieżka do pliku sqlite [wymagana]
 +
* TableName: nazwa tabeli użytej w instrukcji sql [wymagana]
 +
* SQL: instrukcja SQL select [opcjonalna]
 +
* SaveOnClose: Wartość domyślna to false, co oznacza, że ​​zmiany nie są zapisywane. Można to zmienić na true. [opcjonalna]
 +
* Active: Należy ustawić w czasie projektowania lub podczas uruchamiania programu. [wymagana]
  
* FileName: path of the sqlite file [required]
+
'''Tworzenie tabeli (DataSet)'''
* TableName: name of the table used in the sql statement [required]
 
* SQL: a SQL select statement [optional]
 
* SaveOnClose: The default value is false, which means that changes are not saved. One can change it to true. [optional]
 
* Active: Needs to be set at design time or at program startup. [required]
 
  
'''Creating a Table (Dataset)'''
+
Kliknij 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.
  
Double-click the component icon or use the 'Create Table' item of the popup menu that appears when clicking the right mouse button.
+
Oto wszystkie typy pól obsługiwane przez TSqliteDataset i TSqlite3Dataset:
A simple self-explaining table editor will be shown.
 
 
 
Here are all field types supported by TSqliteDataset and TSqlite3Dataset:  
 
 
    
 
    
 
* Integer
 
* Integer
Line 355: Line 351:
 
* Currency
 
* Currency
 
    
 
    
'''Retrieving the data'''
+
'''Pobieranie danych'''
  
After creating the table or with a previously created Table, open the dataset with the Open method.
+
Po utworzeniu tabeli lub na wcześniej utworzonej tabeli otwórz DataSet za pomocą metody Open.
If the SQL property was not set then all records from all fields will be retrieved, the same if you set the SQL to:
+
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:
  
 
<syntaxhighlight lang=pascal>SQL := 'Select * from TABLENAME';</syntaxhighlight>
 
<syntaxhighlight lang=pascal>SQL := 'Select * from TABLENAME';</syntaxhighlight>
  
'''Applying changes to the underlying datafile'''
+
'''Wprowadzanie zmian do bazowego pliku danych'''
  
To use the ApplyUpdates function, the dataset must contain at least one field that fulfills the requirements for a Primary Key (values must be UNIQUE and not NULL)
+
Aby 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)
  
It's possible to do that in two ways:
+
Można to zrobić na dwa sposoby:
  
* Set PrimaryKey property to the name of a Primary Key field
+
* Ustaw właściwość PrimaryKey na nazwę pola klucza podstawowego
* Add an AutoInc field (This is easier since the TSqliteDataSet automatically handles it as a Primary Key)
+
* Dodaj pole AutoInc (jest to łatwiejsze, ponieważ TSqliteDataSet automatycznie obsługuje je jako klucz podstawowy)
  
If one of the two conditions is set, just call
+
Jeśli spełniony jest jeden z dwóch warunków, po prostu wywołaj
 
    
 
    
 
<syntaxhighlight lang=pascal>ApplyUpdates;</syntaxhighlight>
 
<syntaxhighlight lang=pascal>ApplyUpdates;</syntaxhighlight>
  
{{Note|If both conditions are set, the field corresponding to PrimaryKey is used to apply the updates.}}
+
{{Note|Jeśli obydwa warunki są ustawione, pole odpowiadające PrimaryKey jest używane do zastosowania aktualizacji.}}
  
{{Note|Setting PrimaryKey to a field that is not a Primary Key will lead to loss of data if ApplyUpdates is called, so ensure that the chosen field contains not Null and Unique values before using it.}}
+
{{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.}}
  
=====Master/detail example=====
+
=====Przykład Master/detail=====
  
Various examples of master/detail relations (e.g. the relation between customer and orders):
+
Różne przykłady relacji master/detail (np. relacja pomiędzy klientem a zamówieniem):
  
* the generic SQLDB way of doing this using the <code>DataSource</code> property: [[MasterDetail]]
+
* ogólny sposób SQLDB na wykonanie tego przy użyciu właściwości <code>DataSource</code>:
* TSQLite3 specific example using locate: [[TSqlite3 Master Detail Example]].
+
* Konkretny przykład TSQLite3 używający lokalizację: [[TSqlite3 Przykład wzorca Master]].
  
====Remarks====
+
====Uwagi====
  
* Although it has been tested with 10,000 records and worked fine, TSqliteDataset keeps all the data in memory, so remember to retrieve only the necessary data (especially with Memo Fields).
+
* 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).
* The same datafile (Filename property) can host several tables/datasets
+
* Ten sam plik danych (właściwość Filename) może zawierać kilka tables/datasets
* Several datasets (different combinations of fields) can be created using the same table simultaneously
+
* Kilka DataDets (różne kombinacje pól) można utworzyć jednocześnie przy użyciu tej samej tabeli
* It's possible to filter the data using WHERE statements in the sql, closing and reopening the dataset (or calling RefetchData method). But in this case, the order and number of fields must remain the same  
+
* 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
* It's also possible to use complex SQL statements using aliases, joins, views in multiple tables (remember that they must reside in the same datafile), but in this case ApplyUpdates won't work. If someone wants to use complex queries and to apply the updates to the datafile, mail me and i will give some hints how to do that
+
* 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ć
* Setting filename to a sqlite datafile not created by TSqliteDataset and opening it is allowed but some fields won't have the correct field type detected. These will be treated as string fields.
+
* 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.
  
Generic examples can be found at fpc/fcl-db/src/sqlite SVN directory
+
Ogólne przykłady można znaleźć w katalogu SVN fpc/fcl-db/src/sqlite
  
==See also==
+
==Zobacz także==
  
* [[SQLdb_Tutorial1]] Tutorial for Sqlite
+
* [[SQLdb_Tutorial1]] Samouczek do Sqlite
* [[SqlDBHowto]] General information on SQLDB
+
* [[SqlDBHowto]] Ogólne informacje o SQLDB
* [[Working With TSQLQuery]] Information on SQLDB's TSQLQuery
+
* [[Working With TSQLQuery]] Informacje o TSQLQuery bazy danych SQL
* [http://www.sqlite.org SQLite site]
+
* [http://www.sqlite.org Witryna SQLite]

Latest revision as of 01:44, 21 November 2021

English (en) español (es) français (fr) 日本語 (ja) polski (pl) русский (ru)

Portal bazy danych

Bibliografia:

Poradniki/porady praktyczne:

Bazy danych

Advantage - MySQL - MS SQL - Postgres - Interbase - Firebird - Oracle - ODBC - Paradox - SQLite - dBASE - MS Access - Zeos

Obsługa SQLite i FPC/Lazarus

SQLite 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).

Biblioteka ta może być również umieszona w twoim katalogu Lazarus IDE. Zobacz [1] oraz czytaj dalej, szczególnie dla Zobacz poniżej

Wię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ą.

Win64: zobacz to ostrzeżenie o nieużywaniu niektórych wersji FPC/Lazarus Win64.

Bezpośredni dostęp do SQLite

Moż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. Uwaga, w linku zamień wyrażenie (dot) na kropkę.

Wbudowane komponenty SQLDB

FPC/Lazarus oferuje wbudowane komponenty SQLDB, które obejmują obsługę baz danych SQLite (TSQLite3Connection) na zakładce SQLdb 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.

Wsparcie dla Spatialite

Spatialite to rozszerzenia GIS do SQLite, których można używać z poziomu bazy danych SQL. Zobacz Spatialite.

Obsługa szyfrowania w SQLite

W 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.

Przykłady:

  • SQLCipher: open source, lecz nie darmowe, dostępne są m.in. pliki binarne Windows (jednak musisz je skompilować samodzielnie)
  • System.Data.SQLite: 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)
  • wxSQLite3: open source
  • 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.

sqlite3backup

sqlite3backup 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.

Zeos

Zeos

SQLitePass

Komponenty SQLitePass. Ostatnia aktualizacja kodu w 2010. Ostatnia aktywność na forum w 2011.

TSQLite3Dataset i TSQLiteDataset

Istnieją również oddzielne pakiety TSQLiteDataset (moduł sqliteds) i TSQLite3Dataset (moduł sqlite3ds); poniżej znajdziesz opis, jak z nich korzystać. Odwiedź stronę główną sqlite4fpc, aby znaleźć informacje o interfejsie API i więcej samouczków.

TSqliteDataset i TSqlite3Dataset są potomkami 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ą.

Poniżej znajduje się lista głównych zalet i wad w porównaniu z innymi sterownikami/metodami dostępu FPC/Lazarus SQLite:

Zalety:

  • 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

Wady:

  • Zmiana na inne bazy danych jest trudniejsza niż w przypadku korzystania z komponentów SQLDB lub Zeos
Note-icon.png

Uwaga: 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

Używanie komponentów SQLdb z SQLite

Te 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.

Zobacz 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).

Wykorzystamy 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.

Te 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:

TSQLite3Connection:

  • 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.

Uwaga: 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.:

SQLiteLibraryName:='./sqlite3.so';

TSQLQuery:

  • 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:
    SELECT * FROM foo
    
  • 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.
  • 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.
  • 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.
  • „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.
  • 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).
  • Jeśli używasz pól wyszukiwania
    • 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ć.
    • 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.
  • 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#InsertSQL.2C_UpdateSQL_and_DeleteSQL_-_Basic_use_of_parameters.

Po 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.

Tworzenie bazy danych

Metoda TSQLite3Connection.CreateDB 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:

(Kod wyodrębniony z przykładu sqlite_encryption_pragma, który jest dostarczany z Lazarus 1.3 i nowszymi)

var
  newFile : Boolean;
begin

  SQLite3Connection1.Close; // Upewnij się, że połączenie jest zamknięte, gdy zaczynamy

  try
    // Ponieważ tworzymy tę bazę danych po raz pierwszy,
    // sprawdź, czy plik już istnieje
    newFile := not FileExists(SQLite3Connection1.DatabaseName);

    if newFile then
    begin
      // Utwórz bazę danych i tabele
      try
        SQLite3Connection1.Open;
        SQLTransaction1.Active := true;

        // Tutaj konfigurujemy tabelę o nazwie „DATA” w nowej bazie danych
        SQLite3Connection1.ExecuteDirect('CREATE TABLE "DATA"('+
                    ' "id" Integer NOT NULL PRIMARY KEY AUTOINCREMENT,'+
                    ' "Current_Time" DateTime NOT NULL,'+
                    ' "User_Name" Char(128) NOT NULL,'+
                    ' "Info" Char(128) NOT NULL);');

        // Tworzenie indeksu na podstawie id w tabeli DATA
        SQLite3Connection1.ExecuteDirect('CREATE UNIQUE INDEX "Data_id_idx" ON "DATA"( "id" );');

        SQLTransaction1.Commit;

        ShowMessage('Pomyślnie utworzono bazę danych.');
      except
        ShowMessage('Nie można utworzyć nowej bazy danych');
      end;
    end;
  except
    ShowMessage('Nie można sprawdzić, czy plik bazy danych istnieje');
  end;
 end;

Tworzenie zestawień zdefiniowanych przez użytkownika

// Funkcja daje wynik porównania z rozróżnianiem wielkości liter w utf8
function UTF8xCompare(user: pointer; len1: longint; data1: pointer; len2: longint; data2: pointer): longint; cdecl;
var S1, S2: AnsiString;
begin
  SetString(S1, data1, len1);
  SetString(S2, data2, len2);
  Result := UnicodeCompareStr(UTF8Decode(S1), UTF8Decode(S2));
end;

// Funkcja daje wynik porównania bez rozróżniania wielkości liter w utf8
function UTF8xCompare_CI(user: pointer; len1: longint; data1: pointer; len2: longint; data2: pointer): longint; cdecl;
var S1, S2: AnsiString;
begin
  SetString(S1, data1, len1);
  SetString(S2, data2, len2);
  Result := UnicodeCompareText(UTF8Decode(S1), UTF8Decode(S2));
end;

// zarejestruj porządek sortowania za pomocą SQLite3 API (wymaga modułu sqlite3dyn):
sqlite3_create_collation(SQLite3.Handle, 'UTF8_CI', SQLITE_UTF8, nil, @UTF8xCompare_CI);
// lub za pomocą metody TSQLite3Connection:
CreateCollation('UTF8_CI',1,nil,@UTF8xCompare_CI);  

// teraz możemy użyć porównania bez rozróżniania wielkości liter w SQL, takich jak:
// SELECT * FORM table1 WHERE column1 COLLATE UTF8_CI = 'ą'

// ale to nie działa dla operatora LIKE
// w celu obsługi również operatora LIKE musimy przeciążyć domyślną funkcję LIKE za pomocą sqlite3_create_function()
// http://www.sqlite.org/lang_corefunc.html#like

Tworzenie funkcji zdefiniowanych przez użytkownika

// przykład przeciążenia domyślnej funkcji LOWER() funkcją podaną przez użytkownika
// aby uruchomić to demo, musisz dodać moduły 'sqlite3dyn' i 'ctypes' do sekcji uses
// i dodać stałą 'SQLITE_DETERMINISTIC' o wartości $800

procedure UTF8xLower(ctx: psqlite3_context; N: cint; V: ppsqlite3_value); cdecl;
var S: AnsiString;
begin
  SetString(S, sqlite3_value_text(V[0]), sqlite3_value_bytes(V[0]));
  S := UTF8Encode(AnsiLowerCase(UTF8Decode(S)));
  sqlite3_result_text(ctx, PAnsiChar(S), Length(S), sqlite3_destructor_type(SQLITE_TRANSIENT));
end;

// rejestracja funkcji LOWER() przy użyciu SQLite3 API (wymaga modułu sqlite3dyn):
sqlite3_create_function(SQLite3.Handle, 'lower', 1, SQLITE_UTF8 or SQLITE_DETERMINISTIC, nil, @UTF8xLower, nil, nil);

SQLite3 i daty

  • 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.
  • 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”.
  • 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
  • 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.

Wartości domyślne w czasie lokalnym zamiast UTC

CURRENT_TIME, CURRENT_DATE i CURRENT_TIMESTAMP zwracają aktualną datę i/lub czas UTC. Dla lokalnej daty i/lub czasu możemy użyć:

 DEFAULT (datetime('now','localtime')) dla sformatowanych wartości daty i godziny YYYY-MM-DD HH:MM:SS
 DEFAULT (date('now','localtime')) dla sformatowanej wartości daty YYYY-MM-DD
 DEFAULT (time('now','localtime')) dla sformatowanej wartości czasu HH:MM:SS

Rozwiązywanie problemów z SQLDB i SQLite

  • Należy pamiętać, że aby wsparcie w czasie projektowania (pola itp.) mogło działać, Lazarus musi również znaleźć plik sqlite3.dll.
  • 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.
  • 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:
interface
    procedure RefreshADatasetAfterInsert(pDataSet: TSQLQuery);overload;
    procedure RefreshADatasetAfterInsert(pDataSet: TSQLQuery; pKeyField: string);overload;  
 
implementation
 
procedure RefreshADatasetAfterInsert(pDataSet: TSQLQuery; pKeyField: string);
//Ta procedura odświeża DataSet i ustawia kursor na ostatnim rekordzie
//Do użycia, jeśli nie ma gwarancji, że DataSet zostanie posortowany według klucza podstawowego z automatycznym przyrostem
var
  vLastID: Integer;
  vUpdateStatus : TUpdateStatus;
begin
  vUpdateStatus := pDataset.UpdateStatus;
  //Pobierz ostatnio wstawiony identyfikator w bazie danych
  pDataset.ApplyUpdates;
  vLastID:=(pDataSet.DataBase as TSQLite3Connection).GetInsertID;
  //Teraz wróć do odpowiedniego wiersza (rekordu)
  if vUpdateStatus = usInserted then begin
    pDataset.Refresh;
    //Odśwież i wróć do odpowiedniego wiersza
    pDataset.Locate(pKeyField,vLastID,[]);
  end;
end;
 
procedure RefreshADatasetAfterInsert(pDataSet: TSQLQuery);
//Ta procedura odświeża DataSet i ustawia kursor na ostatnim rekordzie
//Do użycia tylko wtedy, gdy DataSet ma gwarancję, że zostanie posortowany według klucza podstawowego z automatycznym przyrostem
var
  vLastID: Integer;
  vUpdateStatus : TUpdateStatus;
begin
  vUpdateStatus := pDataset.UpdateStatus;
  pDataset.ApplyUpdates;
  vLastID:=(pDataSet.DataBase as TSQLite3Connection).GetInsertID;
  if vUpdateStatus = usInserted then begin
    pDataset.Refresh;
    //Niebezpieczny!
    pDataSet.Last;
  end;
end;

procedure TDataModule1.SQLQuery1AfterPost(DataSet: TDataSet);
begin
  RefreshADatasetAfterInsert(Dataset as TSQLQuery); //Jeśli Twój DataSet jest posortowany według klucza podstawowego
end;  

procedure TDataModule1.SQLQuery2AfterPost(DataSet: TDataSet);
begin
  RefreshADatasetAfterInsert(Dataset as TSQLQuery, 'ID'); //Jeśli nie masz pewności, że DataSet jest zawsze posortowany według klucza podstawowego
end;

Vacuum i inne operacje, które należy wykonać poza transakcją

Wydaje 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 :)

  // commit any pending operations or use a "fresh" sqlconnection
  // zatwierdź wszelkie oczekujące operacje lub użyj „świeżego” sqlconnection
  Conn.ExecuteDirect('End Transaction');  // Zakończ transakcję rozpoczętą przez SQLdb
  Conn.ExecuteDirect('Vacuum');
  Conn.ExecuteDirect('Begin Transaction'); //Rozpocznij transakcję dla SQLdb

Używanie TSQLite3Dataset

W 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

Wymagania

  • Dla baz danych sqlite2 (starsze):
    • FPC 2.0.0 lub nowszy
    • Lazarus 0.9.10 lub nowszy
    • Biblioteka uruchomieniowa SQLite 2.8.15 lub nowsza*
  • Sqlite2 nie jest już utrzymywany, a pliku binarnego nie można znaleźć na stronie sqlite
  • Dla baz danych sqlite3:
    • FPC 2.0.2 lub nowszy
    • Lazarus 0.9.11 (rewizja svn) lub nowszy
    • biblioteka uruchomieniowa sqlite 3.2.1 lub nowsza (pobierz ją ze strony www.sqlite.org)

Przed rozpoczęciem projektu Lazarus upewnij się, że:

  • biblioteka sqlite jest albo
    • w katalogach systemowych lub
    • w katalogu plików wykonywalnych i katalogach Lazarus (lub bieżącego projektu) - ta opcja może działać tylko w systemie Windows
  • pod Linuksem umieść cmem jako pierwszy moduł w sekcji uses programu głównego
    • 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)

Jak używać (podstawowe użycie)

Zainstaluj pakiet znaleziony w katalogu /components/sqlite (zobacz instrukcje tutaj)

W czasie projektowania ustaw następujące właściwości:

  • FileName: ścieżka do pliku sqlite [wymagana]
  • TableName: nazwa tabeli użytej w instrukcji sql [wymagana]
  • SQL: instrukcja SQL select [opcjonalna]
  • SaveOnClose: Wartość domyślna to false, co oznacza, że ​​zmiany nie są zapisywane. Można to zmienić na true. [opcjonalna]
  • Active: Należy ustawić w czasie projektowania lub podczas uruchamiania programu. [wymagana]

Tworzenie tabeli (DataSet)

Kliknij 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.

Oto wszystkie typy pól obsługiwane przez TSqliteDataset i TSqlite3Dataset:

  • Integer
  • AutoInc
  • String
  • Memo
  • Bool
  • Float
  • Word
  • DateTime
  • Date
  • Time
  • LargeInt
  • Currency

Pobieranie danych

Po 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:

SQL := 'Select * from TABLENAME';

Wprowadzanie zmian do bazowego pliku danych

Aby 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)

Można to zrobić na dwa sposoby:

  • Ustaw właściwość PrimaryKey na nazwę pola klucza podstawowego
  • Dodaj pole AutoInc (jest to łatwiejsze, ponieważ TSqliteDataSet automatycznie obsługuje je jako klucz podstawowy)

Jeśli spełniony jest jeden z dwóch warunków, po prostu wywołaj

ApplyUpdates;
Note-icon.png

Uwaga: Jeśli obydwa warunki są ustawione, pole odpowiadające PrimaryKey jest używane do zastosowania aktualizacji.

Note-icon.png

Uwaga: 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.

Przykład Master/detail

Różne przykłady relacji master/detail (np. relacja pomiędzy klientem a zamówieniem):

  • ogólny sposób SQLDB na wykonanie tego przy użyciu właściwości DataSource:
  • Konkretny przykład TSQLite3 używający lokalizację: TSqlite3 Przykład wzorca Master.

Uwagi

  • 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).
  • Ten sam plik danych (właściwość Filename) może zawierać kilka tables/datasets
  • Kilka DataDets (różne kombinacje pól) można utworzyć jednocześnie przy użyciu tej samej tabeli
  • 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
  • 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ć
  • 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.

Ogólne przykłady można znaleźć w katalogu SVN fpc/fcl-db/src/sqlite

Zobacz także