是否可以在使用SELECT创建的命令上使用Oracle EXECUTE IMMEDIATE?

时间:2013-03-04 22:37:01

标签: sql oracle

考虑一个拥有大量过期用户帐户的Oracle 11gR2数据库。我想重新启用所有用户帐户而不更改任何密码。

这是一个SQL语句,用于创建可以执行以重新启用帐户的ALTER USER个SQL语句字符串:

select listagg( cmds, ' ' ) within group ( order by rownum )
    as cmd
from (
    select
        'alter user "' || d.username || '"' ||
            ' identified by values ''' || u.password || '''' ||
            ' account unlock;'
    as
        cmds
    from
        dba_users d, sys.user$ u
    where
        d.user_id = u.user#
);

此查询的结果是一个包含以下内容的字符串:

alter user "USERNAME" identified by values '1234567890ABCDEF' account unlock; ...

我确定可以创建PL / SQL过程来将此查询的结果存储到变量中,然后调用EXECUTE IMMEDIATE [var],但是可以通过一些SQL语法魔法来获取{{1}简单地执行EXECUTE IMMEDATE语句创建的字符串?

2 个答案:

答案 0 :(得分:2)

您不需要存储过程,可以使用匿名PL / SQL块:

DECLARE
   stmt varchar(5000);
   cursor get_users
   is
    select d.username, u.password
    from dba_users d
        join sys.user$ u d.user_id = u.user#
    where lock_date is not null;
   user_rec get_users%rowtype;

BEGIN
    FOR user_rec in get_users loop
    BEGIN
       stmt := 'alter user "' || user_rec.username || '"' ||
               ' identified by values ''' || user_rec.password || '''' || 
               ' account unlock';
       execute immediate stmt;
     EXCEPTION WHEN others THEN
        dbms_output.put_line('Error unlocking '||user_rec.username);
        dbms_output.put_line(SQLERRM);
     END;
   END LOOP;
END;
/

答案 1 :(得分:1)

SQL生成这样的SQL有效,不知道它是否符合您的需求:

sqlplus -s user/pw@db
set heading off
set feedback off 
set pages 0
spool cmd.sql
select ...
spool off
@cmd.sql