0

我想通过数据库链接通过另一个数据库上的过程创建用户。执行过程时出现错误。这是我使用的代码。

create or REPLACE PROCEDURE hostname   
(host_name in varchar2,user_name in VARCHAR2, pass_word in VARCHAR2,    
table_space in varchar2,pro_file in varchar2)    
as    
db_link_name varchar2(30);    
begin    
select db_link into db_link_name from all_db_links where host=host_name;    
EXECUTE IMMEDIATE 'dbms_utility.exec_ddl_statement@'||db_link_name||('CREATE     USER '||user_name||' IDENTIFIED BY '||pass_word||'     
DEFAULT TABLESPACE '||table_space||' PROFILE '|| pro_file||' ACCOUNT UNLOCK');    
EXECUTE IMMEDIATE 'dbms_utility.exec_ddl_statement@'||db_link_name||    
('GRANT CONNECT,RESOURCE,EXECUTE_CATALOG_ROLE,Create table,create session,create     view,create sequence,create procedure,create job,create synonym TO '||user_name);    
end;    
/    
execute hostname('orcl1','rahul1','rahul','users','default');    

错误:ORA-00900:无效的 SQL 语句 ORA-06512:在“SYS.HOSTNAME”,第 6 行 ORA-06512:在第 1 行
00900。00000 -“无效的 SQL 语句”
*原因:
*操作:

4

1 回答 1

3

我想您可能对评论者 mustaccio 提供的一些建议感到有些困惑。他的意思是,您的EXECUTE IMMEDIATE语句中的 SQL 字符串需要使用 PL/SQL 块才能调用存储过程。

换句话说,而不是写

EXECUTE IMMEDIATE 'dbms_utility.exec_ddl_statement ... ';

你应该写

EXECUTE IMMEDIATE 'BEGIN dbms_utility.exec_ddl_statement ... ; END;';

对于您的过程,我建议您为要传递给的字符串引入一个局部变量EXECUTE IMMEDIATE。众所周知,要正确处理这些是非常棘手的,如果您已将它们分配给局部变量,则可以使用dbms_output.put_line. 事实上,我在解决您的程序中的问题时正是这样做的。如果您希望修改或扩展您的程序,我建议您继续这样做。

无论如何,这就是我最终得到的结果,它似乎有效:

create or REPLACE PROCEDURE hostname   
  (host_name in varchar2,user_name in VARCHAR2, pass_word in VARCHAR2,    
  table_space in varchar2,pro_file in varchar2)    
as    
  db_link_name      varchar2(30);
  l_ddl_sql         varchar2(4000);
begin    
  select db_link into db_link_name from all_db_links where host=host_name; 
  l_ddl_sql := 'begin dbms_utility.exec_ddl_statement@'||db_link_name||'(''CREATE     USER '||user_name||' IDENTIFIED BY '||pass_word||'     
    DEFAULT TABLESPACE '||table_space||' PROFILE '|| pro_file||' ACCOUNT UNLOCK''); END;';

  EXECUTE IMMEDIATE l_ddl_sql;

  l_ddl_sql := 'begin dbms_utility.exec_ddl_statement@'||db_link_name||    
    '(''GRANT CONNECT,RESOURCE,EXECUTE_CATALOG_ROLE,Create table,create session,create     view,create sequence,create procedure,create job,create synonym TO '||user_name || '''); END;';

  EXECUTE IMMEDIATE l_ddl_sql;
end;
/
于 2015-01-17T15:06:48.147 回答