1

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

我曾经尝试使用“where current of”在动态 SQL 中使用 ref 游标更新数据,但我现在知道这行不通。

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

之后,我尝试使用记录作为参考游标的返回,这也不适用于弱游标。

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


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

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

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

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

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

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)来存储结果并稍后更改表。(该表仅供我组中的两个人使用,因此不会出现锁定和数据更改的问题)。但我发现因为我正在尝试使用动态 sql,所以实际上我必须定义 ref 游标,返回某些 %rowtype 和基本上所有其他变量, %type 在动态 sql 语句中。这让我觉得我的方法有问题。

我的问题是:

  1. 如果有办法在动态 sql 中定义 %type?将类型绑定到动态 SQL 中的变量?

  2. 谁能给我一个提示如何在动态 SQL 中编写 (5) 部分?

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

  4. 这不是如何使用动态SQL或PLSQL的方式吗?

我对 PL/SQL 很陌生。非常感谢。

4

3 回答 3

1

根据 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   
...
于 2018-06-06T08:53:14.210 回答
0

我不确定你的问题 - 如果这项工作假设每天或每小时运行一次,通过它运行查询将非常昂贵。您可以做的一件事 - 将所有clob数据放在一个文件中并将其保存在您的服务器中(我想它必须是 linux)。然后你可以创建一个shell脚本并安排一个作业来运行gerp命令并获取你需要的值和“如果找到然后更新你的表”。

于 2018-06-05T04:32:35.040 回答
0

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

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

或 2 个游标(如果每个表有超过 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,因此您不必担心数据类型;)

我不确定你想要实现什么,但我希望它可以帮助你。

于 2018-06-05T05:35:17.603 回答