Показать сообщение отдельно
Старый 18.02.2008, 12:13 Вверх   #5
Admin
 
Аватар для RAMZA
RAMZA вне форума
Доп. информация
Лампочка

Можно, путем вызова EXCEPTOIN в триггере. При этом все действия в триггере будут отменены (если не обрабатывать exception), и также будут отменены все действия триггеров, которые были выполнены до указанного триггера. После чего exception будет выдан в тот контекст, откуда вызывался insert. То есть, insert будет целиком отменен.
В before insert совсем отменить insert и не вызывать при этом exception нельзя. В after insert - можно, только путем удаления уже вставленной записи. Например:
create trigger A for X
active after update
as
begin
if (...) then
exception noinsert;
when any do
delete from X
where id = new.id;
end
как создать базу данных?

Это можно сделать в IBConsole, IBExpert, через IBDatabase.CreateDatabase, через IB API и так далее, главное только:
обязательно указать полный путь к базе данных. например c:\dir
желательно указать протокол tcp, даже если сервер на этой же машине (localhost:c:\dir. см. пункт)
желательно указать расширение файла БД, оно может быть любым, но расширение gdb вызовет проблемы под XP и W2003. Правильно будет например c:\dir\data.ib или c:\dir\data.fdb
желательно указать размер страницы 4096 или 8192 байт (см. пункт)
желательно указать диалект 3 (см. пункт)
желательно указать DEFAULT CHARACTER SET WIN1251 (см. faq)
как делать backup (резервную копию)

очень просто. backup это изготовление резервной копии базы данных "на ходу". Выполнять можно при работающих пользователях, однако надо помнить, что сохранены в backup будут только те данные, которые существовали на момент старта backup. Делать backup (и restore) можно как через Services API (в IBConsole, IBExpert и других, или в Delphi в палитре компонент InterBase Admin), так и утилитами командной строки.

Например:
gbak -b localhost:c:\dir\db.gdb d:\db.gbk -user SYSDBA -pass masterkey

расширение файла backup значения не имеет. Не рекомендуется делать backup на тот же логический диск, где лежит база (если кончится место, и БД перестанет работать, и бэкап не сделается), а еще лучше делать backup на отдельный физический диск (с точки зрения производительности).

Быстрее всего backup можно получить, если выключить сборку мусора, которая работает по умолчанию:
gbak -b -g localhost:c:\dir\db.gdb d:\db.gbk -user SYSDBA -pass masterkey

(мусор никогда не попадает в backup. речь просто идет о том, что backup по умолчанию читая записи пытается определить, если у записи есть версии, то нужны они или нет. ключ -g отключает это поведение)

еще лучше всегда добавлять ключ -v, который приводит к подробному выводу действий backup - в этом случае если произойдет ошибка, будет видно, где именно она произошла. Вывод можно направить и в файл:
gbak -b -g localhost:c:\dir\db.gdb d:\db.gbk -user SYSDBA -pass masterkey -v -y bak-log.txt

Backup рекомендуется делать регулярно, и сохранять его в архив (лучший вариант - ежедневный backup с сохранением 7-ми последних копий).

Делать архив БД через простое копирование файла БД можно, только если к этой БД нет ни одного подключенного пользователя - файл БД это файл произвольного доступа, а копирование операционная система выполняет последовательно. В результате вы на выходе получите испорченную "копию" файла БД.

! не рекомендуется делать restore в файл оригинальной БД (ключ -r). Всегда делайте restore только с ключом -c.

! если backup будет каким-либо образом поврежден, восстановить из него базу данных вряд ли удастся.

! даже на нынешних рабочих станциях backup базы данных размером 2 гигабайта идет около 15 минут (с ключом -g). Если у вас этот процесс происходит как минимум в 2-3 раза дольше, значит сервер загружен другими задачами, у вас медленный винчестер, или проблемы какого-то другого рода.
проблемы с float и double precision

под проблемами имеются в виду вопросы
вставляю одно число а вижу другое
не работает сравнение
не хватает точности
вылазит погрешность
... и многие другие

Рекомендуется прочитать
Проблемы с округлением вещественных чисел
http://www.ibase.ru/devinfo/round.htm
Неочевидные особенности вещественных чисел
http://www.delphikingdom.info/asp/vi...?catalogid=374
Руководство по переходу с IB 5 на IB6/7, Firebird...
http://www.ibase.ru/devinfo/migration.htm
Exact numeric, functional description
http://www.ibphoenix.com/main.nfs?a=...0_exact_num_fs

Последний документ описывает поведение numeric/decimal в третьем диалекте (без вещественных чисел.

Кроме того, существует баг с округлением вещественных чисел, исправленный только в FB 1.5.2 (описан на странице 8 Firebird 1.5.2 Release Notes).
Использование генераторов в триггерах

Если у вас возникает такой вопрос, значит вам надо прочитать статью

www.ibase.ru/devinfo/generator.htm

Вкратце решение "проблемы" - значение генератора надо сначала получить в клиентское приложение (например select gen_id(genname, 1) from rdb$database), а затем использовать его как значение столбца первичного ключа таблицы (до DataSet.Post). При этом вы не "потеряете" вставленную запись, не будет проблем со вставкой записей detail после вставки master, и т.п.

В триггере можно оставить присвоение столбцу значения генератора, если значение столбца is null. (if (new.field is null) then new.field=gen_id(genname, 1)).
Guardian и Classic или
гвардеец и классик - не работает, меняет реестр, и т.п.

Guardian (или "гвардеец") появился в InterBase 4.2, который впервые был реализован в архитектуре SuperServer (один процесс на всех пользователей). Поскольку эта версия не была свободна от багов, и например "падала" при одновременном изменении данных и метаданных, потребовался механизм для автоматического рестарта сервера IB в случае его сбоя. На Windows 95, 98 понятие "сервисы" отсутствовало, а в Windows NT 4.0 в свойствах сервисов не было возможности рестартовать сервер при сбое.

Поэтому было создано приложение ibguard.exe, которое при старте запускало ibserver.exe, и при его падении перезапускало его.

Соответственно, Guardian на компьютерах с операционной системой Windows 2000, 2003, XP, Vista - не нужен совершенно, т.к. свойства сервисов (Панель управления, Администрирование, Службы. например, закладка "Восстановление") позволяют не только настроить перезапуск сервиса при его падении, но и указать действия при последующих падениях.

Для архитектуры Classic "гвардеец" не нужен, и более того, не может рестартовать процесс Classic, вот почему: Classic работает в режиме "процесс для пользователя". То есть, если подключилось 10 пользователей, то в памяти будет 11 процессов fb_inet_server.exe. При старте самый первый процесс fb_inet_server занимается только прослушиванием порта 3050, и запуском новых процессов fb_inet_server при подсоединении пользователей. Именно поэтому число процессов Classic всегда n_подключенных_пользователей+1.
Более того, первый процесс fb_inet_server фактически никогда не может "упасть", т.к. он осуществляет достаточно примитивные операции. Guardian, в свою очередь, понятия не имеет, какой из процессов fb_inet_server чем занимается.

Возможность установки Guardian при установке Firebird Classic является недочетом инсталлятора Firebird.

Также атавизмом является FB Server Manager в панели управления, и не рекомендуется к использованию.
Как установить сервер Interbase или Firebird вместе со своим приложением?
как сделать свой инсталлятор сервера?

Это сделать очень просто. Во-первых, есть Install FAQ, в котором в том числе расписаны файлы, необходимые для работы InterBase и Firebird. Во-вторых, есть старый Embedded Installation Guide, который описывает то же самое. В третьих, существует сайт ibinstall.defined.net, на котором собраны инсталляционные скрипты для разных инсталляторов.
Ну и последнее - если вы пользуетесь InnoSetup (отличный бесплатный инсталлятор), то можете взять готовый скрипт для Firebird 1.5, и поменять его как угодно.
Сервер не загружен, все жутко тормозит

Если это точно не сборка мусора, и IBAnalyst подтверждает это, то значит это проблемы с сетью:

Если сервер Windows, то нужно запустить PerfMon, и включить мониторинг

Performance Object: Network interface
Counters: Output Queue Length
Instances: выбрать сетевую карту, которая обслуживает сеть клиентов сервера

Если размер Queue доходит до 250-400 пакетов, то это совершенно точно означает проблемы с передачей пакетов с сервера клиентам. Причиной может быть: драйвер сетевой карты, сама сетевая карта, свитч/хаб.

Для других операционных систем следует проверить то же самое.
можно ли заменить FK на триггеры, или
проверка целостности на триггерах

Часто возникает вопрос, можно ли заменить Foregin Key триггерами. Тем более что в ряде case-инструментов есть пункт "декларативная или "триггерная" ссылочная целостность", где в первом случае создаются обычные FK между таблицами, а во втором - FK эмулируются триггерами.

Общий ответ - нет. FK нельзя заменить триггерами, потому что FK работают вне контекста транзакций, а триггеры - только в той транзакции, которая инициировала их срабатывание. Пример от Ded:
Start Transaction 1
Start Transaction 2
Transaction 1 - Delete From Master
Master Trigger - Select From Detail Where ID_Master=old.ID
Нету, чудненько, можем удалять (и удаляем).
Transaction 2 - Insert Into Detail (ID, Deleted_Master_ID)
Detail Trigger - Select From Master Where ID=new.Master_ID
Есть, чудненько, можно вставить (и вставляем).

Commit в любой последовательности, в результате в таблице detail появилась запись, ссылающаяся на удаленную в таблице master запись. Чего никогда не может произойти в случае наличия обычного FK.

Если же Master - статичный справочник, то есть удаление записей в нем запрещено как класс, и первичный ключ ни в нём, ни в детали не меняется, то FK можно удалить, и оставить нужные проверки на триггерах (это рекомендуется делать только в том случае, когда индекс по конкретному FK сильно неуникальный, и его создание при restore серьезно замедляет процесс restore. См. Дополнительные вопросы и ответы в Справке к IBAnalyst).
Есть ли ограничения на длину запроса
или ограничения на число запросов в процедуре, триггере

Отвечает Vlad Horsun:

Есть ли ограничения на длину SQL-запроса от клиента?

64K

Есть ли ограничение на длину скомпилированного кода запроса (процедуры, триггера)

64К

Какое количество запросов может быть в процедуре, триггере?

255

"Запросами" считается обращение к таблице (контекст). На данный момент число контекстов ограничено 255, хотя в некоторых предыдущих версиях IB/FB было ограничение числа контекстов в 128.
Как ограничить выводимое число записей, или
есть ли в InterBase и Firebird аналог limit, top и т.п. ?

Да, есть.
Начиная с InterBase 6.5 эта и последующие версии InterBase поддерживают синтаксис ROWS.
SELECT * FROM TABLE
ORDER BY <field_list>
[ROWS <lower_value> [TO <upper_value>] [BY <step_value>] [PERCENT] [WITH TIES]
Подробнее см. документацию.
Начиная с Firebird 1.0 эта и последующие версии Firebird поддерживают синтаксис first/skip
SELECT first x skip y * FROM TABLE
Подробнее см. ReleaseNotes. В Firebird 2.0 также будет поддерживаться синтаксис ROWS, совместимый с InterBase.

Оба "ограничителя" количества записей ROWS и first/skip работают следующим образом:
сервер выполняет запрос
на этапе передачи данных клиенту сервер пропускает skip/to записей, и после выдачи first/rows записей выдает клиенту сигнал eof.

то есть, в случае обработки записей на сервере (order by без индекса, group by без индекса, выборка из процедуры и т.п.) сервер все равно сначала выполнит запрос целиком, и только после этого выдаст клиентской части запрошенное число записей. В обоих случаях указание rows/to или first/skip не имеет смысла без ORDER BY ("первые" записи из несортированного набора будут совершенно случайными), хотя Firebird поддерживает возможность в подзапросах указывать first/skip.

Примеры: выбрать 5 записей пропустив 10 из таблицы employee, упорядоченной по фамилии сотрудников:

select first 5 skip 10 *
from employee
order by last_name

select * from employee
order by last_name
rows 5 to 10
update set a=b, b=a теряет значение a

Да, во всех версиях InterBase и Firebird столбцы меняются в update по мере присвоения им значений, а не "потом".

Это не соответствует стандарту, и подлежит исправлению, но существует ряд приложений, который использует именно текущее поведение. Возможно, будет исправлено на стандартное поведение в будущих версиях Firebird.
особенности работы UPDATE и DELETE с подзапросами в условии
или
delete с first в подзапросе удаляет все записи

пример запроса:
delete from table1
where id in (select first N id from table1)

такой запрос приведет к удалению всех записей в таблице table. Проблема в том, что InterBase и Firebird в данном случае (для update и delete) выполняет подзапрос для каждой записи таблицы table1, а не наоборот.

По стандарту сервер сначала должен выполнить подзапрос, а потом выполнить delete/update. Исправление нынешнего поведения Firebird рассматривается разработчиками.
зацикливание на insert into table1 select * from table1

Движок InterBase и Firebird действительно зациклится на такой конструкции, т.к. в данном случае select будет неатомарным, т.е. он будет "подчитывать" вставляемые записи, из-за чего превратится в бесконечный цикл. Прервать такой запрос можно
в InterBase 4.x/5.x/6.0 и всех версиях Firebird (до 2.1) - только остановкой процесса сервера
в InterBase 6.5 - прерыванием запроса с клиента (сложно)
в InterBase 7.x/2007 - прекращением запроса в tmp$statements, или отключением соответствующего соединения в tmp$attachments

Исправить проблему можно или указанием условия where, чтобы select не читал вставляемые записи, или добавлением конструкции order by которая привела бы к сортировке select в памяти (PLAN SORT в плане запроса).

www.ibase.ru, (c) KDV
  Ответить с цитированием
 
Время генерации страницы 0.10423 секунды с 10 запросами