2013-04-26 51 views
0

我想在Oracle中编写存储过程。我没有很多的经验,我遇到了一个问题。该过程的最终目标是从一个数据库获取数据并以不同的形式将数据放入另一个数据库。我似乎有大部分的程序工作,但我遇到的问题似乎应该很简单。在代码的开头,我想检查一下确保创建了一个数据库链接。如果没有,那么我想创建数据库链接。创建一个数据库链接,如果没有在存储过程中创建

这就是我把我的程序里面:

IF (select count(1) from ALL_DB_LINKS where db_link = 'DB_LINK.NAME.COM') = 0 THEN 
     CREATE DATABASE LINK LINK_NAME 
     CONNECT TO username IDENTIFIED BY password 
     USING 'SID'; 
END IF; 

我知道链接的作品,因为我已经做到了这外,做一个查找它。我收到的时候我尝试编译错误是这样的:

出现符号“CREATE”在需要下列之一时:

我已经做了所有的谷歌上搜索,我想我可以做的,我无法弄清楚我做错了什么。为了解决我有的其他问题,我也尝试了这样做:

DECLARE test_count number;

select count(1) into test_count from ALL_DB_LINKS where db_link = 'DB_LINK.NAME.COM'; 
BEGIN 
    IF test_count = 0 THEN 
     CREATE DATABASE LINK LINK_NAME 
     CONNECT TO username IDENTIFIED BY password 
     USING 'SID'; 
    END IF; 
END; 

但是我得到了同样的错误。我也不确定是否能够在开始阶段开始工作。任何帮助将是一个伟大的...好吧,帮助。

+1

您不能直接在Oracle中的过程中执行DDL。你可以通过使用'EXECUTE IMMEDIATE'来解决这个问题。 – 2013-04-26 20:25:57

+0

我想你还必须使用动态SQL来查询链接;我现在无法测试,但是我非常肯定,如果您从静态SQL中不存在的链接中进行选择,那么该过程将无法编译,并且如果随后被删除,将会失效。在运行时创建对象听起来像是你可能想要重新思考的东西...... – 2013-04-26 21:31:11

回答

2

Oracle编译软件包,并且为了确保代码中引用的所有对象都必须已经存在。这包括通过数据库链接引用的对象。如果引用的对象不存在,则事物将被标记为无效。通常,DBA将使用PL/SQL脚本创建和维护这样的环境,而不是存储过程。

如果你真的想反正:

EXECUTE IMMEDIATE q'[ CREATE DATABASE LINK LINK_NAME 
     CONNECT TO username IDENTIFIED BY password 
     USING 'SID']'; 
+0

是的,这就是我一直在寻找的东西。我明白,这不是最好的方式,但现在这是我需要做的,因为其他情况。谢谢您的帮助! – user940769 2013-04-29 12:41:01

0

如果你真的需要做到这一点,您可以创建使用动态SQL爱德吉布斯提出和Brian表明,只要链接已经存在的链接点创建过程:

create database link test_link 
connect to scott identified by oracle 
using 'ORCL'; 

Database link created. 

create or replace procedure p42 as 
    l_count number; 
    l_dummy dual.dummy%type; 
begin 
    select count(*) into l_count 
    from all_db_links 
    where db_link = 'TEST_LINK'; 

    if l_count = 0 then 
     execute immediate q'[ 
      create database link test_link 
      connect to scott identified by oracle 
      using 'ORCL' 
     ]'; 
    end if; 
    select dummy into l_dummy from [email protected]_link; 
    dbms_output.put_line('Value from remote database: ' || l_dummy); 
end; 
/

Procedure created. 

exec p42; 

Value from remote database: X 

PL/SQL procedure successfully completed. 

但如果该链接已经不程序将无法编译存在:

drop database link test_link; 

create or replace procedure p42 as 
... 
end; 
/

Warning: Procedure created with compilation errors. 

show errors 

Errors for PROCEDURE P42: 

LINE/COL ERROR 
-------- ----------------------------------------------------------------- 
16/5  PL/SQL: SQL Statement ignored 
16/5  PL/SQL: ORA-00942: table or view does not exist 

奇怪的是,如果您在链接存在的情况下创建过程,则不会反对,然后删除该链接;该程序保持有效,动态SQL工作重新链接,以及程序成功运行:

drop database link test_link; 

Database link dropped. 

select object_type, object_name, status from all_objects 
where object_type = 'PROCEDURE' and object_name = 'P42'; 

OBJECT_TYPE  OBJECT_NAME  STATUS 
--------------- --------------- --------------------- 
PROCEDURE  P42    VALID 

exec p42; 

Value from remote database: X 

PL/SQL procedure successfully completed. 

我本来期望下降的链接无效的程序,但显然不是,尽管它在all_dependencies出现。你不能重新编译,虽然这个过程:

drop database link test_link; 

Database link dropped. 

alter procedure p42 compile; 

Warning: Procedure altered with compilation errors. 

show errors 

Errors for PROCEDURE P42: 

LINE/COL ERROR 
-------- ----------------------------------------------------------------- 
16/5  PL/SQL: SQL Statement ignored 
16/5  PL/SQL: ORA-00942: table or view does not exist 

为了让您编译(或重新编译),而该链接不存在,你需要使用动态SQL以及参考链接:

drop database link test_link; 

drop database link test_link 
        * 
ERROR at line 1: 
ORA-02024: database link not found 

create or replace procedure p42 as 
    .... 
    execute immediate 'select dummy from [email protected]_link' into l_dummy; 
    dbms_output.put_line('Value from remote database: ' || l_dummy); 
end; 
/

Procedure created. 

exec p42; 

Value from remote database: X 

PL/SQL procedure successfully completed. 

drop database link test_link; 

Database link dropped. 

exec p42; 

Value from remote database: X 

PL/SQL procedure successfully completed. 

drop database link test_link; 

Database link dropped. 

alter procedure p42 compile; 

Procedure altered. 

exec p42; 

Value from remote database: X 

PL/SQL procedure successfully completed.