如何在Oracle SQL中的FOR循环中创建视图

如何在Oracle SQL中的FOR循环中创建视图,sql,plsql,oracle11g,dynamic-sql,Sql,Plsql,Oracle11g,Dynamic Sql,我要做的是根据两个表之间的条件创建视图,我希望它遍历所有满足此条件的表 我做了一些研究,发现游标对这类事情很有帮助,但我在第15行遇到了“游标超出范围” DECLARE query_str VARCHAR2(32000); CURSOR all_syn IS SELECT SYNONYM_NAME, TABLE_NAME FROM ALL_SYNONYMS WHERE SYNONYM_NAME LIKE 'S!_AG!_%' ESCAPE '!'; CUR

我要做的是根据两个表之间的条件创建视图,我希望它遍历所有满足此条件的表

我做了一些研究,发现游标对这类事情很有帮助,但我在第15行遇到了“游标超出范围”

DECLARE

  query_str  VARCHAR2(32000);
  CURSOR all_syn IS
    SELECT SYNONYM_NAME, TABLE_NAME
    FROM ALL_SYNONYMS
    WHERE SYNONYM_NAME LIKE 'S!_AG!_%' ESCAPE '!';
  CURSOR our_tables IS
    SELECT TABLE_NAME
    FROM   ALL_TABLES
    WHERE  TABLE_NAME LIKE 'AG!_%1' ESCAPE '!';

BEGIN

  query_str := 'CREATE OR REPLACE VIEW ' || LTRIM(all_syn.SYNONYM_NAME, 'S_') || 'AS
        SELECT TO_CHAR(itemnum) itemnum,
               TO_CHAR(keywordnum) keywordnum,
               TO_CHAR(keysetnum) keysetnum,
               MOD_BY_EMPLOYEE,
               MOD_BY_PROCESS,
               MOD_DATE_EMPLOYEE,
               MOD_DATE_PROCESS
        FROM   all_syn.SYNONYM_NAME,
               our_tables.TABLE_NAME
        WHERE  our_tables.TABLE_NAME = ' || LTRIM(all_syn.SYNONYM_NAME, 'S_');
  FOR v_rec IN all_syn LOOP
IF (v_rec.TABLE_NAME LIKE 'KEYXITEM%') THEN
 EXECUTE IMMEDIATE query_str;

    END IF;
  END LOOP;
END;
我这样做的原因是因为我的公司有一些表没有直接连接到某个第三方DB链接,所以他们让我更改表名,在受影响的表末尾加上1,用DB链接为这些表创建同义词,然后用原始表名查看这些同义词,这样它们现在就有了DB链接并充当原始表,这样我们就不必更改任何代码。我必须将同义词表与更改的表连接起来,因为我们添加了一些第三方表没有的属性

如果任何人有任何建议或建议,将不胜感激!我不熟悉使用动态sql和PL/sql,所以请耐心听我说

编辑:

所以我改进了我的代码,我觉得我越来越接近我想要的结果,但是我得到了一个奇怪的错误:

第28行第52列: PLS-00357:在此上下文中不允许表格、视图或序列引用“所有表格。表格名称”

这对我来说没有意义,因为我在查询中声明了它

BEGIN
  FOR v_rec IN all_syn LOOP
    IF (v_rec.TABLE_NAME LIKE 'KEYXITEM%') THEN
      query_str := 'CREATE OR REPLACE VIEW ' || LTRIM(v_rec.SYNONYM_NAME, 'S_') || ' AS
          SELECT itemnum AS item_num,
                 keywordnum AS key_word_num,
                 keysetnum AS key_set_num,
                 MOD_BY_EMPLOYEE,
                 MOD_BY_PROCESS,
                 MOD_DATE_EMPLOYEE,
                 MOD_DATE_PROCESS,
          FROM   (    SELECT TABLE_NAME
                      FROM   ALL_TABLES
                      WHERE  TABLE_NAME LIKE ' || '''AG!_%1''' || ' ESCAPE ' || '''!''' || '
                         AND ' || RTRIM(ALL_TABLES.TABLE_NAME, '1') ||' = ' || LTRIM(v_rec.SYNONYM_NAME, 'S_') || ') our_tables,   
                 ' || v_rec.SYNONYM_NAME;
     -- EXECUTE IMMEDIATE query_str;
    END IF;
              dbms_output.put_line(query_str);
  END LOOP;
END;

不能像那样引用游标。将查询\u str创建移动到FOR循环中并引用记录变量

编辑:我已尝试修复FROM/WHERE子句,但您可能缺少连接条件

DECLARE
  query_str  VARCHAR2(32000);
  CURSOR all_syn IS
    SELECT SYNONYM_NAME, TABLE_NAME
    FROM ALL_SYNONYMS
    WHERE SYNONYM_NAME LIKE 'S!_AG!_%' ESCAPE '!';
  CURSOR our_tables IS
    SELECT TABLE_NAME
    FROM   ALL_TABLES
    WHERE  TABLE_NAME LIKE 'AG!_%1' ESCAPE '!';

BEGIN
  FOR v_rec IN all_syn LOOP
    IF (v_rec.TABLE_NAME LIKE 'KEYXITEM%') THEN
      query_str := 'CREATE OR REPLACE VIEW ' || LTRIM(v_rec.SYNONYM_NAME, 'S_') || 'AS
          SELECT TO_CHAR(itemnum) itemnum,
                 TO_CHAR(keywordnum) keywordnum,
                 TO_CHAR(keysetnum) keysetnum,
                 MOD_BY_EMPLOYEE,
                 MOD_BY_PROCESS,
                 MOD_DATE_EMPLOYEE,
                 MOD_DATE_PROCESS
          FROM   ' || v_rec.SYNONYM_NAME || ',
                 ' || v_rec.TABLE_NAME || '
          WHERE  ' || v_rec.TABLE_NAME = ' || LTRIM(v_rec.SYNONYM_NAME, 'S_');
      EXECUTE IMMEDIATE query_str;
    END IF;
  END LOOP;
END;

好吧,我肯定不是Oracle专家,但如果您的查询在循环之外,它会改变吗?(这对我来说是有意义的,这将产生一个范围错误)感谢您的快速响应!抱歉,第一次在sql中使用游标和循环,试图习惯它。但是,我在EXECUTE IMMEDIATE语句中遇到了一个“missing keyword”错误,我正在研究原因。如果您的查询\u str不正确,请添加一个dbms\u输出。将\u line(query\u str)行放入for循环中,以便您可以调整DDL命令本身。FROM条款似乎是个问题。必须将同义词_NAME和表_NAME连接起来。我已经调整了原来的答案。您还缺少一件事,那就是原始表和第三方表之间的某种连接条件,否则最终将使用笛卡尔连接。