FOR循环中的Oracle FOR循环

FOR循环中的Oracle FOR循环,oracle,plsql,Oracle,Plsql,这是我的密码。请原谅我没有把变量放在声明部分,因为编辑器在我提交我的问题之前给了我很长的时间来格式化它 我希望结果变量(v_Var)的值打印为 v_ID = :NEW.ID; v_NAME = :NEW.NAME; v_ENTITY_ID = :NEW.ENTITY_ID; v_ID = :NEW.ID; v_ID = :NEW.ID; v_NAME = :NEW.NAME; v_ENTITY_ID = :NEW.ENTITY_ID; 但是,它被印刷成 v_ID = :NEW.ID; v_N

这是我的密码。请原谅我没有把变量放在声明部分,因为编辑器在我提交我的问题之前给了我很长的时间来格式化它

我希望结果变量(v_Var)的值打印为

v_ID = :NEW.ID;
v_NAME = :NEW.NAME;
v_ENTITY_ID = :NEW.ENTITY_ID;
v_ID = :NEW.ID;
v_ID = :NEW.ID;
v_NAME = :NEW.NAME;
v_ENTITY_ID = :NEW.ENTITY_ID;
但是,它被印刷成

v_ID = :NEW.ID;
v_NAME = :NEW.NAME;
v_ENTITY_ID = :NEW.ENTITY_ID;
v_ID = :NEW.ID;
v_ID = :NEW.ID;
v_NAME = :NEW.NAME;
v_ENTITY_ID = :NEW.ENTITY_ID;
由于表TEMP_TRG_CONSTRNT有2行,因此它也为v_ID工作了两次。 我知道这个问题与外部FOR循环有关,但我不确定如何处理它

DECLARE
    CURSOR c1 IS 
SELECT NAME, OCCUR_COUNT FROM IFMS_SYSTEMCONFIGURATION.TEMP_TRG_CONSTRNT;


BEGIN
    v_TableName := 'MyTable';
    EXECUTE IMMEDIATE 'TRUNCATE TABLE IFMS_SYSTEMCONFIGURATION.TEMP_TRG_CONSTRNT';

    INSERT INTO IFMS_SYSTEMCONFIGURATION.TEMP_TRG_CONSTRNT (NAME, OCCUR_COUNT)
    SELECT A.FKN, COUNT(A.FKN) AS OCCUR_COUNT FROM 
    (
      SELECT A.CONSTRAINT_NAME AS FKN FROM ALL_CONSTRAINTS A
      INNER JOIN ALL_CONS_COLUMNS B
      ON A.CONSTRAINT_NAME = B.CONSTRAINT_NAME 
      WHERE  A.CONSTRAINT_TYPE IN ('P', 'U') AND A.TABLE_NAME = 'MyTable'
    )A
    GROUP BY A.FKN;

    --FOR CONSTR_NAME IN (SELECT NAME FROM IFMS_SYSTEMCONFIGURATION.TEMP_TRG_CONSTRNT)
    FOR CONSTR_NAME IN c1
    LOOP
    --SELECT NAME, OCCUR_COUNT INTO v_Constr_Name, v_Index_Count FROM TEMP_TRG_CONSTRNT WHERE NAME = CONSTR_NAME.NAME;
      FOR COL_NAME IN (SELECT COLUMN_NAME FROM ALL_CONS_COLUMNS WHERE CONSTRAINT_NAME = CONSTR_NAME.NAME)   
      LOOP
      v_Var := v_Var || 'v_' || COL_NAME.COLUMN_NAME || ' = :NEW.' || COL_NAME.COLUMN_NAME || ';' || CHR(13);
      END LOOP;
    DBMS_OUTPUT.PUT_LINE(v_Var);
    END LOOP;

    END;

可能有几个因素会导致您的结果:

  • 不同架构中有同名的表(两个表之间缺少所有者连接)
  • 同一个表上可能有多个约束
  • 除此之外,您还通过执行嵌套循环,成功地重新创建了嵌套循环联接。一般来说,这是一个坏主意-如果哈希连接的性能更好呢?通过使用嵌套游标进行循环,您将有效地阻碍Oracle。至少,在循环之前,可以将两个游标连接到一个sql语句中

    但是,看起来您正在尝试生成一个变量列表,而不必键入它们。您可以在一条SQL语句中执行此操作—无需PL/SQL,如下所示:

    SELECT DISTINCT con.constraint_name,
                    con.owner,
                    con.table_name,
                    col.column_name,
                    'v_'||col.column_name||' := :NEW.'||col.column_name||';'
    FROM   all_constraints con
           inner JOIN all_cons_columns col ON con.constraint_name = col.constraint_name
                                               AND con.owner = col.owner
                                               AND con.constraint_type IN ('P', 'U')
                                               --AND con.owner = 'SOME_OWNER' -- uncomment out and put in the correct owner name, esp if your table exists in more than one owner.
                                               AND con.table_name = 'YOUR_TABLE'
    ORDER BY con.owner, con.table_name;
    
    请注意,我已经包括了额外的专栏,这样您就可以了解为什么会得到您得到的结果,以防这与您期望看到的结果不符。我使用DISTINCT关键字来处理为单个owner.table返回多个约束的情况


    如果要同时为多个表生成变量列表,可能需要在上述查询中使用aggregate listag函数(这意味着您可以删除DISTINCT),并使用分隔符CHR(10).

    您能展示一下您已经编写了哪些代码吗?我已经用实际代码替换了前面的描述。您是否尝试过在for循环中选择DISTINCT以删除重复项?基本上我必须为每个项而不是表上的for TEMP\u TRG\n construnt做进一步的分析,我认为问题在于我在哪里构造我的字符串,对于变量v_Var。。有人请建议一种更好的方法谢谢你建议另一种方法。。我发现在我的方法中,问题在于我构建v_Var(输出)的方式,我还想补充一点,您的建议更明智。