Есть БД, в таблицах которой множество ограничений целостности, каждое из которых имеет заранее известное имя. Как узнать имя ограничения, вызвавшего исключение при выполнении ХП?
Есть таблица и ограничение:
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
Здравствуйте, 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: как узнать, какое ограничение нарушено?
Но ничего утешительного для Вас там нет. Пока разработчики не предусмотрели возможности получения такой информации на стороне сервера. В любом случае исходный код Firebird открыт и Вы можете сами добавить такую функциональность
Re[2]: Firebird: как узнать, какое ограничение нарушено?
Как вариант, можно рассмотреть реализацию функциональности внешних ключей через триггеры с генерацией пользовательских исключений. Но в таком варианте довольно много отрицательных моментов.
Re[2]: Firebird: как узнать, какое ограничение нарушено?
Здравствуйте, 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: как узнать, какое ограничение нарушено?
LVlad, спасибо за ответ. Уже выяснил, что на сервере имя ограничения я не получу. Обидно, досадно, но ладно. Модификация ядра — явная панацея,
Здравствуйте, LVlad, Вы писали:
LV>Как вариант, можно рассмотреть реализацию функциональности внешних ключей через триггеры с генерацией пользовательских исключений. Но в таком варианте довольно много отрицательных моментов.
Вариант, но слишком жуткий. В принципе, анализа полученного исключения в клиенте вполне хватит.
Re[4]: Firebird: как узнать, какое ограничение нарушено?
Согласен, это наверное самый крайний вариант, если необходимо делать такую обработку на сервере.
Для Firebird, конечно такую схему лучше реализовать на клиенте.
На сервере такую функциональность можно реализовать в Oracle Database и MS SQL.