数据库从 PostgreSQL 迁移到 Oracle

Posted

技术标签:

【中文标题】数据库从 PostgreSQL 迁移到 Oracle【英文标题】:Database migration from PostgreSQL to Oracle 【发布时间】:2013-10-02 10:49:52 【问题描述】:

我正在将我的数据库服务器从 PostgreSQL 迁移到 Oracle 11g。我尝试了各种工具,例如Squirrel SQL。但是大多数迁移工具都支持表和视图的迁移。我找不到迁移我的过程和功能的解决方案。我可以迁移功能和程序的方式是什么。请找到以下功能之一。

CREATE OR REPLACE FUNCTION hrms.fngetstatus(iactdate character varying, ideactdate character varying)
  RETURNS character varying AS
$BODY$
   returnval   VARCHAR (1);
BEGIN
   IF     TO_DATE (iactdate, 'mm/dd/yyyy') >
                      TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
      AND TO_DATE (ideactdate, 'mm/dd/yyyy') >
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
   THEN
        returnval := 'D';
   ELSIF     TO_DATE (iactdate, 'mm/dd/yyyy') >
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
         AND TO_DATE (ideactdate, 'mm/dd/yyyy') IS NULL
   THEN

       returnval := 'D';
   ELSIF     TO_DATE (iactdate, 'mm/dd/yyyy') <=
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
         AND TO_DATE (ideactdate, 'mm/dd/yyyy') >
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
   THEN
        returnval := 'A';
   ELSIF     TO_DATE (iactdate, 'mm/dd/yyyy') <=
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
         AND TO_DATE (ideactdate, 'mm/dd/yyyy') IS NULL
   THEN
      returnval := 'A';
   ELSIF     TO_DATE (iactdate, 'mm/dd/yyyy') <
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
         AND TO_DATE (ideactdate, 'mm/dd/yyyy') <=
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
   THEN
      returnval := 'D';
   ELSIF     TO_DATE (iactdate, 'mm/dd/yyyy') =
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
         AND TO_DATE (ideactdate, 'mm/dd/yyyy') =
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
   THEN
      returnval := 'D';
        ELSIF     TO_DATE (ideactdate, 'mm/dd/yyyy') >=
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
         AND TO_DATE (iactdate, 'mm/dd/yyyy') is null                      
   THEN
      returnval := 'A';  
        ELSIF     TO_DATE (iactdate, 'mm/dd/yyyy') <=
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
         AND TO_DATE (ideactdate, 'mm/dd/yyyy') <
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')   
   THEN
      returnval := 'A';  
        ELSIF     TO_DATE (iactdate, 'mm/dd/yyyy') >
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
         AND TO_DATE (ideactdate, 'mm/dd/yyyy') <
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')   
   THEN
      returnval := 'D';   
          ELSIF     TO_DATE (iactdate, 'mm/dd/yyyy') >
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
         AND TO_DATE (ideactdate, 'mm/dd/yyyy') <=
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')   
   THEN
      returnval := 'D';    
   END IF;
   RETURN returnval;
END$BODY$
  LANGUAGE edbspl VOLATILE SECURITY DEFINER
  COST 100;
ALTER FUNCTION hrms.fngetstatus(character varying, character varying)
  OWNER TO enterprisedb;

【问题讨论】:

不同的数据库引擎做不同的事情。例如,oracle 没有您在许多其他数据库引擎中找到的两个常用日期函数(dateadd、datediff)。我认为唯一能做到这一点的方法就是手动完成,这样你就可以测试你所做的一切。 你能给我一份文档,我可以在其中阅读清单以在手动转换它们时牢记吗? 你为什么不把它们全部重写。 Oracle 支持来自 Postgress 的不同内置函数 @DanBracuk:您不需要 Oracle(或 Postgres)中笨拙的 dateadddateadd,因为它支持 ANSI SQL 日期算术,例如some_date + interval '1' week 或者更简单的 current_date + 1 表示“明天” 我粘贴的函数只是一个例子。我尝试直接在 oracle sql 控制台执行此操作,在控制台中出现很多错误。前任。 ORA-06550: line 7, column 24: PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following: * &amp; = - + ; &lt; / &gt; at in is mod remainder not rem &lt;an exponent (**)&gt; &lt;&gt; or != or ~= &gt;= &lt;= &lt;&gt; and or like like2 like4 likec between || multiset member submultiset 【参考方案1】:

您唯一需要更改的是“围绕”函数的代码。 Oracle 使用与 Postgres 不同的“标题”。

所以 PL/SQL 中的函数看起来像这样。我只更改了开头的 CREATE OR REPLACE 和最后的 END 之后的部分。

CREATE OR REPLACE FUNCTION fngetstatus(iactdate varchar, ideactdate varchar)
  RETURN varchar 
AS
   returnval   VARCHAR (1);
BEGIN
   IF     TO_DATE (iactdate, 'mm/dd/yyyy') >
                      TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
      AND TO_DATE (ideactdate, 'mm/dd/yyyy') >
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
   THEN
        returnval := 'D';
   ELSIF     TO_DATE (iactdate, 'mm/dd/yyyy') >
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
         AND TO_DATE (ideactdate, 'mm/dd/yyyy') IS NULL
   THEN

       returnval := 'D';
   ELSIF     TO_DATE (iactdate, 'mm/dd/yyyy') <=
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
         AND TO_DATE (ideactdate, 'mm/dd/yyyy') >
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
   THEN
        returnval := 'A';
   ELSIF     TO_DATE (iactdate, 'mm/dd/yyyy') <=
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
         AND TO_DATE (ideactdate, 'mm/dd/yyyy') IS NULL
   THEN
      returnval := 'A';
   ELSIF     TO_DATE (iactdate, 'mm/dd/yyyy') <
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
         AND TO_DATE (ideactdate, 'mm/dd/yyyy') <=
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
   THEN
      returnval := 'D';
   ELSIF     TO_DATE (iactdate, 'mm/dd/yyyy') =
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
         AND TO_DATE (ideactdate, 'mm/dd/yyyy') =
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
   THEN
      returnval := 'D';
        ELSIF     TO_DATE (ideactdate, 'mm/dd/yyyy') >=
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
         AND TO_DATE (iactdate, 'mm/dd/yyyy') is null                      
   THEN
      returnval := 'A';  
        ELSIF     TO_DATE (iactdate, 'mm/dd/yyyy') <=
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
         AND TO_DATE (ideactdate, 'mm/dd/yyyy') <
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')   
   THEN
      returnval := 'A';  
        ELSIF     TO_DATE (iactdate, 'mm/dd/yyyy') >
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
         AND TO_DATE (ideactdate, 'mm/dd/yyyy') <
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')   
   THEN
      returnval := 'D';   
          ELSIF     TO_DATE (iactdate, 'mm/dd/yyyy') >
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')
         AND TO_DATE (ideactdate, 'mm/dd/yyyy') <=
                       TO_DATE (TO_CHAR (SYSDATE, 'mm/dd/yyyy'), 'mm/dd/yyyy')   
   THEN
      returnval := 'D';    
   END IF;
   RETURN returnval;
END;
/

这是一个 SQLFiddle 示例:http://sqlfiddle.com/#!4/94990/2

【讨论】:

我尝试执行您更新的查询。收到以下错误ORA-06550: line 7, column 24: PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following: * &amp; = - + ; &lt; / &gt; at in is mod remainder not rem &lt;an exponent (**)&gt; &lt;&gt; or != or ~= &gt;= &lt;= &lt;&gt; and or like like2 like4 likec between || multiset member submultiset @Jeyasithar 那么你并没有告诉我们一切。请参阅我的 SQLFiddle 它确实 工作。 Squirrel 是否支持 PL/SQL 定义的 / 终止符? 我在 Eclipse 中使用数据源浏览器插件来执行查询。 @Jeyasithar:对不起,我不使用 Eclipse,所以我无法对此发表评论。但显然它不支持创建 PL/SQL 过程。您应该尝试使用 SQL Developer、SQL*Plus 或任何其他可以使用备用分隔符的工具(因为这就是您所需要的 - 很可能 Eclipse 将所有内容发送到第一个 ;,因为它无法识别 /)跨度>

以上是关于数据库从 PostgreSQL 迁移到 Oracle的主要内容,如果未能解决你的问题,请参考以下文章

从 mysql 迁移到 postgresql 时,Laravel 雄辩的 ORM 不起作用

从 MySQL 迁移到 PostgreSQL [关闭]

RowVersion字段从SqlServer到PostgreSQL的迁移

如何从SQLServer 迁移数据 到PostgreSQL

从 MySQL 迁移到 PostgreSQL 后类似查询的 SQL 性能问题

从 MSSQL 迁移到 postgresql 或 mysql [关闭]