有关从Oracle迁移到PostgreSQL的问题

首先

这是2019年PostgreSQL Advent Calendar的第八天的文章。
这篇文章是我自己在从Oracle迁移到PostgreSQL过程中所调查的内容。

去年开始准备了服务器替换工作(从Windows Server 2008R2 + Oracle 11g 到 Windows Server 2016 + PostgreSQL 9.6),从今年9月开始逐步展开。
最初考虑的是使用 Oracle 12c,但问题主要出在许可费用上(2016年发生了 Oracle Database 许可费的大幅改动)。由于我们有25个地点,成本非常高昂。因此为了降低成本,我们决定转向使用PostgreSQL。

不使用EDB Postgres(与Oracle兼容的高版本PostgreSQL),而是仔细筛选了大约20个现有应用程序的SQL,并从Oracle迁移至PostgreSQL。

PostgreSQL的概述

这个词的发音是“Postgres QL”。它是Ingres的下一版本(Post)并被命名为Postgres。QL是Query Language的缩写。

PostgreSQL采用了追加型架构。即使数据有变化,也不会直接物理删除原始记录,而是添加新行并将原始记录标记为无效。要将未使用的空间重新利用,需要使用VACUUM命令。

将来,EnterpriseDB希望放弃增量式架构,并实施像其他数据库一样拥有UNDO日志的开发中的“zHeap”技术。作为一个数据库,作为一个开放源代码项目,作为一个社区 – 石井達夫先生谈到了PostgreSQL的优势和挑战。

【2021/08/03补充】根据“zheap的现状”,由于zheap的主要开发者Amit离开了EDB,可惜地,“zheap”目前陷入停滞。

支持结束日期 (EOL = 结束生命周期)

バージョン初期リリース日サポート終了期限152022年10月13日2027年11月11日142021年09月30日2026年11月12日132020年09月24日2025年11月13日122019年10月03日2024年11月14日112018年10月18日2023年11月09日102017年10月05日2022年11月10日9.62016年09月29日2021年11月11日

【2021/06/25附注】
由于 PostgreSQL 9.6 的支持期限即将到期,我们计划将其升级到某N公司最新支持的 PostgreSQL 12。
【2021/08/02附注】
已撰写一篇关于升级到 PostgreSQL 12 的文章。

 

更改名称

【2021/08/02更新】
在PostgreSQL 10中,有一些目录名称和函数名称等发生了更改。

    • ログファイル出力先のディレクトリ名がpg_logからlogへ変更

 

    • WALに関連するディレクトリ/関数/コマンドなどでxlogがwal、locationがlsnに変更

 

    コミットログの出力先ディレクトリ名がpg_clogからpg_xactへ変更
PostgreSQL 9.6以前の名称PostgreSQL 10以降の名称pg_loglogpg_xlogpg_walpg_clogpg_xactpg_current_xlog_locationpg_current_wal_lsnpg_xlogdumppg_waldumppg_receivexlogpg_receivewal

环境

    • Windows Server 2016

 

    • PostgreSQL 9.6

 

    • .NETライブラリ「Npgsql」

 

    psqlodbc ODBCドライバー(UNICODE版)

由于在准备开始时,PostgreSQL 9.6是在还未发布PostgreSQL 10.0之前的版本。
现在已经发布了 PostgreSQL 12(2019/10/3)和 PostgreSQL 13(2020/09/24)。

连接驱动程序已更改为.NET的应用程序使用”Npgsql”,而Classic ASP应用程序(32位)使用psqlodbc(Unicode版本)。

在管理工具的”ODBC数据源管理员(32位)”中注册并使用”PostgreSQL35W PostgreSQL Unicode”作为系统DNS。
由于PostgreSQL OLDDB驱动程序慢且无法正确获取PostgreSQL的numeric类型字段值等问题,因此使用ODBC驱动程序。
不建议使用PostgreSQL的OLEDB连接。

Session("ConnectionString") = "DSN=PostgreSQL35W;Server=localhost;Database=db_test;UID=fuga;PWD=hoge;Port=5432;"

建立

他需要对主机进行设置更改以进行连接。

listen_addresses = '*'		# what IP address(es) to listen on;
port = 5432			# (change requires restart)

※更改后,重新启动PostgreSQL服务。

取消评论。将”localhost”更改为”*”。如果不这样做,只能连接到本地主机。
为了从其他主机连接,需要进行以下设置。

设定可以连接的客户端

在pg_hda.conf中添加配置。

允许来自所有客户端电脑的连接。

# IPv4 local connections:
host all all 0.0.0.0/0 md5

限制來自客戶端計算機的連接。

# IPv4 local connections:
host all all 192.168.64.0/24 md5

※認証方式 trust: 可以使用任意角色名无需密码连接,md5: 使用密码认证
※更改后,不需要重新启动PostgreSQL服务

地區

lc_collate和lc_ctype的默认设置是“C”,而lc_messages、lc_monetary、lc_numeric和lc_time将在此次运行中统一设定为“C”。
* 不利的一面是,输出到pg_log的日志消息将不会是日语,而是英语。

按照相同的顺序对照片进行匹配。

如果不设置排序顺序,很容易被忽视,别人会说排序不对。

{A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z}
 
文字コード順
は(清音)
ば(濁音)
ぱ(半濁音)
ハ(清音)
バ(濁音)
パ(半濁音)
{a,A,A,b,B,B,c,C,C,d,D,D,e,E,E,f,F,F,g,G,G,h,H,H,i,I,I,j,J,J,k,K,K,l,L,L,m,M,M,n,N,N,o,O,O,p,P,P,q,Q,Q,r,R,R,s,S,S,t,T,T,u,U,U,v,V,V,w,W,W,x,X,X,y,Y,Y,z,Z,Z}
 
アイウエオ一つずつ「カタカナ → ひらがな」の順に並びます。
ハ(清音)
は(清音)
バ(濁音)
ば(濁音)
パ(半濁音)
ぱ(半濁音)

更改日志输出设置

将logging_collector从”off”更改为”on”,并将日志输出到pg_log文件夹。
应该设置三个与日志相关的参数以应对故障。

logging_collector = on		# Enable capturing of stderr and csvlog
log_line_prefix='[%t] %u %d %p[%l] '	# special values:

※改动后,请重新启动PostgreSQL服务。

[2019-04-25 14:37:08 JST]  7496[1] LOG:  database system was shut down at 2019-04-25 14:37:06 JST
[2019-04-25 14:37:08 JST]  7496[2] LOG:  MultiXact member wraparound protections are now enabled
[2019-04-25 14:37:08 JST]  6592[3] LOG:  database system is ready to accept connections
[2019-04-25 14:37:08 JST]  3240[1] LOG:  autovacuum launcher started

【2020/04/03补充】
当发生错误时,知道客户端IP和应用程序会更容易追踪到错误的原因。
%r:输出客户端IP地址
%a:输出应用程序,例如psql pgAdmin III,大部分是未知[unknown]的。

log_line_prefix='[%t] %u %d %p[%l] %r %a '	# special values:
[2020-03-30 17:42:57 JST] hoge test 5912[1] 127.0.0.1(65080) psql ERROR:  duplicate key value violates unique constraint "pk_sno"
[2020-03-31 10:26:21 JST] hoge test 4172[1] 10.20.30.1(54228) pgAdmin III- ?????????????????? ERROR:  syntax error at or near "elect" at character 1
[2020-03-31 16:21:20 JST] hoge test 7424[1] 192.168.0.105(49160) [unknown] LOG:  could not receive data from client: An existing connection was forcibly closed by the remote host.

由于使客户端IP可见,我们能够确定连接被终止的IP地址是本地(127.0.0.1),而不是远程地址。这样我们就能找出问题的原因了。原来,服务器监控软件在300秒超时后会强制断开连接。

省略输入psql密码

要在没有输入密码的情况下执行psql,需要在下面的文件夹中的”pgpass.conf”中设置密码。
%APPDATA%\postgresql\pgpass.conf

localhost:5432:*:postgres:(パスワード)

作为另一种选择,虽然在安全性上不推荐,但可以在批处理文件中设置环境变量(PGPASSWORD)然后运行。

SET PGPASSWORD=(パスワード)
psql -U (ユーザー) -f xxxxx.sql 

更改的数据类型,函数

数据类型

在创建表时需要更改的数据类型如下所示。※仅代表个人观点。

Oracleのデータ型PostgreSQL説明備考VARCHAR2(n)CHARACTER VARYING(n)最大n文字の長さの文字列Oracleはバイト数だがPostgreSQLは文字数となるNUMBERNUMERIC最大1000桁、ユーザ指定精度
DATETIMESTAMPDATEのままだと日付のみになる
SYSDATEcurrent_timestamp
※SQL92に従いnow()は使わない現在の日付/時刻を取得する関数HH24MMSS → HH24MISSROWIDoid32bit(約43億)で一周してしまうCreate文でWITH OIDSと設定しないと使用できない。PostgreSQL12以降はWITH OIDS廃止

请使用以下参照进行Oracle_fdw的数据类型映射。

请留意

Oracle中的VARCHAR2是以字节计算的,而PostgreSQL中的CHARACTER VARYING是以字符计算的。
将Oracle的NUMBER类型直接转换为PostgreSQL的NUMERIC类型存在一些弊端。
如果只能存放整数,可能更好的选择是直接使用smallint类型或integer类型。

在.NET应用程序中,由于类型转换错误导致需要修复程序。
在Oracle中,Number类型仅限整数,因此之前使用(int)进行类型转换,但在PostgreSQL中,NUMERIC类型将转换为Decimal类型,如果在使用DataRow时使用(int)进行类型转换,将会发生类型转换错误。因此,我进行了修正,使用Convert.ToInt32进行类型转换。
参考:当从DataRow中提取值时,无法将其转换为decimal类型。

函数

在创建表时需要更改的函数如下所示。

Oracle演算子PostgreSQLの演算子説明NVL(文字列,変換文字列)COALESCE(文字列,変換文字列)文字列がNULLの場合は、変換文字列を返す、NULLでなければ文字列を返す。INSTR(文字列,検索文字列)POSITION(検索文字列,IN 文字列)文字列から検索文字列で始まる位置を返す。DECODE(expr, cmp_expr1, ret_expr1, cmp_expr2, ret_expr2, default_expr)CASE expr
WHEN cmp_expr1 THEN ret_expr1
WHEN cmp_expr2 THEN ret_expr2
ELSE default_expr ENDexprがcmp_expr1と同値ならret_expr1を返す、cmp_expr2と同値ならret_expr2を返す、それ以外ならdefault_exprを返す。SELECT t1.key1, t1.name1, t2.name2 FROM table t1, table t2 WHERE t1.key1 = t2.key2(+)SELECT t1.key1, t1.name1, t2.name2 FROM table t1 LEFT OUTER JOIN table t2 ON t1.key1 = t2.keyt1の列key1にしか存在しないデータを検索

有关SUBSTR的内容

当第2参数的起始索引为”0″时,在Oracle中与起始索引”1″相同,但在PostgreSQL中会删除前1个字符。
※可以将第2参数的起始索引视为从”1″开始。
[数据库比较]子字符串获取SUBSTR的陷阱

-- Oracle
SELECT SUBSTR('ABCDE',0,3) FROM DUAL -> 'ABC'
-- PostgreSQL
SELECT SUBSTR('ABCDE',0,3) -> 'AB'

如果第二个参数是负数(表示要从右边获取),需要注意。如果想从右边获取,可以使用RIGHT函数。

-- Oracle
SELECT SUBSTR('123456', -4, 4) FROM DUAL -> '3456'
-- PostgreSQL
SELECT SUBSTR('123456',-4, 4) -> null
SELECT RIGHT('123456', 4) -> '3456'

文字串連

当在SELECT语句中连接包含null字符串的列时,整个结果将变为null。
为了避免这种情况,可以为每列指定替代null的字符串。
[PostgreSQL] PostgreSQL中在SELECT语句中连接Null字符串的方法是什么?

SELECT ok_column || '-' || coalesce((null_column, '') FROM foo;

规格

仕様差比功能差更为棘手。

PostgreSQL 企业联盟技术部门第2工作组
从不同种类的 DBMS 迁移到 PostgreSQL 的数据迁移和字符编码转换
链接:https://www.pgecons.org/wp-content/uploads/PGECons/2013/WG2/05_DataMigrationResearch_ConvertCharacterCode.pdf

    • SQLの観点から「Oracle Database」「PostgreSQL」「MySQL」の特徴を整理しよう!

 

    OracleからPostgreSQLに乗り換えたい人に送る何か

对于NULL和空字符串的处理

在Oracle中,NULL和空字符串被视为相同的,但在PostgreSQL中则被区分为两个不同的对象。

除法运算会产生误差。

如果SQL内部实现了包含除法运算的计算,答案将不一致。这不是一个错误,而是一种规范。

要么允许误差,要么如果不能容忍误差的话,应该在SQL中只存储计算结果而不进行计算。

OraclePostgreSQL1÷3×3=11÷3×3=0.999…1/3+1/3+1/3=11/3+1/3+1/3=0.999…

交易结果不同

当使用多个事务时,事务的并发执行结果将会不同。

    • PostgreSQLとOracle Databaseのアーキテクチャ構造

 

    日経SYSTEMS 2019/7 特集2 Oracle DB コスト削減大作戦

SQL语句迁移

在中文中,可以这样表达:
表名和列名的大小写区分

没有引号的标识符始终被解释为小写,但通过用引号括起来,可以区分大小写。例如,标识符FOO、foo和”foo”在PostgreSQL中被视为相同,但”Foo”和”FOO”被视为不同的标识符(因为PostgreSQL将没有引号的标识符解释为小写,并不与标准SQL兼容。根据标准SQL,没有引号的标识符应该被解释为大写。因此,根据标准SQL,foo应该与”FOO”相同,与”foo”不同。如果想写一个可移植的应用程序,建议将特定的标识符统一地用引号括起来,或者完全不用引号括起来)。

如果查询条件中使用了表名或列名,由于PostgreSQL将其转换为英文小写,因此需要将英文大写字母转换为小写字母。

文字型的数值比较会出现错误。

在PostgreSQL的情况下,如果在Numeric类型后面加上单引号来指定,会导致错误。
修正示例:KBN=1 → KBN=’1′

在PostgreSQL中,如果没有给1位字符型的varchar类型加上单引号进行指定,就会出现错误。
修正例:KBN=’1′ → KBN=1

文稿格式

在 PostgreSQL 中,to_char/to_number 函数需要指定第2个参数,如果省略则会出错。
迁移到 PostgreSQL

在PostgreSQL中,使用to_char函数会在字符串的开头添加一个半角空格。
通过在to_char函数的第二个参数中添加FM前缀,可以取消自动添加的半角空格。

-- Oracle
SELECT TO_CHAR(10, '00000') FROM DUAL -> '00010'
-- PostgreSQL 先頭の半角スペースが入る
SELECT to_char(10, '00000') -> ' 00010'
-- PostgreSQL
SELECT to_char(10, 'FM00000') -> '00010'

PostgreSQL的數字字串轉換

添加DUAL表

Oracle有一个DUAL表,但是PostgreSQL没有。
在PostgreSQL中不需要写FROM。
DUAL表在Oracle中的语源是什么?

-- Oracle
SELECT '' FROM DUAL
-- PostgreSQL
SELECT ''

通过创建DUAL表,以便在迁移操作中不会遇到困难,使其与Oracle表现相同。

CREATE TABLE DUAL (
    DUMMY CHARACTER VARYING(1) DEFAULT '1' NOT NULL
)
WITH (
    OIDS=FALSE
);
	
-- OWNER設定
ALTER TABLE DUAL
    OWNER TO postgres;

【2021/09/08追加】
与其创建表格,将其作为视图更为常见。
PostgreSQL与Oracle之间的数据库互迁手册 – ThinkIT

CREATE VIEW dual AS
  SELECT 'X' AS DUMMY;

指定结果集中的行号

OraclePostgreSQLROWNUMOFFSETLINE BETWEENOFFSET + LIMIT
-- Oracle
SELECT * FROM 商品マスタ
WHERE 卸単価 IS NOT NULL
AND ROWNUM <= 5
ORDER BY 卸単価 DESC;

-- PostgreSQL
SELECT * FROM 商品マスタ
WHERE 卸単価 IS NOT NULL
ORDER BY 卸単価 DESC
LIMIT 5 OFFSET 0;

外部连接(Outer Join)语法

OraclePostgreSQLWHERE 表1.列A(+) = 表2.列AFROM 表1 RIGHT OUTER JOIN 表2 ON (表1.列A = 表2.列A)WHERE 表1.列A = 表2.列A(+)FROM 表1 LEFT OUTER JOIN 表2 ON (表1.列A = 表2.列A)

次の言葉を中国語で自然な表現に言い換えると、一つのオプションがあります:

副问题查询

在Scala子查询的情况下,Oracle和PostgreSQL的语法不会有变化。但是,在使用FROM子句或WHERE子句时,PostgreSQL需要使用别名。

标量子查询

没有区别

SELECT 商品名 FROM 商品マスタ
WHERE 卸単価 = (SELECT MAX(卸単価) FROM 商品マスタ);

在从句中进行副问句的查询方式。

如果在PostgreSQL中没有为子查询添加别名(例如T),则会出现错误。

-- Oracle
SELECT 担当者名
FROM (SELECT *
      FROM 担当者マスタ
      WHERE 生年月日< '1970-1-1')
WHERE MGR_ID IS NOT NULL;

-- PostgreSQL
SELECT 担当者名
FROM (SELECT *
      FROM 担当者マスタ
      WHERE 生年月日< '1970-1-1') T
WHERE MGR_ID IS NOT NULL;

在DELETE语句的FROM子句中不能使用JOIN

将句子”USING”改为”使用”或”利用”句子,将”IN”改为”在”句子。

 

合并文档支持(PostgreSQL 15及更高版本)。

PostgreSQL 15现已支持MERGE语句。

    • PostgreSQL15 検証レポート – pdf

 

    PostgreSQL 15にMERGE文UPSERTがやってくる

集合演算 (jí hé 的意思是对集合元素进行操作和计算的一种数学过程。

在UNION和INTERSECT语句中没有任何更改。然而,在Oracle中的MINUS子句在PostgreSQL中被改为EXCEPT子句。
※由于在性能验证时EXCEPT子句较慢,因此我们经常将其改写为NOT EXISTS。这并不仅仅是简单的转换。

-- Oracle
SELECT 担当者ID, 担当者名
FROM 担当者マスタ
MINUS
SELECT 支店担当者ID, 支店担当者名
FROM 支店担当者マスタ
ORDER BY 1;

-- PostgreSQL
SELECT 担当者ID, 担当者名
FROM 担当者マスタ
EXCEPT
SELECT 支店担当者ID, 支店担当者名
FROM 支店担当者マスタ
ORDER BY 1;

複合索引的指定方式

进行性能验证时,其中一个原因是它很慢。

对于包含从索引定义的第一列开始的任意数量连续向右的列的查询,可以使用多列索引。
11.3. 多列索引。

由于复合索引只在连续指定的列中有效,所以如果从索引定义的中间列开始指定条件,索引将失效并变慢。

WHERE AC = xxx AND AD = xxx
      
WHERE AA = xxx AND AB = xxx AND AC = xxx AND AD = xxx

与Oracle的不同

对于Oracle来说,自从Oracle 9i开始,即使索引中的第一列不包含在提取条件中,也可以通过跳过第一列来使用复合索引的INDEX (SKIP SCAN)功能。然而,由于PostgreSQL目前还没有这个功能,所以必须始终使用索引,就必须确保提供了第一个键。

考虑一个表格的列(C1、C2、C3)现在正在使用复合索引来进行排序。这个复合索引是根据C1、C2和C3的顺序进行排列的。复合索引是指定构成列中的哪一列来选择候选项。

C1C2C3Oracle
複合インデックス利用可不可PostgreSQL
複合インデックス利用可不可○○○可可○○×可可○××可可○×○可 ※C1のみ、C3は無視可 ※C1のみ、C3は無視×○○可 ※索引スキップ・スキャン可 ※table scanが選択される可能性高い×○×可 ※索引スキップ・スキャン可 ※table scanが選択される可能性高い××○可 ※索引スキップ・スキャン可 ※table scanが選択される可能性高い×××不可不可

使用bloom索引

当主键有多个时,索引默认使用b-tree索引,但弱点是当首个键不匹配时,索引将无法被使用。如果遇到这种情况,可以通过使用布隆过滤器索引,即使首个键条件不匹配,索引仍然可以被使用。

 

无法创建连接的索引

在PostgreSQL中,当使用双竖线连接列时,索引将失效。
在Oracle中,可以创建双竖线连接的索引本身,但在PostgreSQL中不可以。
在PostgreSQL中,可以通过创建单个或复合索引,并使用行值表达式来使索引生效。
不能将日期和时间分开进行比较。

SELECT * FROM TEST
WHERE 
(UPDATE_DATE, UPDATE_TIME) >  ('20190218','141435') AND
(UPDATE_DATE, UPDATE_TIME) <= ('20190219','141435')

尽管Oracle的行值表达式只支持等于(=,!=,IN)运算符,但PostgreSQL还支持范围条件(>,<=等)。需要注意的是,SQLServer至今仍不支持行值表达式。

用户定义函数 hù shù)

NVL函数

移植Oracle的NVL函数到Postgres的Coalesce函数失败了。

-- 型違いの複数登録が必要
CREATE OR REPLACE FUNCTION nvl(expr1 text, expr2 text)
    RETURNS text AS
$BODY$
    SELECT coalesce($1, $2);
$BODY$
    LANGUAGE sql;
    
CREATE OR REPLACE FUNCTION nvl(expr1 date, expr2 date)
    RETURNS date AS
$BODY$
    SELECT coalesce($1, $2);
$BODY$
    LANGUAGE sql;

CREATE OR REPLACE FUNCTION nvl(expr1 numeric, expr2 integer)
    RETURNS numeric AS
$BODY$
    SELECT coalesce($1, $2);
$BODY$
    LANGUAGE sql;  

日期计算、时间计算

在PostgreSQL中,由于没有提供ADD_MONTHS等日期计算和时间计算函数,所以最好是使用用户自定义函数来创建所需功能。

在使用PostgreSQL进行日期计算和时间计算时,可以使用interval类型,例如’1 month’等等。

CREATE FUNCTION add_months(in timestamptz, in int4)
    RETURNS timestamptz AS
$BODY$
    SELECT $1 + $2 * interval '1 month'
$BODY$
    LANGUAGE 'sql'

动态查询

以「EXECUTE sql;」的方式执行动态查询。并以「RETURN QUERY」的方式返回表格。
PostgreSQL备注- 存储过程

CREATE FUNCTION func_FugaTable(key text)
RETURNS TABLE(col1 text, col2 text) AS $$
DECLARE
    sql TEXT;
BEGIN
    sql := 'SELECT id::text, name::text FROM t_Fuga WHERE id = ''' || key || '''';
    RETURN QUERY EXECUTE sql;
END;
$$ LANGUAGE plpgsql;

三角函数

    • Oracleではトリガー単体ですんだが、PostgreSQLではトリガーとトリガー専用関数のセットとなっている。

 

    • Oracle は IN、OUT、INOUT というパラメータを関数に渡すことができ、PostgreSQLは IN のみとなっている。

 

    • 35.11. Oracle PL/SQLからの移植

 

    PostgreSQLではTRIGGERのREPLACEが存在しないため、更新の際はTRIGGERの削除が必要になる。

介绍创建和调用三角函数的方法。

-- Insert Beforeトリガ
CREATE OR REPLACE TRIGGER TBI_MSTW000010
BEFORE INSERT 
ON MSTW012010
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW 
BEGIN
    :new.CA := TO_CHAR(SYSDATE,'YYYYMMDD');
    :new.CB := TO_CHAR(SYSDATE,'HH24MMSS');
END;
 
-- Update Beforeトリガ
CREATE OR REPLACE TRIGGER TBU_MSTW000010
BEFORE UPDATE 
ON MSTW000010
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW 
BEGIN
    :new.CC := TO_CHAR(SYSDATE,'YYYYMMDD');
    :new.CD := TO_CHAR(SYSDATE,'HHMMSS');
END;

在PostgreSQL中,需要单独创建一个只用于触发器的函数(无参数)。

-- トリガ関数
CREATE OR REPLACE FUNCTION db_test."MSTW000010_insert"() RETURNS trigger AS
$BODY$
BEGIN
    NEW.CA := to_char(current_timestamp,'YYYYMMDD');
    NEW.CB := to_char(current_timestamp,'HH24MISS');
RETURN NEW;
END;
$BODY$
    LANGUAGE plpgsql VOLATILE
    COST 100;
    ALTER FUNCTION db_test."MSTW000010_insert"()
    OWNER TO postgres;
 
CREATE OR REPLACE FUNCTION db_test."MSTW000010_update"() RETURNS trigger AS
$BODY$
BEGIN
    NEW.CC := to_char(current_timestamp,'YYYYMMDD');
    NEW.CD := to_char(current_timestamp,'HHMISS');
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION db_test."MSTW000010_update"()
OWNER TO postgres;
 
-- Insert Before トリガ
CREATE TRIGGER "TBI_MSTW000010"
BEFORE INSERT
ON db_test.mstw000010
FOR EACH ROW
EXECUTE PROCEDURE db_test."MSTW000010_insert"();
 
-- Update Before トリガ
CREATE TRIGGER "TBU_MSTW000010"
BEFORE UPDATE
ON db_test.mstw000010
FOR EACH ROW
EXECUTE PROCEDURE db_test."MSTW000010_update"();

自我约束型交易

自律型交易是由正在进行的主要交易启动的独立(自主)交易。主要交易和自律型交易的提交回滚操作互不影响,完全独立的不同交易。

Oracle可以使用自动事务,但是PostgreSQL不能使用。

通过使用dblink等工具可以实现这一功能。
【PostgreSQL】可以在SELECT中更新其他表。

其他(唯一的选择)

    • PostgreSQLの場合、テーブルのカラム名に予約語(例 “DO”)があるとそのままでは使えない。二重引用符”do”を付与すれば使える

 

    • PostgreSQLの場合、SELECTで別名にしたカラム名をORDER BY句で指定できないため、一段上にSELECTを追加する必要がある

 

    • PostgreSQLの場合、MAX値取得でORDER BY句があるとエラーになる。そもそもORDER BY句が不要

 

    • PostgreSQLの場合、FORMAT関数ではパーセント(%)をエスケープで2つ(%%)にする必要がある

 

    PostgreSQLの場合、FROMとテーブル名の区切りが全角空白だとエラーになるので半角空白にする。

PL/SQL迁移

将PL/SQL迁移到PostgreSQL-迁移概述/迁移示例。

Oracle到PostgresSQL的迁移工具

转移支援工具(ora2pg)。

    • ora2pg

 

    • このora2pgがすごい!Oracleのストアドプロシージャ2種をPostgreSQLに移行してみた!

 

    • how to install ora2pg on windows 7?

 

    • OracleからPostgresqlへ移行する

 

    オープンソースミドルウェアへの移行のための 移植開発支援ツールの評価 pdf

要运行ora2pg,需要使用Perl5。

    Windows で使用できるフリーの Perl実行環境 Strawberry Perl

甲骨文互換函式庫(oraface)。

只要从源代码编译,门槛就会很高(因为有用户提供预编译版本,可以享受到好处),有起初就可使用的环境就很便利。

    • Orafce ホームページへようこそ

 

    • PGECons 組み込み関数移行調査編

 

    • orafce拡張モジュールの紹介

 

    • PostgreSQL 10、11、および12用のorafce3.8用のプリコンパイル済みライブラリ

 

    Windows 10 + PostgreSQL 10.10 に orafce を組込む

数据库语法差异

这是由NTT开发的开源工具。它支持Ora2Pg不支持的SELECT语句、UPDATE语句等数据操作的SQL。它还可以用于嵌入在程序语言中作为字符串字面量的SQL代码。然而,实际的修正仍然需要人工进行。

    • APをPostgreSQLへ移植する際の影響箇所を検出するツール

 

    • 影響箇所抽出作業の短縮化

 

    抽出の網羅性向上、品質の均⼀化

EDB Postgres(兼容Oracle的高度互換性的PostgreSQL)

EDB Postgres(一个前身是Postgres Plus Advanced Server的产品)具有与Oracle Database高度兼容的特性,支持与Oracle Database相同的SQL语法、函数和过程。

Oracleで使用しているSQLPostgreSQLでの対応EDB Postgresでの対応外部結合演算子(+)外部結合OUTER JOIN対応日付、時刻 日付関数や書式ほぼすべて変更が必要一部互換動作に対応条件分岐関数 nvlなど
対応トランザクション内のROLLBACK挙動・対応不可Oracle互換モードを選択可能FROM句内のサブクエリで別名不要・FROM句内サブクエリの別名必須対応集合演算子 minus・集合演算子 except対応NULLと空文字の区別がない対応不可一部互換動作を設定可能・ROWNUM
・MERGE文
・oidまたはROWNUMで対応(制限あり)
・INSERT ・・・ON CONFRICT

以下提供了兼容性实用工具。

Oracle Database (コマンド)Postgres Plus (コマンド)SQL*Plus (sqlplus)EDB*Plus (edbplus.sh)SQL*Loader (sqlldr)EDB*Loader (edbldr)Wrap (wrap)EDB*Wrap (edbwrap)
    • PostgresPlus Advanced Server の Oracle Database 互換機能検証 – SlideShare

 

    • Vol.3 Postgres Plus Advanced Server(体験編1)

 

    • Vol.4 Postgres Plus Advanced Server(体験編2)

 

    • 商用DBからPostgreSQLへ まず知っておいて欲しいまとめ – SlideShare

 

    Oratopostgres-hiroshima – SlideShare

请根据以下内容进行中国本土化的改写:

借鉴

    • PostgreSQL select で文字列を連結するときの注意点

 

    • PostgreSQLで文字列の結合(||)をすると勝手にトリムされる(固定長文字列を生成する際には注意)

 

    • PostgreSQLとOracleによるデータベース相互移行マニュアル

 

    • Oracle PL/SQL からの移植

 

    • Oracle DatabaseとPostgreSQLの違い

 

    • OracleとPostgreSQLの違い PostgreSQLでは、nullと空文字は区別されます。

 

    • [Oracle][PostgreSQL]Date型の違い

 

    • Oracle PL/SQL から PostgreSQL PL/pgSQL への移植の注意メモ PostgreSQL では関数をオーバーロードすることができます。

 

    • PostgreSQL の SELECT句で Null文字列を連結する方法

 

    • PostgreSQLのSQL

 

    • PostgreSQLでカラムを追加する際にdefault値を設定する方法

 

    • PostgreSQLで自動的にインデックスが生成される条件

 

    • PostgreSQLとMySQLはどちらかに明確な優位性がありますか、というの質問・回答

 

    • テーブル名やカラム名にSQLの予約語を使う方法

 

    • Oracle⇔Postgresqlの組み込みデータ型対応表

 

    • PostgreSQLチューニング実践テクニック(DISTINCTよりGROUP BYの方が速い)

 

    • PostgreSQL Internals (1) for PostgreSQL 9.6 (Japanese) – SlideShare

 

    WHERE句でエイリアスを使う

最后

还有其他的机会来谈论关于导入、导出、调整和备份与恢复等等的事项。我在另一篇文章中进行了描述,现在提供链接。

    • エクスポートやインポート

 

    • チューニング

 

    • 【PostgreSQL 9.6】指定した時間までリカバリするPITR

 

    • 【PostgreSQL 12】指定した時間までリカバリするPITR

 

    • 【PostgreSQL】WSH/VBScriptでpsqlを使用する

 

    • 【PostgreSQL】psqlのCOPYコマンドに変数で絶対パスを渡す

 

    • 【PostgreSQL】psqlのCOPYコマンドによるCSVインポートで重複エラーを回避する

 

    • 【PostgreSQL】テーブルのインデックスが壊れた話

 

    • PostgreSQLテーブルの作成日時と更新日時の取得について

 

    • PostgreSQLインデックスの作成日時と更新日時の取得について

 

    • 【PostgreSQL】psqlのスクリプトエラーを無視し続行させる

 

    • 【PostgreSQL】SELECT内で他のテーブルを更新する

 

    • 【PostgreSQL】トリガーを使用して回数チェックし例外エラーとする

 

    • 【PostgreSQL】初回クエリーが遅い

 

    • 【PostgreSQL 9.6→12】pg_upgrade によるアップグレード手順

 

    【PostgreSQL 12→14】pg_upgrade によるアップグレード手順
广告
将在 10 秒后关闭
bannerAds