Как я могу развернуть хранимую процедуру DB2, которая записывает в таблицу, которая еще не существует (но будет к тому времени, когда она это сделает)?
Как вы, скорее всего, и поняли из следующего вопроса, я новичок в DB2 в целом. Я пытаюсь написать свою вторую хранимую процедуру с использованием IBM Data Studio и сталкиваюсь с ошибкой при ее развертывании. Смысл хранимой процедуры заключается в поиске текстовой строки в полях разных таблиц. ПРИМЕЧАНИЕ. Код не является полным и бесполезным в его текущей форме. Я пытаюсь проверить каждый шаг по мере продвижения.
Вот весь код, который у меня есть:
CREATE OR REPLACE PROCEDURE sp_find_string (in in_search_string varchar(200), in in_schema varchar(50))
DYNAMIC RESULT SETS 1
P1: BEGIN
-- #######################################################################
-- #
-- #######################################################################
declare table_a varchar(200);
declare colname varchar(200);
declare sqlcmd varchar(2000);
declare eof smallint default 0;
declare not_found condition for sqlstate '02000';
-- Declare cursor
DECLARE cursor1 CURSOR WITH RETURN for
select tabname, colname from syscat.columns c
--inner join syscat.tables t on t.tabschema = c.tabschema
-- and t.tabname = c.tabname
where tabname like 'MERLIN%'
and tabschema = in_schema;
DECLARE CONTINUE HANDLER FOR SQLSTATE '42704' -- or SQLEXCEPTION
-------------------------------------------------
if (exists
(
select 1 from sysibm.systables
where creator = 'A2815'
and name = 'DBP_TEMP_SEARCH_RESULTS'
)
) then drop table A2815.DBP_TEMP_SEARCH_RESULTS;
end if;
create table A2815.DBP_TEMP_SEARCH_RESULTS
(text_to_match varchar(200)
,table_a varchar(200)
,colname varchar(200)
,match_count bigint);
-- Cursor left open for client application
OPEN cursor1;
while eof = 0 do
p2: begin
declare continue handler for not_found set eof = 1;
fetch from cursor1 into table_a, colname;
insert into A2815.DPB_TEMP_SEARCH_RESULTS
values(table_a, colname);
end p2;
end while;
close cursor1;
--return;
END P1
Я получаю эту ошибку при попытке развернуть:
Deploy [TIO_D]A2815.SP_FIND_STRING(VARCHAR(200), VARCHAR(50))
Running
A2815.SP_FIND_STRING - Deploy started.
Create stored procedure returns SQLCODE: -204, SQLSTATE: 42704.
A2815.SP_FIND_STRING: 44: "A2815.DPB_TEMP_SEARCH_RESULTS" is an undefined name.. SQLCODE=-204, SQLSTATE=42704, DRIVER=4.18.60
"A2815.DPB_TEMP_SEARCH_RESULTS" is an undefined name.. SQLCODE=-204, SQLSTATE=42704, DRIVER=4.18.60
A2815.SP_FIND_STRING - Deploy failed.
A2815.SP_FIND_STRING - Roll back completed successfully.
Когда я закомментирую оператор вставки, он развертывается очень хорошо (но, конечно, процедура не приносит мне большой пользы без возможности вставки):
OPEN cursor1;
while eof = 0 do
p2: begin
declare continue handler for not_found set eof = 1;
fetch from cursor1 into table_a, colname;
--insert into A2815.DPB_TEMP_SEARCH_RESULTS
--values(table_a, colname);
end p2;
end while;
close cursor1;
Это правда, что таблица еще не существует, потому что она должна быть создана процедурой. Однако, если я создаю таблицу, затем развернуть процедуру, я получаю эту ошибку:
Deploy [TIO_D]A2815.SP_FIND_STRING(VARCHAR(200), VARCHAR(50))
Running
A2815.SP_FIND_STRING - Deploy started.
Create stored procedure returns SQLCODE: -601, SQLSTATE: 42710.
A2815.SP_FIND_STRING: 32: The name of the object to be created is identical to the existing name "A2815.DBP_TEMP_SEARCH_RESULTS" of type "TABLE".. SQLCODE=-601, SQLSTATE=42710, DRIVER=4.18.60
The name of the object to be created is identical to the existing name "A2815.DBP_TEMP_SEARCH_RESULTS" of type "TABLE".. SQLCODE=-601, SQLSTATE=42710, DRIVER=4.18.60
A2815.SP_FIND_STRING - Deploy failed.
A2815.SP_FIND_STRING - Roll back completed successfully.
Может кто-нибудь сказать мне, как развернуть эту процедуру, когда таблица существует, когда она не существует, или оба?
Большое спасибо и дайте мне знать, какие еще детали нужны. Кроме того, предложения о том, как улучшить код в целом, были бы также хороши.
2 ответа
Может быть, немного поздно, но лучший способ сделать это - создать строку с вашим запросом, а не использовать запрос напрямую, а затем использовать EXECUTE IMMEDIATELY
Самое простое решение - просто создать эту таблицу так, чтобы она существовала до того, как вы скомпилируете процедуру. Если вы просто запустите оператор create table перед компиляцией процедуры, проблем не будет.
Комментаторы предложили вам использовать Declare Global Temporary Table
, и я согласен с этим, так как вы, кажется, используете это как временную таблицу. Однако на самом деле это не решает вашу конкретную проблему, поскольку процедура все равно не будет компилироваться, если временная таблица не существует во время компиляции. Так что, да, используйте временную таблицу, но вам все равно придется делать то же самое.
Изменение insert
Оператор для динамического SQL также будет работать, хотя это уродливое решение. Не обязательно здесь, но иногда это необходимо.