Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / IBM DB2, WebSphere, IMS, U2 [игнор отключен] [закрыт для гостей] / Java и идеальные ХП / 25 сообщений из 36, страница 1 из 2
11.03.2009, 17:43
    #35862900
Semen Popov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java и идеальные ХП
Здравствуйте всем!

Есть вэб-проект (Servlet, JSP), который разрабатывается на Java под WAS 6 + БД DB2 (v8.2). Дошли руки до создания хранимых процедур в БД. Хочу спросить у уважаемого сообщества, каковы будут самые идеальные ХП (для добавления, изменения, удаления записи таблицы и возвращающие выборку записей) с точки зрения оптимальности и простоты кода (SQL/SQL PL), обработки ошибок (возврата ошибок для дальнейшей обработки в приложение) и т.д?
Вообщем нужен идеальный каркас в SQL/SQL PL-коде хранимых процедур insert, update, delete в таблице TAB1 и хранимой процедуры, возвращающей выборку(select *) из TAB1. Хочется увидеть простенькие примеры каркасов и обсудить, почему те или иные варианты будут лучше.
Например, insert-ХП
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
create procedure TDB.TAB1_INS (in  in_DISTCOD smallint,
                                      in  in_FULLNAM varchar( 100 ),
                                      in  in_LOGIN   varchar( 15 ),
                                      in  in_PSWRD   varchar( 15 ),
                                      in  in_USERTYP smallint,
                                      in  in_ACCESS  smallint,
                                      out ou_RCOU    integer)

   specific TAB1_INS
   modifies SQL DATA
   language SQL

/*
   ou_RCOU - количество добавленных строк. Если 0, то ошибка  
*/
begin atomic
 -- set ou_RCOU = 0;
 insert into TDB.TAB1_INS (DISTCOD, FULLNAM, LOGIN, PSWRD, USERTYP, ACCESS)
 values (in_DISTCOD, in_FULLNAM, in_LOGIN, in_PSWRD, in_USERTYP, in_ACCESS);
 get diagnostics ou_RCOU = ROW_COUNT;
end
@
Что не учтено в этой ХП? Каков будет оптимальный вариант?


Заранее благодарен.
С уважением, Семен Попов
...
Рейтинг: 0 / 0
11.03.2009, 17:49
    #35862913
riman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java и идеальные ХП
А почему не EJB/ORM можно поинтересоваться?
...
Рейтинг: 0 / 0
12.03.2009, 09:36
    #35863816
Semen Popov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java и идеальные ХП
rimanА почему не EJB/ORM можно поинтересоваться?Не дорос ещё. А вообще технология и иерархия данных, реализованные и используемые в моем приложении, позволяют обойтись без EJB/ORM. Хотя, насколько это всё корректно, судить не решаюсь. Но суть не в этом. Даже с EJB/ORM иногда приходится использовать ХП. Для себя ставлю задачу определить общие (предусматривающие основные моменты) каркасы(шаблоны) для хранимых процедур (insert, update, delete, select) по одной таблице, чтобы при создании новых проектов не думать об их решении. Я понимаю, что случаи бывают разными для разных приложений, но задаю вопрос для самого простого варианта. Может какой-то план тела процедуры для себя определить, что-то вроде:
1. Декларация переменных
2. Открытие транзакции
3. Выполнение скрипта(insert, update, delete)
4. Закрытие транзакции
5. Обработка ошибок
и т.д. А лучше кодом SQL PL.
...
Рейтинг: 0 / 0
12.03.2009, 10:22
    #35863928
Vladimir Kiselev
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java и идеальные ХП
Semen Popov,

п.4 - спорно, в общем случае транзакцию закрывать в ХП не нужно. Как пример, кроме записи в основную таблицу бывает необходимо выполнить запись во вспомогательные таблицы.
На мой взгляд, главное выработать концепцию, чтобы в дальнейшем не вспоминать, закрывается транзакция в ХП или нет. Решать Вам.
...
Рейтинг: 0 / 0
12.03.2009, 11:12
    #35864072
Semen Popov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java и идеальные ХП
Vladimir Kiselev
п.4 - спорно, в общем случае транзакцию закрывать в ХП не нужно. Как пример, кроме записи в основную таблицу бывает необходимо выполнить запись во вспомогательные таблицы.
На мой взгляд, главное выработать концепцию, чтобы в дальнейшем не вспоминать, закрывается транзакция в ХП или нет. Решать Вам.Спасибо. Но вот в простом случае, когда выполняется скрипт по одной таблице, а она никуда "не лезет" (записи во вспомогательные таблицы не выполняются, триггеров нет), каков будет план? Или уточню: есть таблица MYTAB (RECID integer generated always as identity, FLD1, FLD2,... c primary key (RECID) и unique key(FLD1)). Насколько будет полноценен скрипт
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
create procedure TESTDB.MYTAB_INS (in  in_FLD1 smallint,
                                      in  in_FLD2 varchar( 100 ),
                                      in  in_FLD3   varchar( 15 ),
                                      ...
                                      out ou_RCOU    integer)
   specific MYTAB_INS
   modifies SQL DATA
   language SQL
/*   ou_RCOU - количество добавленных строк. Если 0, то ошибка  */
begin atomic
 -- Нужно ли присвоить 0 для ou_RCOU?
 -- set ou_RCOU = 0; 
 insert into TESTDB.TAB1 (FLD1, FLD2, FLD3, ...)
 values (in_FLD1, in_FLD2, in_FLD3, ...);
 get diagnostics ou_RCOU = ROW_COUNT;
end
@
?
В процедуре предусмотрен возврат количества обработанных записей. Я узнаю, была ли добавлена запись. А смогу ли в приложении узнать, какая ошибка возникла (если возникла), и затем передать код ошибки и ее описание пользователю? Например, произошло дублирование записи по unique key. Хотелось бы сообщить пользователю ошибку и выдать конфликтный объект БД с его описанием (комментарием). Что в этой ХП нужно максимально предусмотреть, чтобы с ней было легко работать из приложения?
...
Рейтинг: 0 / 0
12.03.2009, 11:19
    #35864101
Semen Popov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java и идеальные ХП
Semen PopovЧто в этой ХП нужно максимально предусмотреть, чтобы с ней было легко работать из приложения?Чтобы процедура была оптимальной, информативной и ещё что-нибудь предусмотреть, о чём я еще не знаю?
...
Рейтинг: 0 / 0
12.03.2009, 13:20
    #35864627
шубин_ду
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java и идеальные ХП
Semen PopovЗдравствуйте всем!

Есть вэб-проект (Servlet, JSP), который разрабатывается на Java под WAS 6 + БД DB2 (v8.2). Дошли руки до создания хранимых процедур в БД.

При программировании на Java хранимые процедуры для этих целей не используют. ХП это тяжелая артиллерия для решения сложных задач, где Java неудобна или приводит к проблемам с производительностью. Для простых операций в Java принято использовать ORM. Он решает поставленные Вами задачи быстро как в плане скорости выполнения, так и в плане скорости разработки. И он обеспечивает Вам автоматом привычный в Java объектный подход. На мой взгляд в вашем случае было бы правильнее выбрать подходящий ORM. Вот тут есть сравнение:

http://terrazadearavaca.blogspot.com/2008/12/jpa-implementations-comparison.html
...
Рейтинг: 0 / 0
12.03.2009, 16:05
    #35865243
Semen Popov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java и идеальные ХП
шубин_дуПри программировании на Java хранимые процедуры для этих целей не используют. ХП это тяжелая артиллерия для решения сложных задач, где Java неудобна или приводит к проблемам с производительностью. Для простых операций в Java принято использовать ORM. Он решает поставленные Вами задачи быстро как в плане скорости выполнения, так и в плане скорости разработки. И он обеспечивает Вам автоматом привычный в Java объектный подход. На мой взгляд в вашем случае было бы правильнее выбрать подходящий ORM. Вот тут есть сравнение:

http://terrazadearavaca.blogspot.com/2008/12/jpa-implementations-comparison.htmlСпасибо. Я понимаю ситуацию так. В той реализации, что сейчас имею, у меня есть два варианта выполнения скриптов - через PrepareStatement и PrepareCall. Выполнение скрипта с помощью PrepareStatement - это динамический SQL. На выполнение динамического скрипта DB2 затрачивает ресурсы - разбор скрипта, проверка синтаксиса и т.д. И это при каждом выполнении скрипта, а таких операций проводится много. Если эти скрипты вынести в хранимые процедуры, то DB2 их будет видеть как свой скомпилированный код, поэтому при их вызове не будет затрачивать дополнительные ресурсы. Слышал, что некоторые ребятишки-программисты рекомендуют часто используемый скрипт выносить в ХП. Вот и спрашиваю, как сделать ХП оптимальной для этих скриптов. Если неправильно рассуждаю, то поправьте меня.
...
Рейтинг: 0 / 0
12.03.2009, 19:25
    #35865806
шубин_ду
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java и идеальные ХП
Semen Popovшубин_дуПри программировании на Java хранимые процедуры для этих целей не используют. ХП это тяжелая артиллерия для решения сложных задач, где Java неудобна или приводит к проблемам с производительностью. Для простых операций в Java принято использовать ORM. Он решает поставленные Вами задачи быстро как в плане скорости выполнения, так и в плане скорости разработки. И он обеспечивает Вам автоматом привычный в Java объектный подход. На мой взгляд в вашем случае было бы правильнее выбрать подходящий ORM. Вот тут есть сравнение:

http://terrazadearavaca.blogspot.com/2008/12/jpa-implementations-comparison.htmlСпасибо. Я понимаю ситуацию так. В той реализации, что сейчас имею, у меня есть два варианта выполнения скриптов - через PrepareStatement и PrepareCall. Выполнение скрипта с помощью PrepareStatement - это динамический SQL. На выполнение динамического скрипта DB2 затрачивает ресурсы - разбор скрипта, проверка синтаксиса и т.д. И это при каждом выполнении скрипта, а таких операций проводится много. Если эти скрипты вынести в хранимые процедуры, то DB2 их будет видеть как свой скомпилированный код, поэтому при их вызове не будет затрачивать дополнительные ресурсы. Слышал, что некоторые ребятишки-программисты рекомендуют часто используемый скрипт выносить в ХП. Вот и спрашиваю, как сделать ХП оптимальной для этих скриптов. Если неправильно рассуждаю, то поправьте меня.

Все верно, ресурсы затрачиваются. И если динамический SQL очень большой и сложный и его нет в кеше, то на разбор будут тратиться секунды. Но если он маленький и простой и он в кеше, то на разбор будут тратиться микросекунды. Сделайте бенчмарк и подтвердите свои опасения. Я уверен на 100%, что разницы никакой не будет. Тест очень простой:

1. 1000 инсертов при помощи вызова хранимой процедуры
2. 1000 инсертов через JPA. Точнее это будут уже не инсерты, а new MyClass(), save. Инсерты сгенерит JPA.

1. 1000 селектов при помощи вызова хранимой процедуры
2. 1000 селектов через JPA. Точнее это будут object.get(). Селекты сгенерит JPA.
...
Рейтинг: 0 / 0
16.03.2009, 11:20
    #35870889
Semen Popov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java и идеальные ХП
Понятно. Спасибо. Будем развиваться, будем использовать.
Но по ХП всё-таки разъясните или покажите, пожалуйста. Хотя бы в части информативности. Что изменить в приведённой мною процедуре, чтобы получать информацию о возникших ошибках? А то сейчас не могу узнать, какая ошибка произошла (нарушена уникальность, не вылонено ограничение по полю и т.д.). get diagnostics сейчас возвращает только количество обработанных строк. Другие параметры get diagnostics могут мне помочь? Может стоит использовать другой оператор?
...
Рейтинг: 0 / 0
16.03.2009, 13:35
    #35871418
Mark Barinstein
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java и идеальные ХП
Semen PopovЧто изменить в приведённой мною процедуре, чтобы получать информацию о возникших ошибках? А то сейчас не могу узнать, какая ошибка произошла (нарушена уникальность, не вылонено ограничение по полю и т.д.). get diagnostics сейчас возвращает только количество обработанных строк. Другие параметры get diagnostics могут мне помочь? Может стоит использовать другой оператор?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
create procedure ...
(
  ...
, out rc int
, out msg varchar( 4000 )
)
language sql
begin
 declare sqlcode int default  0 ;
 declare exit handler for sqlexception
  begin
   GET DIAGNOSTICS EXCEPTION  1  msg = MESSAGE_TEXT;
   SET rc=SQLCODE;
   -- дальнейшая обработка, если надо
   ...
  end;
 ...
end@
...
Рейтинг: 0 / 0
18.03.2009, 10:03
    #35875783
Semen Popov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java и идеальные ХП
Mark Barinstein, спасибо. Но MESSAGE_TEXT хотя и довольно полное сообщение, не указывает имена проблемных объектов. Потестировал ваш код на таблице с уникальным ключом и получил сообщение:

Одно или несколько значений в операторе INSERT, в операторе UPDATE или при обновлении внешнего ключа, вызванном оператором DELETE, недопустимы, поскольку первичный ключ, ограничение уникальности или индекс уникальности "2" запрещают повторение строк для этих столбцов в таблице "TESTDB.MYTAB"

Тут, возможно, надо покопать и другие параметры информационной области диагностики - CONSTRAINT_NAME, COLUMN_NAME, CURSOR_NAME, PARAMETR_NAME, TRIGGER_NAME и другие. Отлавливать хэндлером нужные SQLSTATE и самому генерировать сообщение об ошибке.

Примерно так можно отловить нарушение уникальности и вытащить имя unique-констраинта:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
create procedure ...
(
  ...
  out ou_SQLCODE int,
  out ou_MESSAGE varchar( 4000 )
)
language sql
begin
 declare SQLCODE int default  0 ;
 declare SQLSTATE char( 5 ) default '00000';
 declare cons_name varchar( 18 ) default '';

 declare C_UNIQUE_ERROR condition for sqlstate '23505';
 declare exit handler for sqlexception
 begin
  get diagnostics exception  1  ou_MESSAGE = MESSAGE_TEXT;
  set ou_SQLCODE = SQLCODE;
 end; 
 declare exit handler for C_UNIQUE_ERROR
 begin
  get diagnostics exception  1  ou_MESSAGE = MESSAGE_TEXT, cons_name = CONSTRAINT_NAME;
  set ou_SQLCODE = SQLCODE;
  set ou_MESSAGE = ou_MESSAGE || ', нарушение уникальности по ключу ' || cons_name;
 end; 
 insert into TESTDB.MYTAB (FLD1, FLD2, FLD3, ...)
 values (in_FLD1, in_FLD2, in_FLD3, ...);
end

Если предусмотреть в ХП хэндлеры для часто возникаемых ошибок, то для них можно расширить сообщение об ошибке и дополнить нужной информацией.
...
Рейтинг: 0 / 0
18.03.2009, 11:09
    #35875977
Mark Barinstein
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java и идеальные ХП
Semen PopovТут, возможно, надо покопать и другие параметры информационной области диагностики - CONSTRAINT_NAME, COLUMN_NAME, CURSOR_NAME, PARAMETR_NAME, TRIGGER_NAME и другие.db2 for LUW (в т.ч. ваша db2 v8.2) и db2 for iOS - это 2 разные db2.
GET DIAGNOSTICS для db2 for LUW не имеет таких ключевых слов.
Для "очеловечивания" SQLSTATE 23505 можно так:
create procedure ...
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
create procedure ...
(
  ...
, out ou_SQLCODE  int
, out ou_MESSAGE  varchar( 512 )
, out ou_MESSAGE2 varchar( 512 )
)
language sql
begin
 declare SQLCODE    int default  0 ;
 declare ltoken     varchar( 512 );
 declare lpos1      int;
 declare lpos2      int;
 declare liid       int;
 declare ltabschema varchar( 128 );
 declare ltabname   varchar( 128 );
 declare lindschema varchar( 128 );
 declare lindname   varchar( 128 );

 ...
 declare C_UNIQUE_ERROR condition for sqlstate '23505';
 declare exit handler for C_UNIQUE_ERROR
 begin
  get diagnostics exception  1  
      ou_MESSAGE = MESSAGE_TEXT
    , ltoken     = DB2_TOKEN_STRING;
  set ou_SQLCODE = SQLCODE;
  set lpos1 = posstr(ltoken, x'ff');
  set lpos2 = posstr(ltoken, '.');
  set liid       = int(substr(ltoken,  1 , lpos1- 1 ));
  set ltabschema = substr(ltoken, lpos1+ 1 , lpos2-lpos1- 1 );
  set ltabname   = substr(ltoken, lpos2+ 1 );

  select indschema, indname into lindschema, lindname
  from syscat.indexes
  where iid=liid and tabschema=ltabschema and tabname=ltabname;
  
  set ou_MESSAGE2 = 
    'uniqueness of the index "'||lindschema||'.'||lindname
  ||'" of the table "'||ltabschema||'.'||ltabname||'" is violated';
 end; 
 ...
end@
...
Рейтинг: 0 / 0
19.03.2009, 12:46
    #35878945
Semen Popov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java и идеальные ХП
Потестил. У меня почему-то этот параметр DB2_TOKEN_STRING возвращает скудную информацию

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
call TESTDB.MYTABINS( 0 ,'ABCD','111111','111', 0 , 0 ,?,?,?,?)

  Значение выходных параметров
  --------------------------
  Имя параметра   : OU_SQLCODE
  Значение парам. : - 803 

  Имя параметра   : OU_SQLSTTE
  Значение парам. :  00000  

  Имя параметра   : OU_MESSAGE
  Значение парам. : SQL0803N  Одно или несколько значений в операторе INSERT, 
в операторе UPDATE или при обновлении внешнего ключа, вызванном оператором DELETE,
недопустимы, поскольку первичный ключ, ограничение уникальности или индекс уникальности "2"
запрещают повторение строк для этих столбцов в таблице "TESTDB.MYTAB".  SQLSTATE= 23505    

  Имя параметра   : OU_DB2TOKE
  Значение парам. : 2яTESTDB.MYTAB

  Статус возврата =  0 
Интересно, что значение параметра OU_SQLSTTE не возвращается.

Тело процедуры:
create procedure ...
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
create procedure ...
(
  ...
, out ou_SQLCODE  int
, out ou_SQLSTTE  char( 5 )
, out ou_MESSAGE  varchar( 512 )
, out ou_DB2TOKE   varchar( 512 )
)
language sql
begin
 declare SQLCODE int default  0 ;
 declare SQLSTATE char( 5 ) default '00000';

 declare C_UNIQUE_ERROR condition for sqlstate '23505';
 declare exit handler for sqlexception
 begin
  get diagnostics exception  1  ou_MESSAGE = MESSAGE_TEXT, ou_DB2TOKE = DB2_TOKEN_STRING;
  set ou_SQLCODE=SQLCODE;
  set ou_SQLSTTE=SQLSTATE;
 end; 
 insert into TESTDB.MYTAB ...;
end@
...
Рейтинг: 0 / 0
19.03.2009, 13:11
    #35879036
Mark Barinstein
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java и идеальные ХП
Semen PopovПотестил. У меня почему-то этот параметр DB2_TOKEN_STRING возвращает скудную информацию

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
call TESTDB.MYTABINS( 0 ,'ABCD','111111','111', 0 , 0 ,?,?,?,?)

  Значение выходных параметров
  --------------------------
  Имя параметра   : OU_SQLCODE
  Значение парам. : - 803 

  Имя параметра   : OU_SQLSTTE
  Значение парам. :  00000  

  Имя параметра   : OU_MESSAGE
  Значение парам. : SQL0803N  Одно или несколько значений в операторе INSERT, 
в операторе UPDATE или при обновлении внешнего ключа, вызванном оператором DELETE,
недопустимы, поскольку первичный ключ, ограничение уникальности или индекс уникальности "2"
запрещают повторение строк для этих столбцов в таблице "TESTDB.MYTAB".  SQLSTATE= 23505    

  Имя параметра   : OU_DB2TOKE
  Значение парам. : 2яTESTDB.MYTAB

  Статус возврата =  0 
DB2_TOKEN_STRING возвращает то, что должен в этом случае:
2 лексемы (номер индекса, полное имя таблицы), разделенные символом x'FF'.
Я не зря в соём коде привёл пример, как вытащить из этой строки нужную информацию для запроса на имя уникального индекса.Semen PopovИнтересно, что значение параметра OU_SQLSTTE не возвращается.

Тело процедуры:
create procedure ...
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
create procedure ...
(
  ...
, out ou_SQLCODE  int
, out ou_SQLSTTE  char( 5 )
, out ou_MESSAGE  varchar( 512 )
, out ou_DB2TOKE   varchar( 512 )
)
language sql
begin
 declare SQLCODE int default  0 ;
 declare SQLSTATE char( 5 ) default '00000';

 declare C_UNIQUE_ERROR condition for sqlstate '23505';
 declare exit handler for sqlexception
 begin
  get diagnostics exception  1  ou_MESSAGE = MESSAGE_TEXT, ou_DB2TOKE = DB2_TOKEN_STRING;
  set ou_SQLCODE=SQLCODE;
  set ou_SQLSTTE=SQLSTATE;
 end; 
 insert into TESTDB.MYTAB ...;
end@
Специальные переменные SQLCODE и SQLSTATE сбрасываются после каждой команды, кроме get diagnostics.
Поэтому, чтобы получить одновременно и SQLCODE и SQLSTATE, вам надо это сделать одной командой сразу после get diagnostics , например, так:
Код: plaintext
1.
get diagnostics ...;
values (SQLCODE, SQLSTATE) into ou_SQLCODE, ou_SQLSTTE;
...
Рейтинг: 0 / 0
19.03.2009, 14:08
    #35879253
Semen Popov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java и идеальные ХП
Понятно. Большое спасибо
...
Рейтинг: 0 / 0
19.03.2009, 16:29
    #35879761
Semen Popov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java и идеальные ХП
Маленький итог темы в части информативности:
Хранимая процедура с получением подробного отчета об ошибке
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
create procedure ... (...
                                      out ou_SQLSTTE  char( 5 ),
                                      out ou_MESSAGE  varchar( 512 ))

   language SQL
begin
 -- необходимые системные переменные
 declare SQLCODE int default  0 ;
 declare SQLSTATE char( 5 ) default '00000';
 -- дополнительные переменные
 declare sp_sqlcode  int;
 declare sp_sqlstate char( 5 );
 declare sp_ltoken      varchar( 512 );
 declare sp_lpos1       int;
 declare sp_lpos2       int;
 declare sp_liid        int;
 declare sp_ltabschema  varchar( 128 );
 declare sp_ltabname    varchar( 128 );
 declare sp_lindschema  varchar( 128 );
 declare sp_lindname    varchar( 128 );
 -- недлеры ошибок, которые нужно перехватить и дать "очеловеченное" описание
 declare C_UNIQUE_ERROR condition for sqlstate '23505';
 declare exit handler for C_UNIQUE_ERROR
 begin
  -- обработка и получение дополнительной информации об ошибке
  get diagnostics exception  1  ou_MESSAGE = MESSAGE_TEXT, sp_ltoken = DB2_TOKEN_STRING;
  values (SQLCODE, SQLSTATE) into sp_sqlcode, sp_sqlstate;
  values(sp_sqlstate) into ou_SQLSTTE;

  set sp_lpos1 = posstr(sp_ltoken, x'ff');
  set sp_lpos2 = posstr(sp_ltoken, '.');
  set sp_liid       = int(substr(sp_ltoken,  1 , sp_lpos1- 1 ));
  set sp_ltabschema = substr(sp_ltoken, sp_lpos1+ 1 , sp_lpos2-sp_lpos1- 1 );
  set sp_ltabname   = substr(sp_ltoken, sp_lpos2+ 1 );

  select INDSCHEMA, INDNAME into sp_lindschema, sp_lindname
  from SYSCAT.INDEXES
  where IID=liid and TABSCHEMA=sp_ltabschema and TABNAME=sp_ltabname;
  -- из SYSCAT можно достать много другой дополнительной информации

  set ou_MESSAGE = 'Возникла ошибка SQLSTATE='||sp_sqlstate||', SQLCODE='||rtrim(char(sp_sqlcode))||': '||
  'Добавление записи создает дублирование для индекса "'||sp_lindschema||'.'||sp_lindname||
  '" таблицы "'||sp_ltabschema||'.'||sp_ltabname||'". Запись не добавлена';
 end; 
 -- другие хендлеры
 ...
 
 body: begin
  ...
 end body;
end@

Замечания:
1. Использование хендлеров в ХП не дает возможности передачи возникшего исключения в приложение. Поэтому, если в java-приложении предусмотрен перехват исключения (вызов процедуры в конструкции try {} catch ();), то он срабатывать не будет. Обработать ошибки отдельных SQLSTATE в java-приложении нужно будет по возвращаемому параметру ou_SQLSTTE.
2. Было бы разумно вынести обработку ошибок в отдельную процедуру для того, чтобы не повторять его в каждой ХП. Возможно ли это реализовать?
...
Рейтинг: 0 / 0
19.03.2009, 17:18
    #35879936
Mark Barinstein
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java и идеальные ХП
Semen PopovЗамечания:
1. Использование хендлеров в ХП не дает возможности передачи возникшего исключения в приложение. Поэтому, если в java-приложении предусмотрен перехват исключения (вызов процедуры в конструкции try {} catch ();), то он срабатывать не будет. Обработать ошибки отдельных SQLSTATE в java-приложении нужно будет по возвращаемому параметру ou_SQLSTTE.
2. Было бы разумно вынести обработку ошибок в отдельную процедуру для того, чтобы не повторять его в каждой ХП. Возможно ли это реализовать?Можете вынести обработку ошибок в свою собственную процедуру. Передавайте туда sqlcode, sqlstate, db2_token_string из handler'а процедуры, вызвавшей ошибку.
Кроме того, можете также вызывать SIGNAL / RESIGNAL команды в процедуре-обработчике, если хочется сформировать своё сообщение и выкинуть его вместе с ошибкой приложению. Только текст такого сообщения будет не более 70 символов.
...
Рейтинг: 0 / 0
20.03.2009, 09:48
    #35880888
Semen Popov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java и идеальные ХП
Mark BarinsteinМожете вынести обработку ошибок в свою собственную процедуру. Передавайте туда sqlcode, sqlstate, db2_token_string из handler'а процедуры, вызвавшей ошибку.Спасибо. А ещё более удобней было бы вынести весь код (декларацию хендлеров и обработку) в SQL-рутину. В DB2 v8.2 поддерживаются SQL-routines? Тогда бы вообще не пришлось в головных процедурах декларировать объекты, связанные с обработкой ошибок. Я правильно понимаю SQL-routine?
...
Рейтинг: 0 / 0
20.03.2009, 10:03
    #35880913
Mark Barinstein
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java и идеальные ХП
Semen PopovВ DB2 v8.2 поддерживаются SQL-routines?Да.
...
Рейтинг: 0 / 0
20.03.2009, 11:25
    #35881187
Semen Popov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java и идеальные ХП
Скорее, они не помогут. Наверно, я неправильно понимаю SQL routine. В моем программистском понимании рутина - это фрагмент часто используемого кода, вынесенный из тела процедуры. В процедуре в нужных местах лишь подставляется её имя. Это указывает компилятору, чтобы тот вставил фрагмент кода. Подобное можно реализовать в DB2? А то мы вроде обработку ошибок выносим в отдельную процедуру, но не полностью. Декларацию хендлеров, системных переменных и т.д. все равно нужно делать в каждой ХП.
...
Рейтинг: 0 / 0
20.03.2009, 12:08
    #35881348
Mark Barinstein
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java и идеальные ХП
Semen PopovА то мы вроде обработку ошибок выносим в отдельную процедуру, но не полностью. Декларацию хендлеров, системных переменных и т.д. все равно нужно делать в каждой ХП.Это вас сильно напрягает?
Это ведь маленький кусочек кода в каждой процедуре...
...
Рейтинг: 0 / 0
20.03.2009, 13:51
    #35881789
Semen Popov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java и идеальные ХП
Mark BarinsteinЭто вас сильно напрягает?
Это ведь маленький кусочек кода в каждой процедуре...В принципе нет. Но как то не красиво получается - некоторая зависимость функционала обработки ошибок от ХП. Было б хорошо реализовать обработчик, который всё делал сам - и исключения отлавливал, и разбор ошибки и составление сообщения. Ну, да ладно.
...
Рейтинг: 0 / 0
06.04.2009, 07:03
    #35913484
Николаха
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java и идеальные ХП
Добрый день. Никак не могу понять!!!
Есть ХП с входным параметром IN param INTEGER. На основе этого параметра мне надо создать курсор.
Т.е. так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
DECLARE ppp INTEGER DEFAULT  0 ;

IF (param> 10 ) THEN SET ppp =  0 ;
IF (param> 20 ) THEN SET ppp =  1 ;
.............................................

DECLARE cur CURSOR FOR
     select t.* from t1 t where t.fff=ppp;
.............................................

Как я понял сначало надо DECLARE, а потом уже что-то делать. Как тут можно сделать!?
...
Рейтинг: 0 / 0
06.04.2009, 09:48
    #35913621
Mark Barinstein
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java и идеальные ХП
НиколахаДобрый день. Никак не могу понять!!!
Есть ХП с входным параметром IN param INTEGER. На основе этого параметра мне надо создать курсор.
Т.е. так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
DECLARE ppp INTEGER DEFAULT  0 ;

IF (param> 10 ) THEN SET ppp =  0 ;
IF (param> 20 ) THEN SET ppp =  1 ;
.............................................

DECLARE cur CURSOR FOR
     select t.* from t1 t where t.fff=ppp;
.............................................

Как я понял сначало надо DECLARE, а потом уже что-то делать. Как тут можно сделать!? Compound SQL (Procedure) statement .
Обратите внимание, что порядок следования команд внутри compound statement такой:
1. декларация переменных
2. декларация курсоров
3. SQL Procedure statement

А у вас сначала 3, потом 2.
Так нельзя.
...
Рейтинг: 0 / 0
Форумы / IBM DB2, WebSphere, IMS, U2 [игнор отключен] [закрыт для гостей] / Java и идеальные ХП / 25 сообщений из 36, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]