For 循环从游标中获取数据被跳过

时间:2021-02-07 10:55:30

标签: sql oracle plsql oracle11g sqlplus

这是我正在使用的代码。我是 PL/SQL 的新手,正在对现有的 pl/sql 代码进行一些修改。

有一个游标 C_GET_REFERENCED_USER_GROUPS,它根据存储在变量 r_username 中的用户输入存储来自 sec_user_group 表的数据。

所以我提供了一些输入,这些输入将作为游标 C_GET_REFERENCED_USER_GROUPS 中使用的变量的值,并且它的输出只有几行。在 for 循环内执行光标期间,尽管有输出并且我没有给出任何退出代码的行,但 for 循环被完全跳过。

这就是 for 循环的创建方式,循环遍历游标并添加到表中。

FOR R_GROUP_NAME IN C_GET_REFERENCED_USER_GROUPS
        LOOP
                BEGIN
                        add_user_to_group_cmd :='insert into PROD.SEC_USER_GROUP VALUES('||R_GROUP_NAME.group_id||','''||l_user_id||''',sys_context(''userenv'', ''current_user''),sysdate)';
                        dbms_output.put_line(add_user_to_group_cmd||';');
                        execute immediate (add_user_to_group_cmd);
                        exception
                        when others then
                            dbms_output.put_line('>>>>> ERROR : Unable to add user to group : '||SQLERRM);    
                END;
        END LOOP;
        COMMIT;

我在执行这段代码时没有遇到任何错误,只是在循环执行 for 循环后执行完成,循环执行循环游标 C_GET_ROLE_DETAIL 并跳过上面提到的最后执行的游标执行.

我还在 PL/SQL 块开始执行期间打印了游标,只是为了通过使用简单的 for 循环来验证输出是否存在:

FOR rec IN C_GET_REFERENCED_USER_GROUPS 
            LOOP 
                DBMS_OUTPUT.put_line (rec.group_id); 
            END LOOP; 

上面确实打印了几行,但在 pl/sql 插入的最后部分没有插入相同的行。

请参阅下面的完整代码:

SET lines 200
SET trimspool ON
SET echo OFF
SET verify OFF
--SET serveroutput ON size 1000000
SET serveroutput ON size unlimited
DECLARE
  l_cmd            VARCHAR2(4000);
  l_rmsschema      VARCHAR2(5000) := trim('&&rmsschema');
  l_username       VARCHAR2(5000);
  l_password       VARCHAR2(5000);
  l_name           VARCHAR2(5000);
  l_email          VARCHAR2(5000);
  l_user_id VARCHAR2(5000) :=trim('&&userid');
  l_pwd VARCHAR2(5000) :=trim('&&password');
  l_new_username VARCHAR2(5000) :=trim('&&new_user_name');
  l_user_email VARCHAR2(5000) :=trim('&&emailid');
  r_username VARCHAR2(5000) :=trim('&&referenced_schema_name');
  insert_new_user_cmd VARCHAR2(5000);
  add_user_to_group_cmd VARCHAR2(5000);
  l_granted_roles VARCHAR2(5000);
  l_granted_groups VARCHAR2(5000);
  RMS_SCHEMA_ERROR EXCEPTION;

  CURSOR C_GET_NEW_USER_DETAIL
  IS
        select distinct nuc.user_id,nuc.pwd,nuc.user_name,nuc.user_email from PROD.NEW_USER_CREATION nuc
        where not exists ( select 1 from dba_users du where du.username=nuc.user_id );

  CURSOR C_GET_ROLE_DETAIL
  IS
        select distinct nuc.user_id,nuc.granted_role from PROD.NEW_USER_CREATION nuc order by 1;

 CURSOR C_GET_REFERENCED_USER_ROLES
        IS
        select GRANTED_ROLE from dba_role_privs where grantee=r_username;

CURSOR C_GET_REFERENCED_USER_GROUPS
        IS
        select group_id from prod.sec_user_group where user_id=r_username;

BEGIN

        ----Testing the cursor values by printing it-----
           FOR rec IN C_GET_REFERENCED_USER_GROUPS 
            LOOP 
                DBMS_OUTPUT.put_line (rec.group_id); 
            END LOOP; 

        ------Insert into NEW_USER_CREATION_TABLE----------
        OPEN C_GET_REFERENCED_USER_ROLES;
        dbms_output.put_line('TRUNCATE TABLE PROD.NEW_USER_CREATION');
        EXECUTE immediate 'TRUNCATE TABLE PROD.NEW_USER_CREATION';
        LOOP
        FETCH C_GET_REFERENCED_USER_ROLES into l_granted_roles;
        EXIT when C_GET_REFERENCED_USER_ROLES%NOTFOUND;
        insert_new_user_cmd := 'insert into PROD.NEW_USER_CREATION(USER_ID,PWD,USER_NAME,USER_EMAIL,GRANTED_ROLE)  VALUES('''|| l_user_id ||''','''||l_pwd||''','''||l_new_username||''','''||l_user_email||''','''||l_granted_roles||''')';
        dbms_output.put_line(insert_new_user_cmd||';');
        execute immediate (insert_new_user_cmd);
        commit;
        END LOOP;
        CLOSE C_GET_REFERENCED_USER_ROLES;


        --  User Creation-------------------------------------------------------------------------
        FOR A_REC IN C_GET_NEW_USER_DETAIL
        LOOP
            BEGIN
                l_username                     := A_REC.USER_ID;
                l_password                     := A_REC.PWD;
                l_name                         := A_REC.USER_NAME;
                l_email                        := A_REC.USER_EMAIL;
                
                BEGIN
                    dbms_output.put(CHR(10));
                    dbms_output.put_line('Creating RMS');
                    BEGIN
                        l_cmd := 'CREATE USER "'||l_username||'" identified by "'||l_password||'" DEFAULT TABLESPACE USERS TEMPORARY TABLESPACE TEMP01';
                        dbms_output.put_line(l_cmd||';');
                        EXECUTE immediate (l_cmd);
                    EXCEPTION
                    WHEN OTHERS THEN
                        dbms_output.put_line('>>>>> ERROR : CREATE USER : '||SQLERRM);
                    END;
                    
                    BEGIN
                        --l_cmd := 'INSERT INTO '||l_rmsschema||'.USER_ATTRIB(USER_ID, USER_NAME, LANG, USER_EMAIL) VALUES('''||l_username||''','''||l_name||''',''1'','''||l_email||''')';
                        l_cmd := 'MERGE INTO '||l_rmsschema||'.USER_ATTRIB TGT';
                        l_cmd := l_cmd || ' USING (SELECT DISTINCT USER_ID,USER_NAME, USER_EMAIL FROM '||l_rmsschema||'.NEW_USER_CREATION WHERE user_id=''' || A_REC.USER_ID  || ''') SRC';
                        l_cmd := l_cmd || ' ON (TGT.USER_ID = SRC.USER_ID )';
                        l_cmd := l_cmd || ' WHEN NOT MATCHED THEN';
                        l_cmd := l_cmd || ' INSERT (USER_ID, USER_NAME, LANG, USER_EMAIL)';
                        l_cmd := l_cmd || ' VALUES ('''||l_username||''','''||l_name||''',''1'','''||l_email||''')';
                        dbms_output.put_line(l_cmd||';');
                        EXECUTE immediate(l_cmd);
                    
                        COMMIT;
                        --CR_SYNONYMS
                        BEGIN
                        declare
                            missing_object         varchar2(128);
                            prefix1                varchar2(128);
                            prefix2                varchar2(128);
                            cursor c_get_missing_object is
                                select object_name
                                from   dba_objects
                                where  owner = upper(l_rmsschema)
                                    and object_type in ('TABLE', 'VIEW', 'CLUSTER', 'FUNCTION', 'PACKAGE', 'PROCEDURE', 'SEQUENCE', 'TYPE')
                                    and object_name not like 'DBC_%'
                                    and object_name not like 'BIN$%'
                                MINUS
                                select object_name
                                from   dba_objects
                                where  owner = upper(l_username)
                                order by 1;
                        begin
                            if l_username <> '&_USER' then
                                prefix1:='"' || l_username || '".';
                            else
                                prefix1:='';
                            end if;
                            if l_rmsschema <> '&_USER' then
                                prefix2:='"' || l_rmsschema || '".' ;
                            else
                                prefix2:='';
                            end if;
        
                            open c_get_missing_object;
                            LOOP
                                fetch c_get_missing_object into missing_object;
                                --When at end of objects, exit
                                if c_get_missing_object%NOTFOUND then
                                    exit;
                                end if;
                    
                                BEGIN
                                    execute immediate 'CREATE SYNONYM '||prefix1||'"'||missing_object||'" FOR '||prefix2||'"'||missing_object||'"';
                                    dbms_output.put_line('Created synonym '||prefix1||missing_object||' pointing to '||prefix2||missing_object);
                                EXCEPTION
                                WHEN OTHERS THEN
                                    dbms_output.put_line('Create synonym FAILED '||missing_object||' '||SQLCODE||' - '||SQLERRM);
                                END;
                            END LOOP;
                            close c_get_missing_object;
                        end;
                    END;
                    EXCEPTION
                    WHEN OTHERS THEN
                        dbms_output.put_line('>>>>> ERROR RMS: INSERT USER_ATTRIB: '||SQLERRM);
                    END;
                EXCEPTION
                WHEN OTHERS THEN
                dbms_output.put_line('>>>>> ERROR : '||SQLERRM);
                END;
            EXCEPTION
            WHEN NO_DATA_FOUND THEN
                EXIT ;
            END;
        END LOOP;
    -- RMS Role Assignment------------------------------------------------------------------------- 
        FOR A_REC IN C_GET_ROLE_DETAIL
        LOOP
        -- RMS Role Assignment-------------------------------------------------------------------------
            begin
                    l_cmd := 'grant '|| A_REC.GRANTED_ROLE ||'  to "'||A_REC.USER_ID||'"';
                    dbms_output.put_line(l_cmd||';');
                    execute immediate (l_cmd);
                exception
                when others then
                    dbms_output.put_line('>>>>> ERROR : GRANT PRIVILEGES : '||SQLERRM);
            end;
        end loop; 
        commit;
        EXCEPTION
        WHEN utl_file.invalid_path THEN
        raise_application_error(-20000, 'Invalid path. Create directory or set UTL_FILE_DIR.');
        WHEN OTHERS THEN
        dbms_output.put_line('>>>>> ERROR : '||SQLERRM);
        
-----Adding user to groups-----------------------------------------------------------------------

        FOR R_GROUP_NAME IN C_GET_REFERENCED_USER_GROUPS
        LOOP
                BEGIN
                        add_user_to_group_cmd :='insert into PROD.SEC_USER_GROUP VALUES('||R_GROUP_NAME.group_id||','''||l_user_id||''',sys_context(''userenv'', ''current_user''),sysdate)';
                        dbms_output.put_line(add_user_to_group_cmd||';');
                        execute immediate (add_user_to_group_cmd);
                        exception
                        when others then
                            dbms_output.put_line('>>>>> ERROR : Unable to add user to group : '||SQLERRM);    
                END;
        END LOOP;
        COMMIT;
END;
/

我已将输出假脱机到日志文件中:这是日志文件的一部分:

Enter value for rmsschema: prod
Enter value for userid: SCOTT
Enter value for password: scott
Enter value for new_user_name: scott
Enter value for emailid: scott@test
Enter value for referenced_schema_name: 23093
1404 
8322//These are the two values that are returned by the cursor and after that should be inserted into the table SEC_USER_GROUP but it's somehow getting skipped.////
TRUNCATE TABLE prod.NEW_USER_CREATION
insert into prod.NEW_USER_CREATION(USER_ID,PWD,USER_NAME,USER_EMAIL,GRANTED_ROLE)  VALUES('SCOTT','scott','scott','scott@test','TEST_USER_ROLE');
insert into prod.NEW_USER_CREATION(USER_ID,PWD,USER_NAME,USER_EMAIL,GRANTED_ROLE)  VALUES('SCOTT','scott','scott','scott@test','CUSTOMER_ROLE');

Creating RMS
CREATE USER "SCOTT" identified by "scott" DEFAULT TABLESPACE USERS TEMPORARY TABLESPACE TEMP01;
MERGE INTO prod.USER_ATTRIB TGT USING (SELECT DISTINCT USER_ID,USER_NAME, USER_EMAIL FROM prod.NEW_USER_CREATION WHERE user_id='SCOTT') SRC ON (TGT.USER_ID = SRC.USER_ID ) WHEN NOT
MATCHED THEN INSERT (USER_ID, USER_NAME, LANG, USER_EMAIL) VALUES ('SCOTT','scott','1','scott@test');
//Synonyms for the user created
Created synonym "SCOTT".AA_XX_ITEM pointing to "prod".AA_XX_ITEM
Created synonym "SCOTT".ACC_VALIDATE_API pointing to "prod".ACC_VALIDATE_API
Created synonym "SCOTT".ADDR pointing to "prod".ADDR
Created synonym "SCOTT".ADDRESS_SQL pointing to "prod".ADDRESS_SQL
.................................................................
grant TEST_USER_ROLE  to "SCOTT";
grant CUSTOMER_ROLE  to "SCOTT";

PL/SQL procedure successfully completed.

如上所示,即使游标返回行,代码的最后部分也不会执行。

0 个答案:

没有答案