値が Oracle から PostgreSQL に転送されるときにエラーが発生するため、後処理ではエラーを防止できません。
デモンストレーションのために、問題を示す Oracle テーブルを作成してみましょう:
CREATE TABLE nulltest( id number(5) CONSTRAINT nulltest_pkey PRIMARY KEY, val varchar2(10 CHAR) ); INSERT INTO nulltest VALUES (1, 'schön'); INSERT INTO nulltest VALUES (2, 'bö' || CHR(0) || 'se'); INSERT INTO nulltest VALUES (3, 'egal'); COMMIT;
プレ>PostgreSQL に外部テーブルを作成しましょう:
CREATE FOREIGN TABLE nulltest ( id integer OPTIONS (key 'true') NOT NULL, val varchar(10) ) SERVER oracle OPTIONS (table 'NULLTEST'); SELECT * FROM nulltest; ERROR: invalid byte sequence for encoding "UTF8": 0x00 CONTEXT: converting column "val" for foreign table scan of "nulltest", row 2
プレ>最も簡単な方法は、ゼロ文字を除外する外部テーブルを作成することです:
CREATE FOREIGN TABLE filter_nulltest ( id integer OPTIONS (key 'true') NOT NULL, val varchar(10) ) SERVER oracle OPTIONS (table '(SELECT id, replace(val, CHR(0), NULL) FROM nulltest)'); SELECT * FROM filter_nulltest; ┌────┬───────┐ │ id │ val │ ├────┼───────┤ │ 1 │ schön │ │ 2 │ böse │ │ 3 │ egal │ └────┴───────┘ (3 rows)
プレ>効率の悪いもう 1 つのオプションは、Oracle 側で修正できるように、不正な行をキャッチして報告する関数を作成することです。
CREATE OR REPLACE FUNCTION get_nulltest() RETURNS SETOF nulltest LANGUAGE plpgsql AS $$DECLARE v_id integer; n nulltest; BEGIN FOR v_id IN SELECT id FROM nulltest LOOP BEGIN SELECT nulltest.* INTO n FROM nulltest WHERE id = v_id; RETURN NEXT n; EXCEPTION WHEN OTHERS THEN RAISE NOTICE 'Caught error % for id=%: %', SQLSTATE, v_id, SQLERRM; END; END LOOP; END;$$; SELECT * FROM get_nulltest(); NOTICE: Caught error 22021 for id=2: invalid byte sequence for encoding "UTF8": 0x00 ┌────┬───────┐ │ id │ val │ ├────┼───────┤ │ 1 │ schön │ │ 3 │ egal │ └────┴───────┘ (2 rows)
プレ>