Привет, у меня есть эта функция:
CREATE or replace FUNCTION Tablereturn (SWITCHER INTEGER)
RETURNS TABLE (Test CHAR(9),
tester INTEGER
)
LANGUAGE SQL
CONTAINS SQL
DETERMINISTIC
NO EXTERNAL ACTION
BEGIN
DECLARE SELECT1, SELECT2 VARCHAR(1024);
set select1 ='SELECT TEST, TESTER FROM TESTTAB';
set select2 ='SELECT DUMMY, JAR, BRAND FROM TESTTAB';
IF (SWITCHER = '1') THEN return select1;
ELSEIF (SWITCHER = '2') THEN return select2;
END IF;
RETURN TABLE;
END@
Звонок был бы
select TEST from TABLE(Tablereturn(1))@
или
select JAR from TABLE(Tablereturn(2))@
Проблема в том, что это не работает. Компилятор сообщает, что после возврата появляется неожиданный токен «SELECT1». Я хочу иметь возможность вызывать его как таблицу и выбирать значения по мере необходимости из вызова. Я не могу просто назвать это процедурой с select as return, так как мне нужно работать с select как с таблицей и изменять возвращаемый результат в большем выборе. Могу ли я использовать EXECUTE IMMEDIATE в функции?
Любые идеи? Другой вопрос: как заставить функцию возвращать разные таблицы? Select2 возвращает 3 значения, а select1 возвращает только 2.
Спасибо за помощь.
Возможный дубликат Как выполнить строку SQL в DB2
Он не компилируется, потому что select1 не принимается
Не понимаю, почему это дубликат?
Могу ли я выполнить EXECUTE IMMEDIATE в функции?
В select2 есть еще одна проблема ... "ВЫБЕРИТЕ DUMMY, JAR, BRAND" ... вы выбираете 3 поля, а вам нужно только 2 поля ...
Попробуйте объявить SELECT1 и 2 в отдельной строке: DECLARE SELECT1 VARCHAR (1024) DEFAULT '' ; DECLARE SELECT2 VARCHAR (1024) DEFAULT '' ;
Оператор RETURN должен быть последним оператором функции. Существует класс функций, называемых «конвейерными», в которых вы можете использовать логику «если, то иначе». Нравится:
CREATE OR REPLACE FUNCTION TEST_PIPELINED(P_CHOICE INT)
RETURNS TABLE (R_COL1 VARCHAR(128), R_COL2 VARCHAR(128))
BEGIN
DECLARE SQLSTATE CHAR(5);
DECLARE L_COL1 VARCHAR(128);
DECLARE L_COL2 VARCHAR(128);
DECLARE c1 CURSOR FOR S1;
IF P_CHOICE=1 THEN
PREPARE S1 FROM 'SELECT COLNAME, COLNO FROM SYSCAT.COLUMNS FETCH FIRST 10 ROWS ONLY';
ELSE
PREPARE S1 FROM 'SELECT TABNAME, OWNER FROM SYSCAT.TABLES FETCH FIRST 10 ROWS ONLY';
END IF;
OPEN c1;
L1: LOOP
FETCH c1 INTO L_COL1, L_COL2;
IF SQLSTATE<>'00000' THEN LEAVE L1; END IF;
PIPE(L_COL1, L_COL2);
END LOOP L1;
CLOSE c1;
RETURN;
END@
Есть ли способ вернуть разные таблицы в зависимости от P_CHOICE?
Если вы спросите о наборах результатов разной структуры, то нет, вы не сможете. Ваш результирующий набор должен иметь такую же структуру, как объявлено в предложении RETURN TABLE (...). У нас есть класс функций, называемый «универсальным», в котором вы можете объявить структуру набора результатов во время выполнения. Но это могут быть только JAVA (внешние) функции, но не SQL.
Альтернативой использованию PIPE
было бы что-то простое вроде этого
CREATE OR REPLACE FUNCTION TEST_CHOICE(P_CHOICE INT)
RETURNS TABLE (R_COL1 VARCHAR(128), R_COL2 VARCHAR(128))
RETURN
SELECT COLNAME, TYPENAME FROM SYSCAT.COLUMNS WHERE P_CHOICE = 1
UNION ALL
SELECT TABNAME, OWNER FROM SYSCAT.TABLES WHERE P_CHOICE = 2
;
Что значит «не работает»?