IBEScript – легкость работы с Firebird через скрипт

IBEScript -прекрасная утилита от компании HK-Software. Эта же компания написала легендарный IBExpert – инструмент для администрирования и разработки баз данных Firebird и Interbase.
И так, что такое IBEScript? Эта приложение является значительно расширенным аналогом isql.exe (консольная утилиты предоставляющей доступ через SQL до баз Firebird).
Кроме дублирования функционала isql-утилиты, IBEScript расширен специальными командами под названием IBEBlock. Количество команд переваливает за 3 сотни. Понятно, что такое количество новых функций делает из утилиты предназначенную в первую очередь для написания хранимых процедур и простых SQL запросов – мощный инструмент на многие случаи жизни.
Но в основном IBEScript используется для написания скриптов которые работают с базами Firebird. И очень жалко что не для всех баз данных такой инструмент сущесвует.
Для тех, кто будет читать дальше, поясняю что все здесь написано рассчитано на людей знакома с хранимыми процедурами Firebird. Приступим.

Скрипт начинается как хранимая процедура в Firebird

execute ibeblock     
as
begin
	-- текст скрипта
end

Для того что бы его запустить создаем bat-файл следующего содержания:

Cd .
IBEScript.exe "script.ibb" -Dc:db.fbd -Usysdba –Pmasterkey
Pause

script.ibb – это путь до скрипта.
Далее идут параметры подключения (-Dc:db.fbd -Usysdba –Pmasterkey). Их можно не указывать если вы подключайтесь к базе в самом скрипите или например берете эти данные из ini файла (А это IBEBlock позволяет!)

И так вы можете теперь позапускать скрипт. Он правда ничего не делает 🙂
Рассмотрим некоторые примеры. Качаем файл.

Script1.ibb
Показывает возможность логирования действий скрипта. Логирование всегда полезно)

execute ibeblock     
as
begin
    -- лог файл с информацие
    log_file = ibec_GetRunDir() || 'script.log';
    if(ibec_FileExists(:log_file)) then
        begin
            -- файл открываем
            log_fs = ibec_fs_OpenFile(:log_file, __fmOpenReadWrite); 
            ibec_fs_Seek(log_fs,0,__soFromEnd);
        end
    else -- файл создаем		
        log_fs = ibec_fs_OpenFile(:log_file, __fmCreate); 
	
    s = ibec_Now()||' - Начало работы скрипта';
    ibec_Progress(s);
    ibec_fs_WriteLn(log_fs, s);		
end

Тут используются следующие ibeblock функции:

  • ibec_GetRunDir – возвращает каталог из которого запущен IBScript или IBExprt выполняющий текущий скрипт.
  • ibec_FileExists – проверка наличия файла
  • ibec_fs_OpenFile – открытие файла или создаем его
  • ibec_fs_Seek – Перейти к определенной позиции в файле. В нашем случае в конец файла.
  • ibec_fs_WriteLn – пишем в файл строку с переходом на следующую
  • ibec_Now – текущее время и дата

script2.ibb
Предположим вам понадобилось перенести часть данных из одной базы в другую. Данный скрипт показывает, как организовать подключение в данном случае.
Я уже упомянул выше, что при запуске скрипта можно не упоминать параметры подключения к базе. IBEScript позволяет передавать переменные из командной строки в скрипт. Это дествительно делает скрипты гибче.

Запустите base_create.cmd для создания тестовых баз: c:base_new.fdb и c:base_old.fdb
base_new – пустая, а base_old – с данными.

Теперь посмотрим, как запускается скрипт который работает с этими базами:

set old_base=127.0.0.1:C:base_new.fdb
set new_base=127.0.0.1:C:base_old.fdb
IBEScript.exe "script2.ibb" -GOldBase="%old_base%" -GNewBase="%new_base%"

Для того что бы получить эти данные в скрипите пишем:

-- получаем пути для соединения
OldBase = ibec_GetGlobalVar('OldBase', '127.0.0.1:C:BASE_OLD.FDB');
NewBase = ibec_GetGlobalVar('NewBase', '127.0.0.1:C:BASE_NEW.FDB');

Затем создаем строку подключения к базе и само подключение:

StrConnect = 'DBName="'||OldBase||'"; User=SYSDBA; Password=masterkey; Names=WIN1251; SqlDialect=3;';    
DBOld = ibec_CreateConnection( __ctFirebird, StrConnect);

StrConnect = 'DBName="'||NewBase||'"; User=SYSDBA; Password= masterkey; Names=WIN1251; SqlDialect=3;';
DBNew = ibec_CreateConnection( __ctFirebird, StrConnect); 

Теперь для того что бы обратится к одной или к другой базе нам достаточно написать предварительно ibec_UseConnection(ИмяСоединеия).
Скрипт полностью.

execute ibeblock     
as
begin
    -- лог файл с информацие
    log_file = ibec_GetRunDir() || 'script2.log';
    if(ibec_FileExists(:log_file)) then
        begin
            -- файл открываем
            log_fs = ibec_fs_OpenFile(:log_file, __fmOpenReadWrite); 
            ibec_fs_Seek(log_fs,0,__soFromEnd);
        end
    else -- файл создаем		
        log_fs = ibec_fs_OpenFile(:log_file, __fmCreate); 
	
    s = ibec_Now()||' - Начало работы скрипта';
    ibec_Progress(s);
    ibec_fs_WriteLn(log_fs, s);		
	
    -- получаем пути для соединения
    OldBase = ibec_GetGlobalVar('OldBase', '127.0.0.1:C:BASE_OLD.FDB');
    NewBase = ibec_GetGlobalVar('NewBase', '127.0.0.1:C:BASE_NEW.FDB'); 
	
    -- создаем соединения с базой
    StrConnect = 'DBName="'||OldBase||'"; User=SYSDBA; Password=z; Names=WIN1251; SqlDialect=3;';    
    DBOld = ibec_CreateConnection( __ctFirebird, StrConnect); 

    StrConnect = 'DBName="'||NewBase||'"; User=SYSDBA; Password=z; Names=WIN1251; SqlDialect=3;';
    DBNew = ibec_CreateConnection( __ctFirebird, StrConnect); 	

    -- указываем что работаем со старой базой
    ibec_UseConnection(DBOld);	
	
    for select p.ID, p.NAME
	from partner p
	into :id, :name
    do begin				
        s = :id||' - '||:name;
        ibec_Progress(s);	
        ibec_fs_WriteLn(log_fs, s);
		
        -- переносим данные данные в новую базу
        ibec_UseConnection(DBNew);	
        INSERT INTO PARTNER (ID, NAME) VALUES (:id, :name);
        ibec_UseConnection(DBOld);	
    end
    
    -- сохраняем все изменения
    commit;
	
    s = ibec_Now()||' - Закончил работату скрипт';
    ibec_Progress(s);
    ibec_fs_WriteLn(log_fs, s);			
end

Команда commit подтверждает изменения. Если ее не поставить транзакции не будут подтверждены.

IBEScript – легкость работы с Firebird через скрипт: 14 комментариев

  1. fraks

    Точности ради, IBEScript не копирует функциональность isql.

    Он дает возможность выполнения скрипта IBExpert без наличия самого IBExpert.

    А так, IBEScript кое что не умеет, по сравнению с isql — например в нем нет интерактивного режима. Понятно, что оно там и не надо — есть же сам IBE.

    Сам юзаю IBEScript для накатывания патчей на базы в филиалах фирмы. Пишу скрипт, к нему инструкцию по применению — и местные админы-эникейщики справляются с этим делом.

  2. BoriMor

    Насчет интерактивного режима в isql — правы.
    Я им не пользовался поэтому упустил из виду.

  3. Юрий

    Люди добрые!!! Подскажите пожалуйста, Мне не нужно написанный скрипт запускать при промощи IBEScript, а нужно запустить с тригера в IBExpert. есть ли такая возможность, если да то какой командой?!

    Скрипт использует функцию отсылки email ibec_smtp_SendMail()

  4. BorisMor

    Юр, не уверен что идея отправки почты через базу это хорошая идея)
    Ф-ции ibec_* внедрить в PSQL не удастся. Вам надо смотреть в сторону udf.

  5. Юрий

    Спасибо… Я уже понял что это практически не реально, просто скрипт делает анализ базы и когда появляется новая запись в таблице должен отправить почту, получается необходимо для решения такой вроде простой задачи необходимо писать внешнее приложение которое к примеру раз в минуту будет запускать скрипт… А для чего же еще тогда нужна функция ibec_smtp_SendMail() немогу понять…??? (((

  6. fraks

    IBExpert — и IBEScript -это и есть внешнее приложение.
    Конструкции ibec_* — это не конструкции сервера, это внутренние конструкции IBExpert/IBEScript, к собственно серверу они не имеют никакого отношения.

    По поводу новая запись — новая почта — путь тупиковый. Что если вставили 10000 записей? Получится 10000 писем, а кто их будет читать?

    Кстати, «скрипт» — сервером тоже не выполняется. Сервер может выполнять либо отдельные команды либо команды в составе Stored Procedure, или сейчас есть еще возможность выполнить Execure Block что по сути так же процедура только на сервере не хранится.

    Но те скрипты которые выполняет IBExpert — это другие скрипты, их выполняет не сервер. IBExpert разбирает скрипт по командам и те что предназначены к выполнению сервером — посылает на сервер. А те команды которые для самого IBExpert — выполняет сам. ibec_* — это как раз такие команды.

  7. fraks

    Вообще говоря если стоит именно такая задача — поймать событие — то надо наверное глянуть в сторону внешнего приложения получающего факт события по event. Event — механизм сервера позволяющий передать клиенту сообщение о наступлении некого события, которое можно инициировать в триггере.

    А вообще, задача-то как выглядит, исходно?

  8. Юрий

    Спасибо за мысль…
    Задача состоит в том что: есть хранимая процедура которая определяет новые события в базе, и при выполнении нестандартных изменений значений, делает вставку в определенную таблицу этих же данных, после чего эти данные нужно выслать смс-кой на мобильный при помощи email (есть такая функция у мобильного оператора). Для чего я написал скрипт используя функцию ibec_smtp_SendMail(). Теперь я его запускаю раз в минуту и он определяет если новые данные в таблице для отсылки смс, и если они там есть он их отсылает…
    Вообщем и все.
    Задача в принципе реализована. Но я считаю что не совсем правильно запускать раз в минуту скрипт. Идея с Event наверное самая правильная. Буду пробывать реализовать это при помощи событий…

  9. borismor

    К сожалению под рукой сейчас нет Firebird
    Но я бы порекомендовал выполнить эти операции сначала на копии базы через IBExpert.
    Он показывает все SQL операции которые выполняет.
    Можете записать их в файлик и выполнить.

  10. acd

    А как дописать в этот скрипт условие: UPDATE dbNew.partner set name = dbOld.partner.name WHERE dbNew.partner.id = dbOld.partner.id.

    Очень надо! А времени нет, чтоб книжки перечитывать..

  11. borismor

    Навскидку

    ibec_UseConnection(dbOld);      
    for select p.ID, p.NAME
    	    from partner p
    	    into :id, :name
    do begin  
    	ibec_UseConnection(dbNew);      
            UPDATE partner set name = :name WHERE partner.id = :id.
            ibec_UseConnection(dbOld);      
    end

  12. leo

    ibec_ds_Post не работает вообще никак… Только можно считать в датасет а скинуть обратно в таблицу ни ни ibec_ds_Edit позволяет править активный датасет можно добавить или удалить запись, но POST ни фига не работает…

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *