Difference between revisions of "Firebird/ru"

From Free Pascal wiki
Jump to navigationJump to search
Line 192: Line 192:
 
'''To do: убедитесь, что это работает с гридами Lazarus и т. д..'''
 
'''To do: убедитесь, что это работает с гридами Lazarus и т. д..'''
  
=== Проблемы INSERT INTO...RETURNING/Не открытый курсор ====
+
=== Проблемы INSERT INTO...RETURNING/Не открытый курсор ===
  
 
Если вы попытаетесь сделать выборку SQL (например, Query.Open) в следущем SQL-запросе:
 
Если вы попытаетесь сделать выборку SQL (например, Query.Open) в следущем SQL-запросе:
Line 231: Line 231:
 
^
 
^
 
</syntaxhighlight>
 
</syntaxhighlight>
чтобы переложить заботу о генерации PK на плечи сервера.
+
чтобы переложить заботу о генерации PK на плечи сервера, передавая с клиента NULL-значение генератора (или не передавая его вообще, что будет восприниматься сервером, как NULL).
 
----
 
----
  

Revision as of 07:33, 3 October 2019

English (en) français (fr) русский (ru)

Databases portal

References:

Tutorials/practical articles:

Databases

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

Это руководство по использованию базы данных Firebird в Lazarus/FPC, с использованием Firebird с SQLDB (встроенная библиотека базы данных FPC/Lazarus). Другие методы доступа описаны в разделе Другие библиотеки Firebird.

Обзор

Firebird - это бесплатный сервер баз данных с открытым исходным кодом, который использовался и разрабатывался десятилетиями (он разрабатывался на основе базы данных Interbase 6, исходные коды которой были открыты компанией Borland). Он включает в себя расширенную поддержку операторов SQL (например, INSERT...RETURNING), хранимых процедур, триггеров и т.д. Вы можете написать скомпилированные библиотеки UDF (библиотеки пользовательских функций) для сервера в FreePascal, если вы хотите расширить и без того обширный список функций Firebird.

База данных требует очень мало ручной работы администратора баз данных после того, как она настроена, что делает ее идеальной для использования в малом бизнесе или для встроенного использования. При правильной настройке он может вырасти до терабайтного масштаба, хотя PostgreSQL может быть лучшим выбором для таких больших сред.

Firebird предлагает как встроенную (основанную на файлах), так и клиент-серверную базу данных - которую можно использовать без необходимости изменять одну строку кода в FPC/Lazarus. При использовании в качестве встроенной базы данных она предлагает более богатую поддержку SQL, чем SQLite, а также плавную миграцию в базу данных клиент-сервер, хотя SQLite сама по себе является вполне встроенной базой данных.

Последняя стабильная версия, Firebird 2.5 (прим.перев.: на момент перевода статьи - это версия Firebird 3.0.4), работает в Windows (32- и 64-разрядная версия), различных версиях Linux (32- и 64-разрядная версия), Solaris (Sparc и Intel), HP-UX (PA-Risc) и OSX.

В настоящее время сервер портируется на Android; он пока недоступен в Windows CE/Windows Mobile.

Поддержка Firebird в SQLDB компилятора довольно хорошая, сравнимая с уровнем поддержки PostgreSQL.

Документация

Официальная документация включена в FPC 2.6.2+: Документация SQLDB для IBConnection

Установка режимов клиент/сервер и встроенного режима сервера

Firebird может работать в режиме клиент/сервер и в режиме встроенного сервера.

Client/Server означает, что у вас где-то есть физический сервер Firebird: либо на локальной машине, либо на другой машине, доступной по вашей сети. Соединения с сервером проходят через TCP/IP; при указании соединения имя хоста содержит имя или IP-адрес. Серверу Firebird для "общения" с вашими компонентами доступа необходима fbclient.dll/fbclient.so.nnn (вместе с его файлами поддержки).

Embedded Firebird означает, что ваше приложение для доступа к базе данных Firebird на локальной машине загружает единственную библиотеку, которая является и сервером, и клиентской библиотекой Firebird "в одном флаконе". При указании строки соединения имя хоста всегда пусто (не указывается). Серверу Firebird для "общения" с вашими компонентами доступа необходима fbembed.dll/fbembed.so (вместе с его файлами поддержки). См. вики-страницу на Firebird embedded для более подробной информации.

Обратите внимание, что fbembed.dll может использоваться как для клиент-серверного, так и для встроенного использования, поэтому установка только этой dll может быть разумной задачей.


Прим.перев.: необходимо уточнить, что выше описанное справедливо для версий FB 1.5, FB 2.0, FB 2.1 и FB 2.5. Начиная с версии FB 3.0, режим используемого сервера зависит от строки подключения, а клиентская библиотека на все случаи жизни одна - все та же fbclient.dll/libfbclient.so.3.0.n (где n - номер билда версии FB).


Windows

Win64: пожалуйста, см. предупреждение здесь о нежелательном использовании некоторых версий FPC/Lazarus Win64.

Для Windows: (это относится ко всем драйверам базы данных SQLDB) необходимо иметь fbclient.dll (или fbembed.dll' ) и его поддержку dll, установленных в:

  • каталог проекта и каталог вывода исполняемого файла/каталог приложения (например, lib /что-то еще в каталоге вашего проекта)
  • или каталог в вашем PATH (не в системном каталоге)
  • Если вы хотите использовать системный каталог, пожалуйста, используйте официальный установщик и поставьте галочку «скопировать fbclient в системный каталог»

Как и для всех библиотек DLL (базы данных), разрядность библиотеки DLL должна соответствовать вашему приложению: используйте 32-разрядную библиотеку для 32-разрядной скомпилированной программы и 64-разрядную библиотеку для 64-разрядной программы.

Unix/Linux/OSX

В Linux/OSX/FreeBSD должна быть установлена ​​клиентская библиотека Firebird (например, вашим менеджером пакетов; установите обычный пакет и пакет -dev), или они должны быть прописаны в путях поиска библиотеки.

FPC ищет наиболее распространенные имена библиотек (например, libfbclient.so.2.5, libgds.so и libfbembed.so.2.5; пожалуйста, проверьте ibase60.inc, если ваша версия отличается). При желании можно указать имя библиотеки. Есть 2 способа сделать это:

  • использовать компонент TSQLDBLibraryLoader из sqldblib (FPC 2.7.1). Работает для всех компонентов коннектора SQLDB.
  • вызвать функцию
    function InitialiseIBase60(Const LibraryName : AnsiString) : integer;
    
    с правильным именем библиотеки (для этого может потребоваться использовать модуль ibase60dyn).

Примеры подключения

1. Пример для client/server:

Hostname: 192.168.1.1
* База данных находится на сервере с IP-адресом 192.168.1.1.
DatabaseName: /interdata/example.fdb  
* Имя файла базы данных - "example.fdb" в каталоге /interdata сервера (машина с IP-адресом 192.168.1.1).
Username: SYSDBA
Password: masterkey

2. Другой пример client/server:

Hostname: dbhost
* База данных находится на сервере с именем хоста dbhost
DatabaseName: F:\Program Files\firebird\examples\employee.fdb  
* Имя файла базы данных - "employee.fdb" в каталоге Program Files\firebird\examples на диске F: dbhost.
Username: SYSDBA
Password: masterkey

3. Пример для embedded-режима:

Hostname: <пустая строка>
* Оставляя имя хоста пустым, выбирается embedded-режим.
DatabaseName: test.fdb
* Файл базы данных "test.fdb" находится в каталоге запускаемого приложения (убедитесь, что fbembed.dll находится в каталоге исполняемого файла приложения)
Username: SYSDBA
* Для встроенного сервера вы должны указать имя пользователя ...
Password: <пустая строка> (прим.перев.: вообще-то, это может быть любая строка, в т.ч. и пустая)
* ... но не важно, какой пароль вы укажете.

Прим.перев.: выше приведенные примеры подразумевают, что используется порт по умолчанию 3050. Если номер порта отличается от стандартного (например, пусть будет 3051), то для каждого из выше приведенных примеров строка подключения (например, к утилите isql) соответственно будет выглядеть следующим образом:

SQL>connect '192.168.1.1/3051:/interdata/example.fdb' -user 'SYSDBA' -password 'masterkey';
SQL>connect 'dbhost/3051:F:\Program Files\firebird\examples\employee.fdb' -user 'SYSDBA' -password 'masterkey';
SQL>connect 'test.fdb' -user 'SYSDBA' -password '';


Начиная с версии FB 3 появилась возможность указывать другие протоколы коннекта:

  • INET-протокол (для TCP/IP) в виде строки <host>[/<port>]:<database file path or alias>

Тогда строка подключения (например, к утилите isql) для выше указанных примеров соответственно будет выглядеть так:

SQL>connect 'inet://192.168.1.1:3051:/interdata/example.fdb' -user 'SYSDBA' -password 'masterkey';
SQL>connect 'inet://dbhost:3051:F:\Program Files\firebird\examples\employee.fdb' -user 'SYSDBA' -password 'masterkey';
SQL>connect 'inet://test.fdb' -user 'SYSDBA' -password '';

INET-протокол поддерживает URL-стиль (для адресов IPv4 и IPv6) строки подключения вы виде шаблона [<protocol>://[<host>[:<port>]]]/<database file path or alias>. Тогда в строке подключения часть строки заменяется с inet:// на inet4:// или inet6:// соответственно. Например:

SQL>connect 'inet6://192.168.1.1:3051:/interdata/example.fdb' -user 'SYSDBA' -password 'masterkey';
Light bulb  Примечание: по умолчанию Firebird прослушивает нулевой адрес IPv6 (: :) и принимает все входящие соединения, будь то IPv4 или IPv6. Если эти адреса имеют ненулевое значение, то в строке подключения они обрамляются квадратными скобками, чтобы устранить двусмысленность при использовании двоеточия в качестве разделителя

.

Например, если IPv6 = 2014:1234::5, то строка подключения примет вид:

SQL>connect '[2014:1234::5]://192.168.1.1:3051:/interdata/example.fdb' -user 'SYSDBA' -password 'masterkey';

и далее по аналогии...

  • протокол NetBEUI, или WNET (именованные каналы) - только для Windows! - в виде строки \\<host>[@<port>]\<database file path or alias>.
  • протокол XNET для локальных подключений с использованием общей памяти.

Последние два протокола имеют строку подключения, аналогичную INET, только вместо inet:// подставляются wnet:// или xnet:// соответственно.

Более подробную информацию по нововведениям FB 3, в том числе и по протоколам коннекта можно посмотреть здесь.


Устранение проблем с доступом client/server

Убедитесь, что вы запустили сервер Interbase/Firebird на указанном вами IP-адресе/имени хоста сервера. Вы можете проверить подключение, подключившись к компьютеру через telnet. Firebird обычно слушает порт 3050:

telnet 192.168.1.1 3050

Вы должны увидеть что-то, может быть, просто пустой экран, но вы можете что-то напечатать. Это означает, что вы можете отправлять данные в базу данных Firebird.

Для получения дополнительной информации см. документацию Firebird.

Мониторинг событий

FPC/Lazarus поставляется с компонентом для мониторинга событий, поступающих из баз данных Firebird; см. TFBEventMonitor.

Программное создание объектов

Хотя для создания таблиц и т.д. можно использовать такие инструменты, как Flamerobin (прим.перев.: для windows, особенно русскоязычной, предпочтительнее использовать IBExpert), вы также можете создавать объекты БД программно/динамически, что может быть удобно, если вы хотите, чтобы ваши программы обновляли существующие схемы базы данных до новой схемы.

Вы можете использовать, например, TSQLQuery.ExecSQL для выполнения этой задачи:

Query.ExecSQL('CREATE TABLE TEST(ID INTEGER NOT NULL, TESTNAME VARCHAR(800))');
// Вам необходимо закомиттить транзакцию после DDL перед любыми инструкциями DML - SELECT, INSERT и т. Д.
//В противном случае SQL не увидит созданные объекты

Используйте для этих целей объект TSQLScript - см. TSQLScript.

Администрирование базы данных

У FPC/Lazarus есть компонент для администрирования базы данных; см. TFBAdmin

Общие проблемы и решения

Иногда использование Firebird в Lazarus кажется сложным. Пожалуйста, поищите решения ниже по тексту.

Попытка обновления доступного только для чтения столбца / полей COMPUTED BY

Если в вашей таблице Firebird есть поля COMPUTED BY (вычисляемые поля на стороне сервера), SQLDB не будет брать в расчет, что это поля только для чтения (из соображений производительности).

В этом случае автоматически сгенерированные операторы INSERTSQL, UPDATESQL могут привести к сообщениям об ошибках, таких как "attempted update of read-only column" (попытка обновления столбца только для чтения).Решение состоит в том, чтобы вручную указать, что данное поле не может быть обновлено после установки свойства SQL в TSQLQuery, что-то вроде:

// Отключаем обновление этого поля или поиск измененных значений, поскольку пользователь не может изменить его
sqlquery1.fieldbyname('full_name').ProviderFlags:=[];

Bigint: потеря точности

Если вы используете тип данных bigint (64-битное целое число со знаком) в Firebird, пожалуйста, используйте .AsLargeInt вместо .AsInteger для параметров:

// Предполагая, что идентификатор здесь bigint
sqlquery1.sql.text := 'insert into ADDRESS (ID) values (:ID)';
// делаем так:
sqlquery1.params.parambyname('ID').aslargeint := <любая qword- или 64-bit integer-переменная>;
// Не делайте так:
//sqlquery1.params.parambyname('ID').asinteger := <любая qword- или 64-bit integer-переменная>;
...

... в противном случае вы можете получить такие ошибки, как дубликат PK (первичного ключа) - при использовании bigint в качестве первичного ключа.

Логические типы данных

Версии Firebird ниже 3.0 не поддерживают логические типы данных.

По крайней мере, в транке FPC (2.7.1) этот тип данных можно эмулировать:

Используйте домен, который использует тип SMALLINT (другие целочисленные типы также могут работать - пожалуйста, протестируйте и настройте текст):

CREATE DOMAIN "BOOLEAN"
 AS SMALLINT
 CHECK (VALUE IS NULL OR VALUE IN (-1,0,1))
 /* -1 используется для совместимости с SQLDB FPC; 1 используется многими другими слоями доступа к данным */
;


Позвольте вашему полю/столбцу использовать этот тип домена, например

CREATE TABLE MYTABLE
(
...
  MYBOOLEANCOLUMN "BOOLEAN",
);
  • Теперь вы можете использовать .AsBoolean для присвоения значений полей и т.д.

To do: убедитесь, что это работает с гридами Lazarus и т. д..

Проблемы INSERT INTO...RETURNING/Не открытый курсор

Если вы попытаетесь сделать выборку SQL (например, Query.Open) в следущем SQL-запросе:

INSERT INTO PEOPLE (NICKNAME) VALUES ('Superman') RETURNING ID

и получаете что-то вроде этой ошибки:

Database error:  : Fetch :
 -Dynamic SQL Error
 -SQL error code = -504
 -Invalid cursor reference
 -Cursor is not open(error code: 335544569)

во время работы FPC 2.6.0 (которая поставляется с Lazarus 1.0) или ниже, вы, вероятно, столкнулись с ошибкой синтаксического парсера FPC SQLDB.

SQLDB считает, что выполняемый вами оператор является обычным оператором INSERT, который не возвращает данные. Очевидно, он должен возвращать данные. В более новом FPC для этого кода уже внесены исправления.

Если вы используете генераторы/последовательности для своих первичных ключей (как это делают многие), в качестве обходного пути вы должны сначала получить следующий порядковый номер:

SELECT NEXT VALUE FOR GEN_PEOPLEID FROM RDB$DATABASE /* Если имя вашего генератора GEN_PEOPLEID */

затем используйте это, чтобы сделать обычный INSERT. см. FAQ entry


Прим.перев.: вообще-то, мягко говоря, немного странный совет. Гораздо проще и безопаснее создать в БД триггер BeforeInsert примерно следующего содержания:

/* Trigger: TBL_PEOPLE_BI */
CREATE OR ALTER TRIGGER TBL_PEOPLE_BI FOR TBL_PEOPLE
ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
  /* генерируем новое значение поля, если вставляемое является NULL-значением */
  IF (NEW.ID IS NULL) THEN 
    NEW.ID = GEN_ID(GEN_PEOPLEID,1);
END
^

чтобы переложить заботу о генерации PK на плечи сервера, передавая с клиента NULL-значение генератора (или не передавая его вообще, что будет восприниматься сервером, как NULL).


Locate, кажется, не работает

Источник: Issue ##21988

При запуске locate в CHAR-полях с UTF8 (или, возможно, других многобайтовых символов), locate может не найти вашу запись.

Проблема в основном связана с используемой кодировкой UTF8 и тем, как Firebird сообщает о длине столбца. В случае UTF8 Firebird сообщает о максимальной длине столбца (в байтах) как 4 * «размер символа». Поэтому, если у вас есть столбец, определенный как char(8), Firebird сообщает 4*8=32.

Значения "добиваются" пробелами справа до этой длины 32. При поиске, скажем, «57200001», совпадений нет, потому что в поле фактически хранится «57200001 ........................» (с конечными пробелами, представленными здесь точками ).

Обходной путь: перепишите ваш select-запрос:

SELECT substring(THEFIELD from 1 for 8) AS THEFIELD ...

или

SELECT cast(THEFIELD as varchar(8)) as THEFIELD ...

или используйте VARCHAR-тип полей.

Light bulb  Примечание: эта проблема может возникать и для других баз данных, в зависимости от их возвращаемой длины.

Advanced transactions

Sources for this information/further reading:

Transaction isolation levels

If you want to, you can change the transaction isolation levels by adding a line in the transaction's Parameters property:

  • isc_tpb_read_committed: you see all changes committed by other transactions
  • isc_tpb_concurrency: also called Snapshot: you see database as it was when the transaction started. Has more overhead than isc_tpb_read_committed. Better than ANSI Serializable because it has no phantom reads.
  • isc_tpb_consistency: also called Table Stability: stable, serializable view of data, but locks tables. Unlikely you will need this

Example:

SQLTransaction1.Params.text:='isc_tpb_read_committed';

You can also add additional parameters that have an effect on the transaction (taken from the ibconnection.pp source file and [1]):

Access mode

This allow reads only or read/write

  • isc_tpb_read: read permission
  • isc_tpb_write: read+write permission

Lock resolution

  • isc_tpb_nowait: if another transaction is editing the record then don't wait
  • isc_tpb_wait: if another transaction is editing the record then wait for it to finish. Can mitigate "live locks" in heavy contention ([2]). See below for timeout value.

Table reservation

Deals with locking entire tables.

  • isc_tpb_shared: first specify this, then either lock_read or lock_write for one or more tables. Shared read or write mode for tables.
  • isc_tpb_protected: first specify this, then either lock_read or lock_write for one or more tables. Lock on tables; can allow deadlock-free operation at the cost of delayed transactions
  • isc_tpb_lock_read: Set a read lock. Specify which table to lock, e.g. isc_tpb_lock_read=CUSTOMERS
  • isc_tpb_lock_write: Set a read/write lock. Specify which table to lock, e.g. isc_tpb_lock_read=CUSTOMERS

Combinations:

  • Shared, lock_write: write transactions with concurrency or read committed isolation

can update the table. All transactions can read the table

  • Shared, lock_read: any transaction can read or update
  • Protected, lock_write: Other transactions cannot update the table. Only concurrency and

read committed transactions can read the table

  • Protected, lock_read: Other transactions cannot update the table. Any transaction can

read the table

Record versions

This setting is apparently only relevant for isc_tpb_read_committed isolation mode for records being modified by other transactions:

  • isc_tpb_no_rec_version: only newest record version is read. Can be useful for batch/bulk insert operations together with isc_tpb_read_committed)
  • isc_tpb_rec_version: the latest committed version is read, even when the other transaction has other uncommitted changes note: verify this. More overhead than isc_tpb_no_rec_version

Various options

For completeness, some more options appearing in the Firebird/Interbase FPC code. You will likely only ever use isc_tpb_no_auto_undo to speed up batch inserts/edits.

  • isc_tpb_exclusive (apparently translates to protected in Firebird, see [3])
  • isc_tpb_verb_time (Related to deferred constraints, which could execute at verb time or commit time. Firebird: not implemented, always use verb time)
  • isc_tpb_commit_time (Related to deferred constraints, which could execute at verb time or commit time. Firebird: not implemented, always use verb time)
  • isc_tpb_ignore_limbo (ignores the records created by transactions in limbo. Limbo transactions are failing two-phase commits in multi-database transactions. Unlikely that you will need this feature)
  • isc_tpb_autocommit (autocommit this transaction: every statement is a separate transaction. Probably specifically for JayBird JDBC driver.)
  • isc_tpb_restart_requests (apparently looks for requests in the connection which had been active in another transaction, unwinds them, and restarts them under the new transaction.)
  • isc_tpb_no_auto_undo (disable transaction-level undo log, handy for getting max throughput when performing a batch update. Has no effect when only reading data.)
  • isc_tpb_lock_timeout (specify number of seconds to wait for lock release, if you use isc_tpb_wait. If this value is reached without lock release, an error is reported.)

Firebird and ISO transactions

Firebird transaction do not map 1 to 1 to ISO/ANSI transaction levels. An approximation is:

  • ISO Read Committed=READ COMMITTED+RECORD_VERSION
  • ISO Read Committed=READ COMMITTED+NO RECORD_VERSION
  • ISO Repeatable Read=SNAPSHOT (also known as CONCURRENCY)
  • ISO Serializable=SNAPSHOT TABLE STABILITY (also known as CONSISTENCY)

Common combinations

Default is (probably, will have to check) read committed.

Batch/bulk insert

isc_tpb_read_committed and isc_tpb_no_rec_version could be a good combination: it allows other transactions to function while the batch is going on.

Read only transaction

If you want to only have read access to the database, you can do so by setting these transaction parameters:

  • isc_tpb_read
  • isc_tpb_read_committed
  • isc_tpb_rec_version
  • nowait

This combination will not block garbage collection, which is a good thing. Source: [4]

Note: the Firebird FAQ indicates you will need write access to the database file even if you only read from it, unless you set the database read-only flag (e.g. using gfix).

Links and more information

The list below shows links to more information on Firebird and related tools.

Lazarus Firebird samples

Tools

  • FlameRobin Flamerobin site Open source GUI tool to manage Firebird, available for Linux, Windows and Mac OSX. Highly recommended.
  • Turbobird Turbobird site Open source GUI tool to manage Firebird. Written with Lazarus using TIBConnection
  • ibconsole : Tool to manage Firebird an Interbase Databases with a GUI, available for Windows and Linux
  • Lazarus Data Desktop - included in the Lazarus repository (found in the 'tools/lazdatadesktop/' directory)
  • LazSQLX Multi-database open source database management tool. Written with Lazarus using both SQLDB and Zeos components. Includes support for Firebird.
  • tiSQLEditor - included in the "Support Apps" directory of the tiOPF repository. It is a tool used to write SQL with some code completion support, can run scripts, execute upgrade scripts for applications from one build to a later build, has various handy copy and paste functions for Object Pascal applications, has many features that are useful to tiOPF (creates Object Pascal code templates from query results, for tiOPF's visitor classes), export query results to CSV etc.

Firebird

  • The Firebird RDBMS Firebird site. This site also contains a lot of documentation on Firebird.
  • Firebird FAQ [6]. Handy site that shows e.g. differences with other RDBMS.
  • New site that shows how to use the latest tools and LibreOffice, FPC to be added soon Firebird