没有使用级别或开始时出现ORA-01788错误

Fre*_*hen 0 oracle plsql

我刚刚开始学习PL/SQL.在stackoverflow中发布帖子后,我编写了一个脚本来搜索Oracle中的某个值,如下所示:

DECLARE
  match_count INTEGER;
  v_owner VARCHAR2(255);
  v_search_value NUMBER;
BEGIN
  v_owner:='USERA USERB';
  v_search_value:=4823.0;
  EXECUTE IMMEDIATE
  'INSERT INTO TMP SELECT owner, table_name, column_name FROM all_tab_cols WHERE instr(:1, owner)>0 AND data_type like ''%NUMBER%''' USING v_owner;
  commit;
  FOR t IN (SELECT owner, table_name, column_name FROM TMP) LOOP
    EXECUTE IMMEDIATE 
    'SELECT COUNT(*) FROM '||t.owner||'.'||t.table_name||' WHERE '||t.column_name||'= :1'
    INTO match_count
    USING v_search_value;
    IF match_count > 0 THEN
      EXECUTE IMMEDIATE
      'INSERT INTO RESULT VALUES(:1, :2, :3, :4)'
      USING t.owner, t.table_name, t.column_name, match_count;
      commit;
    END IF;
  END LOOP;
END;
Run Code Online (Sandbox Code Playgroud)

在执行脚本之前已正确创建表TMP和RESULT.但是,当我运行脚本时,我收到一个ORA-01788错误,说第12行说"需要连接by子句".我想知道为什么代码会导致此错误以及如何更改脚本以便正确执行.谢谢!

Ale*_*ole 5

你可能有一个带有一个列的表level(正如Florin在我不看时所建议的那样),这是一个保留字.

它可能在任何情况下 - 不只是level,但是LEVEL,或Level- 所以检查你可以这样做:

select owner, table_name, column_name
from all_tab_columns
where upper(column_name) = 'LEVEL';
Run Code Online (Sandbox Code Playgroud)

或者查找正在使用的任何保留字(尽管这并不总能找到所有潜在的问题):

select atc.owner, atc.table_name, atc.column_name, vrw.keyword
from all_tab_columns atc
join v$reserved_words vrw on vrw.keyword = upper(atc.column_name);
Run Code Online (Sandbox Code Playgroud)

您可以对其他地方运行类似的查询all_tablesall_objects查找潜在问题.

如果我运行您的查询的修改版本而不打扰TMP表 - 不知道为什么你想要那个; 不使用动态SQL进行插入; 不提交(这在块中是一件奇怪的事情 - 你不需要在每次插入后都这样做); 只是为了我的利益只显示匹配而不是需要构建results表:

declare
  match_count integer;
  v_owner varchar2(255);
  v_search_value number;
begin
  v_owner := 'USERA USERB';
  v_search_value := 4823.0;
  for t in (
      select owner, table_name, column_name
      from all_tab_cols
      where instr(v_owner, owner) > 0
      and data_type like '%NUMBER%'
    ) loop
    execute immediate 
      'select count(*) from ' || t.owner ||'.'|| t.table_name
        || ' where ' || t.column_name || ' = :1'
      into match_count using v_search_value;
    if match_count > 0 then
--    insert into results values (t.owner, t.table_name,
--      t.column_name, match_count);
      dbms_output.put_line('Matched ' || t.owner ||'.'|| t.table_name
        ||'.'|| t.column_name ||': '|| match_count);
    end if;
  end loop;
end;
/
Run Code Online (Sandbox Code Playgroud)

......这成功完成了.如果我添加一个包含level列的表:

create table t42 ("LEVEL" number);
Run Code Online (Sandbox Code Playgroud)

...然后再次运行相同的块然后我也得到:

ORA-01788: CONNECT BY clause required in this query block
ORA-06512: at line 14
01788. 00000 -  "CONNECT BY clause required in this query block"
*Cause:    
*Action:
Run Code Online (Sandbox Code Playgroud)

除了避免在对象名称中保留单词之外,您可以通过将所有对象名称括在双引号中来完成此工作:

    execute immediate 
      'select count(*) from "' || t.owner ||'"."'|| t.table_name
        || '" where "' || t.column_name || '" = :1'
      into match_count using v_search_value;
Run Code Online (Sandbox Code Playgroud)

这也将处理混合大小写的对象名称,您也应该避免使用它们.