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で 。

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 に答える