PL/SQL 可重复使用的动态 sql 程序用于相同类型的任务但不同 table 和列

PL/SQL reusable dynamic sql program for same type of task but different table and column

谢谢大家的回复。我有点解决了我的问题。

我曾经尝试使用 "where current of" 在动态 SQL 中使用 ref cursor 更新数据,但我现在知道那行不通了。

然后我尝试使用 %rowtype 将 'id' 和 'clob' 存储在一个变量中以供将来更新,但结果是弱引用游标也不能使用该类型绑定。

在那之后,我尝试将记录用作引用游标的 return,但这对弱游标也不起作用。

最后,我创建了另一个游标来分别检索 'id' 以及同时检索 'clob' 的游标,然后使用该 ID 更新 table。


我现在正在处理 Oracle 数据清理任务,并且有如下要求:

有38个table(以后可能会更多),每个table有一个或多个类型为Clob的列。我需要在这些列中找到不同的关键字,并根据列的逻辑 return 二进制标签并将其存储在新列中。

例如,有一个 table 'myTable1',它有 2 个 Clob 列 'clob1' 和 'clob2'。我想从这些列中找到关键字 'sky',并在两个新列 'clob1Sky'、'clob2Sky' 中存储“0”(如果未找到)或“1”(如果找到)。 =14=]

我知道我是否可以以静态方式编写它,这样可以提供更高的效率,但我每次都必须为那些非常相似的任务修改它。我想在这上面节省一些时间,所以我试图以一种可重用的方式编写它,而不是绑定到某些 table。

但是我在写程序的时候遇到了一些问题。我的程序如下:

create or replace PACKAGE body LABELTARGETKEYWORD 
    as
    /**
    @param varcher tableName: the name of table I want to work on
    @param varchar colName: the name of clob column
    @param varchar targetWord: the word I want to find in the column
    @param varchar newColName: the name of new column which store label of clob 
    */ 
    PROCEDURE mainProc(tableName varchar, colName varchar,targetWord varchar,newColName varchar2)
    as
        type c_RecordCur is ref cursor;
        c_sRecordCur c_recordCur;
        /*other variables*/
    begin
        /*(1) check whether column of newColName exist
          (2) if not, alter add table of newColName
          (3) open cursor for retrieving clob
          (4) loop cursor
              (5) update set the value in newColName accroding to func labelword return
          (6) close cursor and commit*/
    end mainProc;

    function labelWord(sRecord VARCHAR2,targetWord varchar2) return boolean...
    function ifColExist(tableName varchar2,newColName varchar2) return boolean...
END LABELTARGETKEYWORD;

大多数 DML 和 DDL 是以动态 sql 方式编写的。

问题是当我写 (5) 部分时,我注意到 'Where current of' 子句不能用在引用游标或动态 sql 语句中。所以我不得不改变计划。

我尝试使用记录(rowid,label)来存储结果并稍后更改table。(table只能由我组中的两个人使用,所以不会'不是锁定和数据更改的问题)。但我发现因为我正在尝试使用动态 sql 所以实际上我必须用某些 %rowtype 的 return 和基本上所有其他变量定义 ref cursor,动态 sql 语句中的 %type .这让我觉得我的方法有问题。

我的问题是:

  1. 是否有办法在动态中定义 %type sql?绑定类型到动态变量 SQL?

  2. 谁能告诉我如何在动态 SQL 中编写第 (5) 部分?

  3. 我不应该这样设计我的程序吗?

  4. 是不是动态SQL或PLSQL的使用方法?

我是 PL/SQL 的新手。非常感谢你。

我不确定你的问题- 如果此作业假设每天或每小时 运行,运行 通过它进行查询将非常昂贵。你可以做的一件事 - 将你所有的 clob 数据放在一个文件中并将其保存在你的服务器中(我猜它必须是 linux)。然后你可以创建一个 shell 脚本并安排一个作业到 运行 gerp 命令并获取你需要的值和 "if found then update your table".

我认为你应该换一种方式解决问题: 1. 找到您需要的所有列:

CURSOR k_clobs
select  table_name, column_name from dba_tab_cols where data_type in ('CLOB','NCLOB');

或 2 个游标(如果每个 table 有超过 1 个 CLOB,您可以构建查询:

 CURSOR k_clobs_table
             select  DISTINCT table_name from dba_tab_cols where data_type in ('CLOB','NCLOB');

CURSOR k_clobs_columns(table_namee varchar(255)) is
         select column_name from dba_tab_cols where data_type in ('CLOB','NCLOB') and table_name = table_namee; 

现在您 100% 确定要检查的列是 clob,因此您不必担心数据类型;)

不知道你想达到什么目的,希望对你有帮助。

根据 Tom Kyte 的建议,要在一个语句中完成,如果可以在一个语句中完成,我会尝试先使用单个 UPDATE 语句:

CREATE TABLE mytable1 (id NUMBER, clob1 CLOB, 
  clob2 CLOB, clob1sky NUMBER, clob2sky NUMBER ) 
LOB(clob1, clob2) STORE AS SECUREFILE (ENABLE STORAGE IN ROW);

INSERT INTO mytable1(id, clob1, clob2) 
SELECT object_id, object_name, object_type FROM all_objects
 WHERE rownum <= 10000;

CREATE OR REPLACE 
PROCEDURE mainProc(tableName VARCHAR2, colName VARCHAR2, targetWord VARCHAR2, newColName VARCHAR2)
IS
  stmt VARCHAR2(30000);
BEGIN
  stmt := 'UPDATE '||tableName||' SET '||newColName||'=1 '||
          'WHERE DBMS_LOB.INSTR('||colName||','''||targetWord||''')>1';
  dbms_output.put_line(stmt);
  EXECUTE IMMEDIATE stmt;
END mainProc;
/

所以,用 mainProc('MYTABLE1', 'CLOB1', 'TAB', 'CLOB1SKY'); 调用它会触发语句

UPDATE MYTABLE1 SET CLOB1SKY=1 WHERE DBMS_LOB.INSTR(CLOB1,'TAB')>1

这似乎可以解决问题:

SELECT * FROM mytable1 WHERE clob1sky=1;

id  clob1    clob2  clob1sky clob2skiy
33  I_TAB1   INDEX  1   
88  NTAB$    TABLE  1   
89  I_NTAB1  INDEX  1   
90  I_NTAB2  INDEX  1   
...