Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / IBM DB2, WebSphere, IMS, U2 [игнор отключен] [закрыт для гостей] / DB2: курсор, зависящий от условия / 4 сообщений из 4, страница 1 из 1
16.10.2014, 18:20
    #38779010
eklm86
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DB2: курсор, зависящий от условия
То есть, что-то такое
Код: plsql
1.
2.
3.
4.
IF (@DDY = '000')
THEN DECLARE C1 CURSOR FOR SELECT * FROM table1
ELSE DECLARE C1 CURSOR FOR SELECT * FROM table1 O WHERE O.RRY = @DDY
END IF;



Этот код не компилируется:
авторMessage: [SQL0104] Лексема C1 недопустима. Допустимые лексемы: GLOBAL. Причина . . . . : В лексеме C1 обнаружена синтаксическая ошибка.


Подумал о COALESCE, что-то вроде:
Код: plsql
1.
2.
3.
4.
5.
6.
DECLARE C1 CURSOR FOR SELECT * FROM table1 O WHERE O.RRY IN (COALESCE(
CASE @DDY
WHEN '000' THEN (SELECT P.RRY FROM table1 P)
ELSE @CCY
END,
CAST(NULL AS CHAR(10))));

но COALESCE вернет первое не-null значение, даже если вывод запроса SELECT P.RRY FROM table1 P отформатировать, чтобы список результатов шел через запятую.
Если SELECT P.RRY FROM table1 возвращает одну строку, то эта конструкция работает, но у меня другой случай.
...
Рейтинг: 0 / 0
16.10.2014, 23:11
    #38779199
mustaccio
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DB2: курсор, зависящий от условия
eklm86,

Первый вариант не работает, поскольку все DECLARE должны предшествовать первому исполняемому предложению.

В зависимости от того, что вы дальше делаете с этими курсорами, можете попробовать так:

Код: sql
1.
2.
3.
4.
5.
6.
7.
DECLARE C1 CURSOR FOR SELECT * FROM table1;
DECLARE C2 CURSOR FOR SELECT * FROM table1 O WHERE O.RRY = @DDY;
IF (@DDY = '000') THEN 
  OPEN C1;
ELSE
  OPEN C2;
END IF;



или попросту так:
Код: sql
1.
DECLARE C1 CURSOR FOR SELECT * FROM table1 O WHERE @DDY = '000' OR O.RRY = @DDY;
...
Рейтинг: 0 / 0
17.10.2014, 12:57
    #38779827
eklm86
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DB2: курсор, зависящий от условия
Мне подошел второй вариант, спасибо.
...
Рейтинг: 0 / 0
20.10.2014, 18:28
    #38782173
CawaSPb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
DB2: курсор, зависящий от условия
eklm86,

Я бы предложил отнестись к варианту с "или" осторожно с точки зрения производительности.
Preemptive optimization - это, конечно, тоже плохо, но совсем не оглядываться на то, "как оно будет выполняться", не стоит.

Полная выборка будет осуществляться table scan'ом (если мы не настояли на обратном в профиле оптимизации).

Выборка по RRY - или table scan'ом, или по индексу (если для RRY есть индекс) в зависимости от того, что оптимизатор посчитает более эффективным.
Для разных значений @DDY это может быть по-разному ( поэтому иногда правильней указать значение в предикате явно, а не параметром, чтобы оптимизатор строил план исходя из статистики по конкретному значению ).

По запросу с условием "WHERE @DDY = '000' OR O.RRY = @DDY" будет строиться единый для обоих вариантов план (грубо - "всегда полный скан таблицы"), что для вариантов с заданным @DDY может оказаться очень неэффективным.

В общем, если количество строк в таблице хоть сколько-нибудь существенно и сканирование по индексу эффектиивней, попробуйте использовать:
Код: sql
1.
2.
3.
4.
DECLARE C1 CURSOR FOR 
  SELECT * FROM table1 WHERE @DDY = '000' 
  UNION ALL 
  SELECT * FROM table1 WHERE @DDY <> '000' AND RRY = @DDY;

это разобъёт план на две самостоятельные ветки (проконтролируйте только, что при @DDY <> '000' первый скан действительно не будет физически выполняться).

Возможно, лучше формировать запрос динамически (если различных значений @DDY немного и это не повлияет сильно на кэш запросов):
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
declare STMT1 STATEMENT;
declare C1 cursor for STMT1;

PREPARE STMT1 from 
  'select * from table1 O '
    || CASE @DDY  
         WHEN '000' THEN '' 
         ELSE 'where O.RRY = ''' || REPLACE(@DDY, '''', '''''') || ''''
       END;
 
OPEN C1;

Это эффективно, если у нас есть значения RRY с сильно разной селективностью (будут строиться разные планы). Похожего результата можно добиться партиционированием по RRY (даже оставляя значение параметризованным, а запрос - статическим).


Но вообще, я не представляю себе ситуации, где можно использовать курсоры, но нельзя выбрать тот или иной, используя условные языковые конструкции.
Разве что, текст одной и той же процедуры пишут два разных кодера, и существует некоторая "name convention", как API по передаче информации из первой части процедуры во вторую. Но это, конечно, в корне неправильно.

Для некоторых ситуаций (с рядом ограничений) можно вообще вот так:
Код: sql
1.
2.
3.
4.
5.
6.
7.
DECLARE C1  CURSOR;

IF (@DDY = '000') THEN 
  SET C1 = CURSOR FOR SELECT * FROM test1;
ELSE
  SET C1 = CURSOR FOR SELECT * FROM test1 O WHERE O.RRY = @DDY;
END IF;
...
Рейтинг: 0 / 0
Форумы / IBM DB2, WebSphere, IMS, U2 [игнор отключен] [закрыт для гостей] / DB2: курсор, зависящий от условия / 4 сообщений из 4, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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