Firebird: как узнать, какое ограничение нарушено?
От: IvanXXX  
Дата: 28.06.10 17:07
Оценка:
Доброго времени суток

Есть БД, в таблицах которой множество ограничений целостности, каждое из которых имеет заранее известное имя. Как узнать имя ограничения, вызвавшего исключение при выполнении ХП?

Есть таблица и ограничение:
CREATE TABLE NEW_TABLE (
    NUMBER  BIGINT,
    STRING  VARCHAR(64)
);

ALTER TABLE NEW_TABLE ADD CONSTRAINT CHK1_NEW_TABLE check (STRING IS NOT NULL);


Пример. Если использовать IBExpert для вставки в эту таблицу, то получим следующее:
insert into new_table(number, string) values(null, null);

Operation violates CHECK constraint  on view or table.
Operation violates CHECK constraint CHK1_NEW_TABLE on view or table NEW_TABLE.
At trigger 'CHECK_3941'.


Теперь пишу следующую ХП:
create procedure NEW_PROCEDURE (
    pNumber bigint,
    pString varchar(64))
returns (
    sql bigint,
   gds bigint,
   message varchar(4096))
as
begin
  insert into new_table(number, string) values(:pNumber, :pString);

  sql = 0;
  gds = 0;
  suspend;

  when any do
  begin
    sql = SQLCODE;
    gds = GDSCODE;
    VIOLATED_CHECK_NAME = FUNC(sql, gds); --- вот с этим проблема
    message = FUNC(VIOLATED_CHECK_NAME);
    suspend;
  end
end


На RSDN есть статья про обработку ошибок БД на примере именно Firebird (http://rsdn.ru/article/db/FBErrors.xml
Автор(ы): Лихачёв Владимир Николаевич
Дата: 26.04.2009
При разработке программ, работающих с БД, важным моментом является обработка ошибочных ситуаций и информативность сообщений, предназначенных для конечного пользователя. При сложной структуре БД формирование таких сообщений для каждой отдельной ситуации может требовать довольно значительных усилий. Обработка ошибок, основанная на анализе структуры БД, и с учётом различных специфических ситуации позволит уменьшить трудозатраты и повысить качество программного обеспечения.
), но там речь идет о формировании сообщения об ошибке на основании сообщения сервера. А вот последнего у меня как раз и нет!

Если кто-то в курсе, как решить вопрос, напишите, буду очень благодарен.
Re: Firebird: как узнать, какое ограничение нарушено?
От: DarkMaster Украина http://www.bdslib.at.ua
Дата: 29.06.10 09:43
Оценка:
Здравствуйте, IvanXXX, Вы писали:

IXX>Есть БД, в таблицах которой множество ограничений целостности, каждое из которых имеет заранее известное имя. Как узнать имя ограничения, вызвавшего исключение при выполнении ХП?


IXX>Теперь пишу следующую ХП:

IXX>
IXX>  when any do
IXX>  begin
IXX>    sql = SQLCODE;
IXX>    gds = GDSCODE;
IXX>    VIOLATED_CHECK_NAME = FUNC(sql, gds); --- вот с этим проблема
IXX>    message = FUNC(VIOLATED_CHECK_NAME);
IXX>    suspend;
IXX>end
IXX>


1) Что есть FUNC и почему это оно вызывается с разными аргументами?
2) Зачем пользователю знать, что обломился именно XXX_YYY_CHK_HABA_DABA чек, а не какой-то AAB_CBDF?

На худой конец можешь конечно на стороне клиента поиграть со статус-вектором, вызовом fb_sqlstate() и прочей магией, но не возьму в толк — зачем?
WBR, Dmitry Beloshistov AKA [-=BDS=-]
Re[2]: Firebird: как узнать, какое ограничение нарушено?
От: LVlad  
Дата: 29.06.10 11:28
Оценка:
В конце второй части статьи этот вопрос рассматривается
http://www.rsdn.ru/article/db/FKeyErrors.xml
Автор(ы): Лихачёв Владимир Николаевич
Дата: 12.07.2009
Данная статья является продолжением статьи “Общий метод формирования сообщений об ошибках при работе с базами данных и его использование для БД Firebird”.
Целью данной статьи является описание возможностей увеличения информативности сообщений для ошибок, вызванных ограничениями внешних ключей, а так же описание ограничений и сложностей, которые необходимо учитывать при использовании описываемого в статьях метода формирования сообщений об ошибках для БД.


Но ничего утешительного для Вас там нет. Пока разработчики не предусмотрели возможности получения такой информации на стороне сервера. В любом случае исходный код Firebird открыт и Вы можете сами добавить такую функциональность
Re[2]: Firebird: как узнать, какое ограничение нарушено?
От: LVlad  
Дата: 29.06.10 11:52
Оценка:
Как вариант, можно рассмотреть реализацию функциональности внешних ключей через триггеры с генерацией пользовательских исключений. Но в таком варианте довольно много отрицательных моментов.
Re[2]: Firebird: как узнать, какое ограничение нарушено?
От: IvanXXX  
Дата: 29.06.10 16:17
Оценка:
Здравствуйте, DarkMaster, Вы писали:

DM>1) Что есть FUNC и почему это оно вызывается с разными аргументами?

Это две разные функции, просто для примера ("вот мы вызываем функцию без параметров, а вот — с параметром и т.д. и т.п.").

DM>2) Зачем пользователю знать, что обломился именно XXX_YYY_CHK_HABA_DABA чек, а не какой-то AAB_CBDF?

DM>На худой конец можешь конечно на стороне клиента поиграть со статус-вектором, вызовом fb_sqlstate() и прочей магией, но не возьму в толк — зачем?

Вот пример:
CREATE TABLE USERS (
    ID BIGINT,
    LOGIN VARCHAR(64)
);

ALTER TABLE NEW_TABLE ADD CONSTRAINT CHK_USERS_LOGIN_INCORRECT check (strlen(trim(STRING)) > 4);

По имени исключения приложение сможет определить причину сбоя вставки/обновления записи. В данном примере: "CHK_USERS_LOGIN_INCORRECT" => при регистрации пользователя логин не указан или его длина слишком мала.
Re[3]: Firebird: как узнать, какое ограничение нарушено?
От: IvanXXX  
Дата: 29.06.10 17:59
Оценка:
LVlad, спасибо за ответ. Уже выяснил, что на сервере имя ограничения я не получу. Обидно, досадно, но ладно. Модификация ядра — явная панацея,

Здравствуйте, LVlad, Вы писали:

LV>Как вариант, можно рассмотреть реализацию функциональности внешних ключей через триггеры с генерацией пользовательских исключений. Но в таком варианте довольно много отрицательных моментов.


Вариант, но слишком жуткий. В принципе, анализа полученного исключения в клиенте вполне хватит.
Re[4]: Firebird: как узнать, какое ограничение нарушено?
От: LVlad  
Дата: 30.06.10 07:52
Оценка:
Согласен, это наверное самый крайний вариант, если необходимо делать такую обработку на сервере.
Для Firebird, конечно такую схему лучше реализовать на клиенте.
На сервере такую функциональность можно реализовать в Oracle Database и MS SQL.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.