将MySQL存储过程移植到Oracle

时间:2011-10-25 22:15:16

标签: mysql oracle stored-procedures plsql

我正在尝试将存储过程从MySQL移植到Oracle,我遇到了很多麻烦。我已经阅读了Oracle文档,而且我在执行非常基本的操作时遇到了麻烦,比如正确地声明变量。我希望有人能告诉我如何正确地声明和设置变量。

我的存储过程用于向两个不同的表添加值,并确保正确映射它并且不会违反外键。

这是我的MySQL代码:

 CREATE DEFINER=root@% PROCEDURE proc_add_entry(IN theName vARCHAR(50), IN theKey VARCHAR(50), IN theOtherData VARCHAR(50), IN theOtherData2 INT, IN theStartDate DATE, IN theEndDate DaTE, IN theReferenceDate DaTE)
     LANGUAGE SQL
     NOT DETERMINISTIC
     CONTAINS SQL
     SQL SECURITY DEFINER
 BEGIN
 declare theNameID int ;
 declare theKeyID int ;
 declare theOtherDataID int default null;
 declare error bool default false;
 declare continue handler for SQLEXCEPTION
    set error = true;

    set theKeyID = (select KeyID from map_alias ma where ma.alias = trim(theKey));
    set theOtherDataID = (select theOtherDataID from map_otherdata mc where mc.otherdata = trim(theOtherData));

    set theNameID = (select max(nameID) from inserttable);
    set theNameID = theNameID + 1;
    insert into inserttable values (theNameID , theKeyID , theOtherDataID , theOtherData2, theStartDate , 
    theEndDate , theReferenceDate);

    if error = true then
        insert into errors_inserttable values (theNameID , theKeyID , theOtherDataID , theOtherData2, theStartDate , 
    theEndDate , theReferenceDate);
    end if;

    set error = false;
    insert into map_inserttable (theNameID , datasourceid, theName) values (theNameID , 1, theName);
    if error = true then
        insert into errors_map_inserttable  (theNameID , datasourceid, theName) values (theNameID , 1, theName);
    end if;

 END

在Oracle中,我的上一个语句被忽略(ORA-00922:缺少或无效选项)。它应该是一个局部变量,所以我不确定为什么我会得到那个特定的错误。

我也在努力宣布继续处理程序。我收到了错误:

 Error(16,27): PLS-00103: Encountered the symbol "FOR" when expecting one of the following:     := . ( @ % ; not null range default character.

到目前为止,这是我的oracle代码:

 CREATE OR REPLACE PROCEDURE PROC_ADD_ENTRY
 (
   THENAME IN VARCHAR2  
 , THEKEY IN VARCHAR2  
 , THEOTHERDATA IN VARCHAR2  
 , THEOTHERDATA2 IN NUMBER  
 , THEFIRSTDATE IN DATE  
 , THELASTDATE IN DATE  
 , THEREFERENCEDATE IN DATE  
 ) AS
  THENAMEID INT;
  THEKEYID INT;
  THEOTHERDATAID int;
  ERROR bool default false;
 BEGIN
 declare continue HANDLER FOR SQLEXCEPTION set error = true;



   set THEKEYID = (select KEYID from map_INSERTTABLE mc where mc.Key = trim(THEKEY));
 END PROC_ADD_ENTRY;

我确信对于使用oracle的人来说,这是非常简单的,但是我正在阅读文档,我看到有关在何处以及如何声明变量,继续处理程序以及为变量赋值的相互矛盾的信息。 (它是:=或=分配值?我在begin语句之后使用单词declare来声明变量,还是按照我在下面显示的方式进行操作?)

如果有人可以告诉我:

a)在哪里声明一个局部变量

b)如何为其赋值(即1到int)

c)如何将DB中的值赋给变量(set var = select table from number_number tn,其中tn.number = 1)

d)如何正确声明一个继续处理程序

我真的很感激。

1 个答案:

答案 0 :(得分:3)

你的基本结构很好。

create or replace procedure <name> (<param list>) as
  <local variables>
begin
  <body>
end <name>;

解决您的具体问题:

  

a)在哪里声明一个局部变量

我在上面标记了这一部分。

  

b)如何为其赋值(即1到int)

您可以使用:=进行分配。

例如。 thenameid := 1;

您想要的数据类型通常与sql数据类型匹配(例如,上面的NUMBER),尽管有特定于PL / SQL的数据类型,例如PLS_INTEGER。请参阅PL/SQL data types documentation for more details

  

c)如何将DB中的值赋给变量(set var = select table from number_number tn,其中tn.number = 1)

您可以使用into关键字和本地定义的变量来存储值。例如。

l_num_rows number;
select count(*) into l_num_rows from user_objects;
  

d)如何正确声明一个继续处理程序

如果我正在阅读正确理解您的代码,那么每次sql语句出现问题时都希望执行set error = true,然后您希望继续存储过程。

Exception handling就是你所追求的。您可以在这样的异常块中包装您认为可能有错误的任何或SQL PL / SQL语句,并根据需要包含尽可能多的异常情况(例如,NO_DATA_FOUND):

begin
  <statements that may fail>
exception when <exception name> then
  <action>
...
exception when others then
  <action>
end;

“其他”是捕获。您可以处理此案例,但与任何错误处理一样,最好先捕获特定案例。


为了完成,这里大致是你的示例程序的样子。我已删除错误代码标记,因为它不需要,并且还将int更改为number s:

create or replace procedure proc_add_entry (
  in thename varchar(50),
  in thekey varchar(50),
  in theotherdata varchar(50),
  in theotherdata2 number,
  in thestartdate date,
  in theenddate date,
  in thereferencedate date
) as
  thenameid number;
  thekeyid number;
  theotherdataid number default null;
begin
  begin
    select keyid into thekeyid from map_alias ma where ma.alias = trim(thekey);

    select theotherdataid into theotherdataid from map_otherdata mc where mc.otherdata = trim(theotherdata);

    select max(nameid) into thenameid from inserttable;
    thenameid := thenameid + 1;

    insert into inserttable values (thenameid, thekeyid, theotherdataid, theotherdata2, thestartdate, theenddate, thereferencedate);
  exception when others then
    insert into errors_inserttable values (thenameid, thekeyid, theotherdataid, theotherdata2, thestartdate, theenddate, thereferencedate);
  end;

  begin
    insert into map_inserttable (thenameid, datasourceid, thename) values (thenameid, 1, thename);
  exception when others then
    insert into errors_map_inserttable (thenameid, datasourceid, thename) values (thenameid, 1, thename);
  end;

end proc_add_entry;