简体   繁体   English

PL / SQL:遍历%ROWTYPE中的属性

[英]PL/SQL: Loop through attributes in a %ROWTYPE

I have a matrix in excel where in the first column I have user names and in the second and subsequent columns I have role names and a 'Y' if a user is a member of the role: 我在excel中有一个矩阵,其中第一列中有用户名,第二列和后续列中有角色名,如果用户是该角色的成员,则为'Y':

User Role1 Role2 Role3
Jon   Y      Y
Mary         Y    Y

I need to load this into an Oracle database. 我需要将其加载到Oracle数据库中。 In the database I already have a table for users: 在数据库中,我已经有一个供用户使用的表:

UserId Username
1        Jon
2        Mary

I need to take the roles ie Role1, Role2, Role3 and load it into a roles table: 我需要担任角色,例如Role1,Role2,Role3,并将其加载到角色表中:

roleId role
1      Role1
2      Role2
3      Role3

And then I need to load the role memberships into a role mapping table: 然后,我需要将角色成员资格加载到角色映射表中:

UserId RoleId
1      1
1      2
2      2
2      3

So far I created a table with Column1,Column2,Column3 attributes and loaded the Excel sheet in there with SQL developer without using the HEADER ! 到目前为止,我创建了一个具有Column1,Column2,Column3属性的表,并在其中使用SQL Developer将Excel工作表加载到其中,而无需使用HEADER

Column1 Column2 Column3 Column4
User    Role1   Role2   Role3
Jon     Y       Y
Mary            Y       Y

From here I'm trying to use a stored procedure to loop through the table with a cursor and where I find the value 'User' in Column1, loop through the attributes in that row and add those to the roles table, etc. 在这里,我尝试使用存储过程通过游标遍历表,并在Column1中找到值“ User”,遍历该行中的属性并将其添加到角色表,等等。

However I'm having trouble looping through the attributes within the CURSOR in each %ROWTYPE. 但是,我在遍历每个%ROWTYPE中CURSOR中的属性时遇到麻烦。

Is this a good approach? 这是一个好方法吗? How can I loop through each attribute in a %ROWTYPE? 如何遍历%ROWTYPE中的每个属性?

This is what I'd do (I'm going for a generalised version here, since you didn't mention your Oracle version you're using. If you're on 11g or above, you could do the unpivoting using the UNPIVOT command): 这就是我要做的(我将在这里使用通用版本,因为您没有提到您正在使用的Oracle版本。如果您使用的是11g或更高版本,则可以使用UNPIVOT命令取消透视):

Setup for my example insert statements: 我的示例插入语句的设置:

create table data_to_upload as
select 'User' col1, 'Role1' col2, 'Role2' col3, 'Role3' col4 from dual union all
select 'Jon' col1, 'Y' col2, 'Y' col3, null col4 from dual union all
select 'Mary' col1, null col2, 'Y' col3, 'Y' col4 from dual;

create table test_users as
select 1 userid, 'Jon' username from dual union all
select 2 userid, 'Mary' username from dual;

create table test_roles (roleid number,
                         rolename varchar2(20));

create sequence test_roles_seq
  start with 1
  maxvalue 9999
  minvalue 1
  nocycle
  cache 20;

create table test_user_roles (userid number, roleid number);

Insert Roles: 插入角色:

insert into test_roles
select test_roles_seq.nextval roleid,
       case when dummy.id = 1 then (select col2 from data_to_upload where col1 = 'User')
            when dummy.id = 2 then (select col3 from data_to_upload where col1 = 'User')
            when dummy.id = 3 then (select col4 from data_to_upload where col1 = 'User')
       end rolename
from   data_to_upload dto
       cross join (select level id
                   from   dual
                   connect by level <= 3 -- number of roles being imported
                  ) dummy
where col1 = 'User';

commit;

Insert User Roles: 插入用户角色:

insert into test_user_roles
select tu.userid,
       case when dummy.id = 1 then (select tr.roleid from data_to_upload dtu2 inner join test_roles tr on (dtu2.col2 = tr.rolename) where dtu2.col1 = 'User')
            when dummy.id = 2 then (select tr.roleid from data_to_upload dtu2 inner join test_roles tr on (dtu2.col3 = tr.rolename) where dtu2.col1 = 'User')
            when dummy.id = 3 then (select tr.roleid from data_to_upload dtu2 inner join test_roles tr on (dtu2.col4 = tr.rolename) where dtu2.col1 = 'User')
       end roleid
from   data_to_upload dtu
       inner join test_users tu on (dtu.col1 = tu.username)
       inner join (select level id
                   from   dual
                   connect by level <= 3 -- number of roles being imported
                  ) dummy on ((dummy.id = 1 and dtu.col2 = 'Y')
                              or (dummy.id = 2 and dtu.col3 = 'Y')
                              or (dummy.id = 3 and dtu.col4 = 'Y'))
where col1 != 'User';

commit;

Both statements unpivot the columns into rows and then select the relevant values before inserting the values. 这两个语句都将列取消透视成行,然后在插入值之前选择相关的值。

No need for loops or anything. 不需要循环或任何东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM