powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / IBM DB2, WebSphere, IMS, U2 [игнор отключен] [закрыт для гостей] / неправильный элемент WITH в хранимой процедуре
14 сообщений из 14, страница 1 из 1
неправильный элемент WITH в хранимой процедуре
    #38570181
askfinder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
v. 9.7.2
Помогите, плз, разобраться.
запрос:

WITH TBL1 (TMP_IDIMP) AS (SELECT IDIMP FROM FINAL TABLE(
UPDATE USRSCHEMA.TMPINHSP B SET B.ERR_EMPTY=1
WHERE B.IDIMP=222 AND B.ERR_EMPTY=0 AND
PRFMED IS NULL
)),
TBL2 (ID) AS (SELECT ID FROM FINAL TABLE(
UPDATE USRSCHEMA.IMPORT SET FLCSTATUS=-1 WHERE ID IN (SELECT TMP_IDIMP FROM TBL1)
))
SELECT COUNT(*) FROM TBL2;

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

CREATE OR REPLACE PROCEDURE USRSCHEMA.MY_CHK (IN ID_IMP BIGINT)

SPECIFIC MY_CHK
LANGUAGE SQL
MODIFIES SQL DATA
------------------------------------------------------------------------
P1: BEGIN

WITH TBL1 (TMP_IDIMP) AS (SELECT IDIMP FROM FINAL TABLE(
UPDATE USRSCHEMA.TMPINHSP B SET B.ERR_EMPTY=1
WHERE B.IDIMP=ID_IMP AND B.ERR_EMPTY=0 AND
PRFMED IS NULL
)),
TBL2 (ID) AS (SELECT ID FROM FINAL TABLE(
UPDATE USRSCHEMA.IMPORT SET FLCSTATUS=-1 WHERE ID IN (SELECT TMP_IDIMP FROM TBL1)
))
SELECT COUNT(*) FROM TBL2;
COMMIT;

END P1@

то DB2 ругается на "неправильный элемент WITH". Почему?
...
Рейтинг: 0 / 0
неправильный элемент WITH в хранимой процедуре
    #38570222
Фотография medoed
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
askfinder,
Второй случай Begin End содержит! Db2 это вам не MSSQL и ни Sybase, select напрямую вернуть нельзя из процедуры. Используйте курсор, имхо!
...
Рейтинг: 0 / 0
неправильный элемент WITH в хранимой процедуре
    #38570241
askfinder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
medoed,

С курсором работает, но как-то не хотелось бы его создавать. Меня собственно результат SELECT Count(*) не интересует, мне нужно лишь выполнить один UPDATE по результатам другого.
...
Рейтинг: 0 / 0
неправильный элемент WITH в хранимой процедуре
    #38570279
Фотография medoed
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
askfindermedoed,

С курсором работает, но как-то не хотелось бы его создавать. Меня собственно результат SELECT Count(*) не интересует, мне нужно лишь выполнить один UPDATE по результатам другого.
Пишите вложенный запрос!
...
Рейтинг: 0 / 0
неправильный элемент WITH в хранимой процедуре
    #38570286
CawaSPb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
askfinder,

Ровно потому, что в процедуре нельзя просто писать select ... (куда оно результат то девать будет?):
Код: sql
1.
2.
3.
BEGIN
  select count(*) from syscat.tables;
END@


Можно так:
Код: sql
1.
2.
3.
4.
5.
BEGIN
  declare result integer;
  
  set result = (select count(*) from syscat.tables);
END@



т.е.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
P1: BEGIN
  declare result integer;

  set result = (
    WITH TBL1 (TMP_IDIMP) AS (SELECT IDIMP FROM FINAL TABLE(
    UPDATE USRSCHEMA.TMPINHSP B SET B.ERR_EMPTY=1
    WHERE B.IDIMP=ID_IMP AND B.ERR_EMPTY=0 AND
    PRFMED IS NULL
    )),
    TBL2 (ID) AS (SELECT ID FROM FINAL TABLE(
    UPDATE USRSCHEMA.IMPORT SET FLCSTATUS=-1 WHERE ID IN (SELECT TMP_IDIMP FROM TBL1)
    ))
    SELECT COUNT(*) FROM TBL2
  );
  COMMIT;

END P1@


Но! Это очень, ОЧЕНЬ! криво хотя бы потому, что для вычислимости count(*) в общем случае нет необходимости инстанциировать таблицу (т.е. проводить сам UPDATE).
Понятно и правильно желание работать с SET'ами, но хорошего альтернативного решения я с ходу не вижу (MERGE в данном случае не помошник).
...
Рейтинг: 0 / 0
неправильный элемент WITH в хранимой процедуре
    #38570309
Фотография medoed
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CawaSPbaskfinder,
Ровно потому, что в процедуре DB2 и Oracle нельзя просто писать select ... (куда оно результат то девать будет?):
.
Поправел
...
Рейтинг: 0 / 0
неправильный элемент WITH в хранимой процедуре
    #38570354
askfinder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
CawaSPb,

Пытался в процедуре сделать подзапросом:

...
UPDATE USRSCHEMA.IMPORT SET FLCSTATUS=-1 WHERE ID IN (
SELECT IDIMP FROM FINAL TABLE(
UPDATE USRSCHEMA.TMPINHSP B SET B.ERR_EMPTY=1
WHERE B.IDIMP=ID_IMP AND B.ERR_EMPTY=0 AND PRFMED IS NULL
) FETCH FIRST 1 ROW ONLY);
COMMIT;
...

Ругается на контекст UPDATE-а. В принципе, конечно можно разбить на два запроса:
...
DECLARE TMPID BIGINT DEFAULT 0;

SELECT IDIMP INTO TMPID FROM FINAL TABLE(
UPDATE USRSCHEMA.TMPINHSP B SET B.ERR_EMPTY=1
WHERE B.IDIMP=ID_IMP AND B.ERR_EMPTY=0 AND PRFMED IS NULL
) FETCH FIRST 1 ROW ONLY;
COMIT;
UPDATE USRSCHEMA.IMPORT SET FLCSTATUS=-1 WHERE ID=TMPID;
COMIT;
...

Но хотелось бы все-таки одним запросом обновлять обе таблицы. Не соображу как это правильно сделать.
...
Рейтинг: 0 / 0
неправильный элемент WITH в хранимой процедуре
    #38570412
askfinder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
CawaSPbт.е.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
P1: BEGIN
  declare result integer;

  set result = (
    WITH TBL1 (TMP_IDIMP) AS (SELECT IDIMP FROM FINAL TABLE(
    UPDATE USRSCHEMA.TMPINHSP B SET B.ERR_EMPTY=1
    WHERE B.IDIMP=ID_IMP AND B.ERR_EMPTY=0 AND
    PRFMED IS NULL
    )),
    TBL2 (ID) AS (SELECT ID FROM FINAL TABLE(
    UPDATE USRSCHEMA.IMPORT SET FLCSTATUS=-1 WHERE ID IN (SELECT TMP_IDIMP FROM TBL1)
    ))
    SELECT COUNT(*) FROM TBL2
  );
  COMMIT;

END P1@




Так тоже ругается - "Обнаружен неправльный элемент "AS" после текста "ITH TBL1 (TMP_IDIMP)". Список возможных правильных элементов: "JOIN"
...
Рейтинг: 0 / 0
неправильный элемент WITH в хранимой процедуре
    #38570627
CawaSPb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
askfinderТак тоже ругается - ...
"Действительно, Пятачок..." (C)

Я смотрю результат "select from update" даже во временную таблицу не запихнуть. т.е. применение этой конструкции очень и очень ограничено, хотя каких-либо технических причин подобного ограничения я не вижу.

Вариант - навесить на USRSCHEMA.TMPINHSP after update триггер. Тем более, это скорее всего будет наиболее точно отражать суть происходящего.
...
Рейтинг: 0 / 0
неправильный элемент WITH в хранимой процедуре
    #38570697
Фотография medoed
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как вариант, можно в declare globary temporary table (реальные темповые таблицы) сохранять результаты и с ними джойнить. Но не уверен, что это корректное решение, просто если это реально темповая таблица, то триггерами её обвешивать, не есть гут,имхо!
...
Рейтинг: 0 / 0
неправильный элемент WITH в хранимой процедуре
    #38571153
Mark Barinstein
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
askfinder,

Как-то так:
Код: sql
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.
CREATE OR REPLACE PROCEDURE USRSCHEMA.MY_CHK (IN ID_IMP BIGINT)

	SPECIFIC MY_CHK
	LANGUAGE SQL
	MODIFIES SQL DATA 
------------------------------------------------------------------------
P1: BEGIN 
  declare l_cnt int;

  for c1 as 
        WITH TBL1 (TMP_IDIMP) AS (SELECT IDIMP FROM FINAL TABLE(
			UPDATE USRSCHEMA.TMPINHSP B SET B.ERR_EMPTY=1 
			WHERE B.IDIMP=ID_IMP  AND B.ERR_EMPTY=0 AND 
 			PRFMED IS NULL
			)), 
	TBL2 (ID) AS (SELECT ID FROM FINAL TABLE(
		UPDATE USRSCHEMA.IMPORT SET FLCSTATUS=-1 WHERE ID IN (SELECT TMP_IDIMP FROM TBL1) 
			)) 
	SELECT COUNT(*) c FROM TBL2
  do
    set l_cnt = c1.c;
  end for;
  COMMIT;

END P1@
...
Рейтинг: 0 / 0
неправильный элемент WITH в хранимой процедуре
    #38571203
askfinder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Mark Barinstein,

Спасибо, Марк. В таком виде все работает. Может подскажете, какой вариант:
1. WITH, завернутый в курсор
2. Два последовательных UPDATE.
3. Конструкция FOR
выглядит более предпочтительным (производительным) в общем случае (при прочих равных условиях)?
...
Рейтинг: 0 / 0
неправильный элемент WITH в хранимой процедуре
    #38575023
Mark Barinstein
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
askfinder,

Добрый день.

Никто не сможет вам сказать для общего случая, как оно будет эффективнее.
Только тестрование разных вариантов на конкретном примере может показать как оно эффективнее будет.
В теории, если брать ваш пример, то вы на основе записей, которые вы обновили первым запросом:

WITH TBL1 (TMP_IDIMP) AS (SELECT IDIMP FROM FINAL TABLE(
UPDATE USRSCHEMA.TMPINHSP B SET B.ERR_EMPTY=1
WHERE B.IDIMP=ID_IMP AND B.ERR_EMPTY=0 AND PRFMED IS NULL
)

делаете изменение в другой таблице:

TBL2 (ID) AS (SELECT ID FROM FINAL TABLE(
UPDATE USRSCHEMA.IMPORT SET FLCSTATUS=-1
WHERE ID IN (SELECT TMP_IDIMP FROM TBL1)
))

Если вы вместо такой удобной конструкции будете реализовавать ту же самую логику по-другому, то вам, скорее всего, придется делать значительно больше IO. Ведь надо как-то запомнить, какие же именно записи изменились первым update, чтобы потом использовать их ID во втором. Для этого select from data change operations и делалось.

Но на практике надо смотреть, приведет ли это действительно к выигрышу в производительности, т.к. никто не знает, как в общем случае поведет себя оптимизатор. Например, он может для такого 2-х этажного запроса выбрать table scan для USRSCHEMA.IMPORT по какой-то причине (например, ошибка в оценке кол-ва измененных записей), хотя если бы вы сохранили эти TMP_IDIMP во временной таблице и собрали бы на нее статистику, то он мог бы выбрать index scan для USRSCHEMA.IMPORT.
...
Рейтинг: 0 / 0
неправильный элемент WITH в хранимой процедуре
    #38575160
Фотография medoed
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Mark Barinsteinaskfinder,

хотя если бы вы сохранили эти TMP_IDIMP во временной таблице и собрали бы на нее статистику, то он мог бы выбрать index scan для USRSCHEMA.IMPORT.
Сам нечто похожее советовал выше, но наткнулся на один неприятный факт.
При вставке пару тысяч строк в темповую таблицу db2 занимает время порядка 5-ти секунд.
В Mssql при вставке в нормальные темповые таблицы такой же структуры пары тысячи строк (#tmp) , это порядка 1-ой секунды занимало. Поэтому к темповым таблицам DB2 отношусь настороженно, там где важно быстродействие...
...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / IBM DB2, WebSphere, IMS, U2 [игнор отключен] [закрыт для гостей] / неправильный элемент WITH в хранимой процедуре
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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