Stored procedures 如何部署一个DB2存储过程,将数据写入一个尚不存在的表中(但当它这样做时,它就会存在)?

Stored procedures 如何部署一个DB2存储过程,将数据写入一个尚不存在的表中(但当它这样做时,它就会存在)?,stored-procedures,db2,ibm-data-studio,Stored Procedures,Db2,Ibm Data Studio,正如您很可能从下面的问题中推断的那样,我对DB2基本上是新手。我正试图使用IBMDataStudio编写第二个存储过程,但在尝试部署它时遇到了一个错误。存储过程的要点是在不同表的字段中搜索文本字符串。注意:代码不完整,在当前形式下不有用。我正在尝试测试每一步 以下是迄今为止我掌握的所有代码: CREATE OR REPLACE PROCEDURE sp_find_string (in in_search_string varchar(200), in in_schema varchar(50))

正如您很可能从下面的问题中推断的那样,我对DB2基本上是新手。我正试图使用IBMDataStudio编写第二个存储过程,但在尝试部署它时遇到了一个错误。存储过程的要点是在不同表的字段中搜索文本字符串。注意:代码不完整,在当前形式下不有用。我正在尝试测试每一步

以下是迄今为止我掌握的所有代码:

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.
当我注释掉insert语句时,它可以很好地部署(但如果没有插入功能,当然这个过程对我没有多大好处):

确实,该表还不存在,因为它应该由过程创建。但是,如果创建表,然后部署过程,则会出现以下错误:

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.
有人能告诉我如何在表存在、不存在或两者都存在的情况下部署此过程吗


非常感谢,请告诉我还需要哪些其他细节。另外,关于如何改进代码的建议也很好。

最简单的解决方案就是在编译过程之前创建该表,使其存在。如果您只是在编译过程之前手动运行CREATETABLE语句,那么就不会有问题

评论者建议您应该使用,我同意这一点,因为您似乎将此用作临时表。但是,它实际上并不能解决您的特定问题,因为如果临时表在编译时不存在,则该过程仍然不会编译。所以,是的,使用一个临时表,但是你仍然需要做同样的事情


insert
语句更改为动态SQL也会起作用,尽管这是一个丑陋的解决方案。这里不需要,但有时需要

最简单的解决方案就是在编译过程之前创建该表,使其存在。如果您只是在编译过程之前手动运行CREATETABLE语句,那么就不会有问题

评论者建议您应该使用,我同意这一点,因为您似乎将此用作临时表。但是,它实际上并不能解决您的特定问题,因为如果临时表在编译时不存在,则该过程仍然不会编译。所以,是的,使用一个临时表,但是你仍然需要做同样的事情


insert
语句更改为动态SQL也会起作用,尽管这是一个丑陋的解决方案。这里不需要,但有时需要

可能有点晚,但最好的方法是在查询中创建字符串,而不是直接使用查询,然后使用立即执行可能有点晚,但最好的方法是在查询中创建字符串,而不是直接使用查询,然后使用“立即执行”

看看这是否给了您一个主意:更好的主意-如果您的版本支持,请使用。您当前的程序一次只允许使用一次(使用此程序的人2会踩满人1)。或者可能不转储到临时表中,只从原始游标读取:毕竟,您必须打开第二个游标才能从临时表中读取完全相同的信息。不过,我不确定你打算用所有的列名做什么。谢谢@mustaccio和@clockworkmuse的回复。我今天将回到这一点,并将研究这两个答案。最终的想法是模仿这里所示的SQL Server版本中的操作:
set@sqlcmd='insert into temp_text_match(text_to_match,table_a,colname,match_count)选择'+char(39)+@text_to_match+char(39)+'+char table_a+char(39)+','+char char 39)+@colname+char(39)+',count(*)从“++@table_a+”中的“++@colname+”类似“+char(39)+”%'++@text_到“\u match+'%'+char(39)print@sqlcmd exec(@sqlcmd)
看看这是否给了您一个主意:更好的主意-如果您的版本支持,请使用。您当前的程序一次只允许使用一次(使用此程序的人2会踩满人1)。或者可能不转储到临时表中,只从原始游标读取:毕竟,您必须打开第二个游标才能从临时表中读取完全相同的信息。不过,我不确定你打算用所有的列名做什么。谢谢@mustaccio和@clockworkmuse的回复。我今天将回到这一点,并将研究这两个答案。最终的想法是模仿这里所示的SQL Server版本中的操作:
set@sqlcmd='insert into temp_text_match(text_to_match,table_a,colname,match_count)选择'+char(39)+@text_to_match+char(39)+'+char table_a+char(39)+','+char char 39)+@colname+char(39)+',count(*)从“++@table_a+”中的“++@colname+”类似“+char(39)+”%'+@text_到“+match+'%'+char(39)print@sqlcmd exec(@sqlcmd)
感谢您对@dan1111的回复。我试图在已经创建了表的情况下部署该过程,也就是当我遇到上面提到的“要创建的对象的名称与现有名称相同”错误时。我有什么误解吗?谢谢你的回复@dan1111。我试图在已经创建了表的情况下部署该过程,也就是当我遇到上面提到的“要创建的对象的名称与现有名称相同”错误时。我是不是误解了什么?
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.