Автор: delphi | 14.12.2007 в 7:19 | Рубрики: Базы данных

Я пытаюсь преобразовать мою базу данных на Oracle в базу данных local Interbase server. Все таблицы Oracle ссылаются на имя схемы. Interbase поддерживает такого типа имена схем?

Нет, Interbase не использует понятие классификатора таблицы (владельца), как это делают другие сервера, например, Oracle или Sybase. Наилучшее решение в этом случае - использование директив компиляции, позволяющее контролировать соглашение о стиле имен Oracle или Interbase, используемое в генерируемом .exe-файле.

Также, Delphi читает все атрибуты Oracle типа Number и конвертирует их в FloatField. Interbase при этом использует тип SmallIntField. Так, для преобразования необходимо пройтись по всем таблицам, удалить поля и затем снова их добавить. Можно это сделать как-то по-человечески?

Если я правильно понял то, что вы хотели сказать, то этот вопрос относится к специфике Interbase. Например, Interbase использует короткое поле (short field) с масштабированием вместо реального типа, если заданная при создании таблицы точность не превышает 10. [например, CREATE TABLE xxx (FLOATFIELD NUMERIC (5, 2)) обычно означает реальный тип с точностью 5 цифр с 2-мя цифрами после запятой. Но Interbase знает, что сможет поместить 5 цифр в короткое поле, поэтому она создаст короткое поле и запись и смасштабирует его с коэффициентом 2.] Проблема в следующем: BDE “спрашивает” Interbase о полях таблицы и их типах, Interbase честно рапортует, что поля имеют тип short, т.е. они “короткие”. Но BDE ничего не знает о масштабировании.

Чтобы обойти этот неприятный момент, необходимо создать поле с точностью более 10, заставляя Interbase делать поля реального, а не короткого типа.

Могу ли я менять один тип SQL на другой, или это - несбыточная мечта?

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

Существует ли возможность инкапсуляции общего кода для работы с базой данных от специфических реализаций конкретных версий баз, что позволило бы клиенту легко переходить от одного типа таблиц к другому?

Как я уже говорил выше: директивы компилятора.

Hаши баги мы для совместимости сохраним в следующих версиях.

Решение найдено. Прочитай сам и передай товарищу:

Надо запустить regedit, и открыть ключ

HKEY_LOCAL_MACHINE\Environment
Там есть строка PATH. Так вот иногда она почему-то становится не строкой, а еще чем-то. Ее надо убить, и пересоздать как строку, прописав туда прежнее содержимое (в виде строки).

Программа “Наша цель - коммунизм!” выполнила недопустимую операцию и будет закрыта. В случае повторной ошибки обращайтесь к разработчику.

Располагайте DLL в каталоге Interbase/Bin, или в одном из каталогов, в которых ОС обязательно будет произведен поиск этой библиотеки (для Windows это %SystemRoot% и %Path%);

При декларировании функции не следует указывать расширение модуля (в Windows по умолчанию DLL):
declare external function f_SubStr
cstring(254), integer, integer
returns
cstring(254)
entry_point “Substr” module_name “UDF1″
Где UDF1 - UDF1.DLL.

{ **** UBPFD *********** by delphibase.endimus.com ****
>> Программное сжатие размера файла базы Interbase

Предназначена для “сжатия” базы данных IB. Входные параметры: база данных,
имя и пароль к серверу IB. Возвращаемое значение: true - функция выполнилась
успешно, false - ошибка во время выполнения функции. Для работы использует
утилиту gbak.exe ииз поставки InterBase Читать полностью…

{
This unit creates a database on a Interbase-Server at run-time.
The IBConsole is no longer needed.
You can execute an SQL script to create tables.
Try it out!
}

{
Diese Unit erstellt eine Datenbank auf einem Interbase - Server zur Laufzeit des Programms.
Es wird nicht mehr die IBConsole gebraucht.
Dazu kann man im Memo noch ein SQL - Skript ablaufen lassen zum erstellen der Tabellen.
Probiert es einfach aus.
}

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ZTransact, ZIbSqlTr, DB, ZQuery, ZIbSqlQuery,
ZConnect, ZIbSqlCon;

type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Button2: TButton;
ZIbSqlQuery1: TZIbSqlQuery;
ZIbSqlTransact1: TZIbSqlTransact;
ZIbSqlDatabase1: TZIbSqlDatabase;
Button3: TButton;
procedure Button1Click(Sender: TObject); // Caption/ Beschriftung : Create Database
procedure Button2Click(Sender: TObject); // Caption/ Beschriftung : SQL-Anweisung
procedure Button3Click(Sender: TObject); // Caption/ Beschriftung : Drop Database
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

// Creating the database
// Hier wird durch drucken des Buttons die Datenbank erstellt
//———————————————————————
procedure TForm1.Button1Click(Sender: TObject);
begin
ZIbSqlDatabase1.Database := ‘< >’;// Path to Database
ZIbSqlDatabase1.Host := ‘testserver’;
ZIbSqlDatabase1.Password := ‘masterkey’;
ZIbSqlDatabase1.Login := ‘SYSDBA’;
ZIbSqlDatabase1.CreateDatabase(”);
end;

// Execute the SQL-Script in the memo
// Hier wird durch drucken des Buttons das SQL-Skript im Memo ausgefuhrt
//———————————————————————-
procedure TForm1.Button2Click(Sender: TObject);
begin
ZIbSqlDatabase1.Database := ‘< >’; // Path to Database
ZIbSqlDatabase1.Host := ‘testserver’;
ZIbSqlDatabase1.Password := ‘masterkey’;
ZIbSqlDatabase1.Login := ‘SYSDBA’;
ZIbSqlQuery1.SQL.Clear;
ZIbSqlQuery1.SQL.AddStrings(memo1.Lines);
ZIbSqlQuery1.ExecSQL;
end;

// Deleted the database
// Hier wird durch drucken des Buttons die Datenbank komplette geloscht
//———————————————————————
procedure TForm1.Button3Click(Sender: TObject);
begin
ZIbSqlDatabase1.Database := ‘< >’; // Path to Database
ZIbSqlDatabase1.Host := ‘testserver’;
ZIbSqlDatabase1.Password := ‘masterkey’;
ZIbSqlDatabase1.Login := ‘SYSDBA’;
ZIbSqlDatabase1.DropDatabase;
end;

end.

Автор: delphi | в 7:19 | Рубрики: Базы данных

procedure TVCLScanner.PostUser(const Email, FirstName, LastName: WideString);
var
Connection: TSQLConnection;
DataSet: TSQLDataSet;
begin
Connection := TSQLConnection.Create(nil);
with Connection do
begin
ConnectionName := ‘VCLScanner’;
DriverName := ‘INTERBASE’;
LibraryName := ‘dbexpint.dll’;
VendorLib := ‘GDS32.DLL’;
GetDriverFunc := ‘getSQLDriverINTERBASE’;
Params.Add(’User_Name=SYSDBA’);
Params.Add(’Password=masterkey’);
Params.Add(’Database=milo2:D:\frank\webservices\umlbank.gdb’);
LoginPrompt := False;
Open;
end;
DataSet := TSQLDataSet.Create(nil);
with DataSet do
begin
SQLConnection := Connection;
CommandText := Format(’INSERT INTO kings VALUES(”%s”,”%s”,”%s”)’,
[Email, FirstN, LastN]);
try
ExecSQL;
except
end;
end;
Connection.Close;
DataSet.Free;
Connection.Free;
end;

Автор: delphi | в 7:19 | Рубрики: Базы данных

Пример библиотеки:

library nikelutils

uses SysUtils, Classes;

function MaxInt(var Int1, Int2: Integer): Integer;
far cdecl export;
begin
if (Int1 > Int2) then
Result := Int1
else
Result := Int2;
end;

function MinInt(var Int1, Int2: Integer): Integer;
far cdecl export;
begin
if (Int1 < Int2) then
Result := Int1
else
Result := Int2;
end;

exports
MaxInt;
MinInt;

begin
end.

А это пишим в базе:

DECLARE EXTERNAL FUNCTION MAXINT INTEGER, INTEGER
RETURNS INTEGER BY VALUE
ENTRY_POINT “MaxInt” MODULE_NAME “nikelutils.dll”;

DECLARE EXTERNAL FUNCTION MININT INTEGER, INTEGER
RETURNS INTEGER BY VALUE
ENTRY_POINT “MinInt” MODULE_NAME “nikelutils.dll”;

Автор: Denis Alexandrovich Ivanov

- Чем схожи занимающийся сексом и юзер?
- И тот и другой входят и выходят.
- А кто при этом получает удовольствие?
- Скорее всего первый и Билл Гейтс.

Как сделать инсталятор, который прописывал бы пользователя в Interbase? BDE при этом не нужна совсем.

1. При помощи InstallShieldExpress формируется проект, который включает в себя установку Interbase Server.
2. После установки Interbase запускаешь программу, написанную на Delphi 6, которая добавляет нового пользователя Interbase
Читать полностью…

{ **** UBPFD *********** by delphibase.endimus.com ****
>> Шифрование текстовых полей таблицы Interbase

Простенько но шустро шифрует текстовую строку VarChar в текстовую
строку VarChar, пригодную для сохранения в текстовом поле базы Interbase.
НЕ ЗАТРАГИВАЕТ ПРОБЕЛЫ!
Метод генерации (в начале) и изменения ключа (в 2-местах!) в вашей программе
лучше изменить от исходного в сторону усложнения, но не трогать “And 127″ в конце.
Для работы с Char возможно стоит добавить “Trim(S1);” в самое начало.
Читать полностью…

(Это очень полезно при прямой работе с IB из различного CASE-инструментария, типа PowerDesigner или ErWIN)

Чтобы не писать каждый раз COLLATE, я сделал следующее:

Создал сохранённую процедуру
create procedure fix_character_sets
as
begin
update
rdb$character_sets
set
rdb$default_collate_name = ‘PXW_CYRL’
where
rdb$character_set_name = ‘WIN1251′
and
rdb$default_collate_name = ‘WIN1251′
;
end
Запустил ее один раз.

Создаю таблицы без указания COLLATE.

После восстановления из архива, запускаю еще раз.

Дата + время - DATE.
Только дата - TODAY.
Только время - DATE-TODAY.

Автор: delphi | в 7:19 | Рубрики: Базы данных

Вежливое обращение к Компьютеру: “Ваше Висючество!”

1. Для Yaffil или FireBird последних билдов - ничего не надо, кроме gds32.dll в директориях поиска библиотек.

2. Для IB5, IB6 или старого FB первых билдов - надо дополнительно прописать в файле services строчку “gds_db 3050/tcp” {файл должен завершаться пустую строкой}.

3. Для IB5, дополнительно к п.2., добавить в ключ реестра:

HKLM\SOFTWARE\InterBase Corp\InterBase\CurrentVersion\RootDirectory

строковое значение - имя папки, в которой лежит файл ib_license.dat

4. В случае медленного подключения клиентов в сети TCP/IP попробуйте прописать адреса IB серверов в файле HOSTS.

{ **** UBPFD *********** by delphibase.endimus.com ****
>> Назначение прав пользователей на таблицу

Какое может быть описание? И так все понятно. Кто делает эти формы?

Зависимости: uses IBQuery,IBDataBase,SysUtils
Автор: Dracula, dracula@krruda.dp.ua, Krivoy Rog
Copyright: Dracula
Дата: 28 января 2003 г.
***************************************************** }

unit IBRights;
interface

uses IBQuery, IBDataBase, SysUtils;

type
TIBUserRights = record
sel: Boolean;
ins: Boolean;
upd: Boolean;
del: Boolean;
exe: Boolean;
end;

function GetUserRights(UserName, Relation: string; IBDb: TIBDataBase):
TIBUserRights;
var
Rights: TIBUserRights;

implementation

function GetUserRights(UserName, Relation: string; IBDb: TIBDataBase):
TIBUserRights;
var
Qr: TIBQuery;
Tr: TIBTransaction;
begin
if Assigned(IBDb) then
begin
Tr := TIBTransaction.Create(nil);
try
Tr.DefaultDatabase := IBDb;
Qr := TIBQuery.Create(nil);
Qr.Database := IBDb;
Tr.StartTransaction;
Qr.Close;
Qr.Sql.Clear;
Qr.Sql.Add(’select RDB$USER,RDB$PRIVILEGE,RDB$RELATION_NAME ‘ +
‘from RDB$USER_PRIVILEGES ‘ +
‘where upper(RDB$USER)=:AUser ‘ +
‘and upper(RDB$RELATION_NAME)=:ARelation’);
Qr.Prepare;
Qr.Params.ParamValues[’AUser’] := AnsiUpperCase(UserName);
Qr.Params.ParamValues[’ARelation’] := AnsiUpperCase(Relation);
Qr.Open;
while not Qr.eof do
begin
if Copy(Trim(Qr.FieldByName(’RDB$PRIVILEGE’).AsString), 1, 1) = ‘S’ then
Rights.sel := true
else
Rights.sel := false;
if Copy(Trim(Qr.FieldByName(’RDB$PRIVILEGE’).AsString), 1, 1) = ‘I’ then
Rights.ins := true
else
Rights.ins := false;
if Copy(Trim(Qr.FieldByName(’RDB$PRIVILEGE’).AsString), 1, 1) = ‘U’ then
Rights.upd := true
else
Rights.upd := false;
if Copy(Trim(Qr.FieldByName(’RDB$PRIVILEGE’).AsString), 1, 1) = ‘D’ then
Rights.del := true
else
Rights.del := false;
if Copy(Trim(Qr.FieldByName(’RDB$PRIVILEGE’).AsString), 1, 1) = ‘X’ then
Rights.exe := true
else
Rights.exe := false;
if Copy(Trim(Qr.FieldByName(’RDB$PRIVILEGE’).AsString), 1, 1) = ‘R’ then
//Rights.ref:=true else Rights.ref:=false;
begin
Rights.sel := true;
Rights.ins := true;
Rights.upd := true;
Rights.del := true;
Rights.exe := true;
end;
Qr.Next;
end;
Qr.Close;
Tr.Commit;
Qr.Free;
finally
Tr.Free;
end;
end;
Result := Rights;
end;

end.
Пример использования:

uses….., IBRights;
……
var
rights: TIBUserRights;

implementation
…..
begin

rights := GetUserRights(DllLogin, NameTable, IBDataBase);
…..
end;

procedure TForm1.ReadOLE;
var
BS: TBlobStream;
begin
BS := TBlobStream.Create(Table1BLOBFIELD_BLOB, bmRead);
OLEContainer1.LoadFromStream(BS);
BS.Free;
end;

procedure TForm1.WriteOLE;
var
BS: TBlobStream;
begin
BS := TBlobStream.Create(Table1BLOBFIELD_BLOB, bmWrite);
OLEContainer1.SaveToStream(BS);
BS.Free;
end;

Я пытаюсь сгенерировать последовательный ключ для первичной ключевой колонки, но LIBS мне отвечает “nested select is not support in this context.” (вложенный выбор не поддерживается в данном контексте.)

Как насчет:

CREATE TRIGGER AUTOINCREMENT FOR MYTABLE
BEFORE INSERT AS
DECLARE VARIABLE new_key INTEGER;
BEGIN
UPDATE AUTOKEYS
SET KEY_VALUE = KEY_VALUE + 1
WHERE (KEY_ID = “A”);
SELECT KEY_VALUE
FROM AUTOKEYS
WHERE KEY_ID = “A”
INTO :new_key;
new.my_key_column = new_key;
END ^

Я пытаюсь добавить запись в таблицу InterBase, содержащую триггеры и blob-поля, тем не менее, всякий раз при выполнении метода “post” после установки (”append”) значений, я получаю ошибку: ‘Record/Key deleted.’ (запись/ключ удален).

Вот реальный пример того, как я обошел эту проблему:

Определение хранимой процедуры:

Create Procedure NewEmployeeKey Returns ( EmployeeKey Integer ) as
begin
EmployeeKey = Gen_Id( gnEmployeeKey, 1 ) ;
end
Определение триггера:
Create Trigger SetEmployeeKey for tbEmployee Active Before Insert Position 0 as
begin
if ( New.EmployeeKey is Null ) then begin
Execute Procedure NewEmployeeKey Returning_Values New.EmployeeKey ;
end
end
Код Delphi для использования в обработчике события OnNewRecord, или AfterInsert, или BeforePost:

{ qyProviderData - это tQuery }
{ spProviderKey - это tStoredProc }

if qyProviderData.State in [dsInsert] then
begin
spProviderKey.ExecProc ;
qyProviderData.FieldByName( ‘ProviderKey’ ).AsInteger :=
spProviderKey.ParamByName( ‘ProviderKey’ ).AsInteger ;
end ; { if }

Это все, что вам необходимо. Хранимая процедура возвращает следующее сгенерированное значение. Триггер это гарантирует, даже если бы данные не были доступны из вашей Delphi-программы, первичный ключ все еще назначает значение. В Delphi-коде, я полагаю, вы могли бы проверять наличие пустого поля первичного ключа вместо .State in [dsInsert], хотя это то же работает.

Оказывается, что Interbase триггер “before insert” срабатывает только после того, как запись “запостится” из Delphi приложения. В связи с чем становится невозможным увеличение автоинкрементальных ключевых полей. Есть решение?

Большинство программистов решило эту проблему созданием хранимой процедуры (stored procedure), позволяющей от InterBase получить следующий номер и поместить его в вашу запись посредством метода onBeforePost или onNewRecord.

Используйте компонент TDatabase. В строках Params пропишите:

USER NAME=sysdba
PASSWORD=masterkey

Затем установите свойство компонента TDataBase LoginPrompt в False.
После этого, с помощью свойства DataBaseName, вы должны создать прикладной псевдоним (Alias) и связать TQuery/TTable с вашим компонентом TDataBase.

Всем известно, что возможности interbase можно расширить за счет написания пользовательских функций UDF. Но почему на Free Pascal?
Есть ряд веских причин.

1. При переносе Вашего сервера на другую платформу, например, с win32 на FreeBSD или Linux, возникает проблема переноса также и UDF. Как известно, есть дистрибутивы Free Pascal на эти платформы.
2. В Pascal имеется очень удачная концепция библиотеки (library). При переносе на другую платформу достаточно перекомпилировать библиотеку, и она будет работать. При написании аналогичной библиотеки на с приходится переделывать make файл. Читать полностью…

UPDATE RDB$FIELDS
SET RDB$CHARACTER_SET_ID = 52
WHERE RDB$FIELD_NAME = ‘RDB$SOURCE”

Как гарантированно сделать backup/restore БД InterBase с опцией ‘Replace existing database’ и записями протоколов в файлы с гарантированным отстрелом пользователей?

Att.bat:
at 01:00 /INTERACTIVE “e:\IB_DATA\BR.BAT”
BR.bat:
del e:\IB_DATA\b.txt
del e:\IB_DATA\r.txt
del e:\ib_data\AR_IB.PRV
del e:\IB_DATA\AR_IB.GBK
d:\ib_42\bin\gfix -shut -force 1 e:\ib_data\AR_IB.GDB -user “SYSDBA” -password “oooo”
net stop “InterBase Server”
copy e:\ib_data\AR_IB.GDB e:\ib_data\AR_IB.PRV
net start “InterBase Server”
d:\ib_42\bin\gbak e:\ib_data\AR_IB.GDB e:\ib_data\AR_IB.GBK -user “SYSDBA” -password “oooo” -B -L -Y “e:\IB_DATA\b.txt”
d:\ib_42\bin\gbak e:\ib_data\AR_IB.GBK e:\ib_data\AR_IB.GDB -user “SYSDBA” -password “oooo” -P 4096 -V -R -Y “e:\IB_DATA\r.txt”
Sergey Klochkovski

Автор: admin | в 2:14 | Рубрики: Базы данных

InterBase BLOB-поля отличаются от полей другого типа. Реально BLOB-поле имеет несколько подтипов (sub-type). Знание подтипа BLOB-поля существенно при создании приложения для работы с базами данных, которые включают в себя InterBase BLOB-поля. BLOB-поля могут быть трех подтипов: подтип 0, подтип 1 (два встроенных подтипа), и пользовательский подтип.

Подтип 0 BLOB-поля создается при выполнении команды CREATE, когда подтип не определен. Для ясности, в синтаксисе SQL все же рекомендуется явно указывать, что BLOB-поле относится к подтипу 0. Данный подтип BLOB-поля используется для хранения бинарных данных. InterBase не производит никакого анализа хранимых данных, он просто хранит данные в BLOB-поле байт-за-байтом. Наиболее частое применение BLOB-полей в приложениях Windows - хранение двоичных данных изображения, обычно отображаемое впоследствие компонентом TDBImage. Для этой цели подходит или BLOB-поле подтипа 0, или BLOB-поле пользовательского подтипа.
Читать полностью…