カテゴリー別アーカイブ: Oracle

OracleのImport/Exportについて

「Oracle10g → 11g へのデータ移行」
の記事がちょこちょこ参照されているようで、やっぱりみんなバージョン違いのImport/Exportはちょっと困ってるんだろうな、と。
なので、今回は己の備忘録も兼ねてimp/expコマンドとはまた別のやり方を。

基本的には imp/expコマンドとほとんど同じで、使うコマンドは impdp/expdp です。

以下、DBサーバ上で作業することを前提に記載します。

impdp/expdp の場合、出力するディレクトリオブジェクトを設定する必要があります。

Exportするディレクトリを「C:\db\expdata」とした場合、
以下、SQL Plus にて、

SQL> create directory [DIR_NAME] as 'C:\db\expdata'

と設定します。

[DIR_NAME]はどんな名前でもいいです。
「test1」でも「expdir」でも。
あくまでも、ディレクトリオブジェクト名なので。

その後、

SQL> host expdp [USER]/[PW] directory=[DIR_NAME] dumpfile=[TABLE_NAME_YYYYMMDD.dump] logfile=[TABLE_NAME_YYYYMMDD.log] tables=[TABLE_NAME];

とやってあげると、指定されたテーブルのDumpデータが、指定されたディレクトリに作成されます。
※テーブル単位、ユーザ単位、スキーマ単位など、そのあたりはマニュアルやら他のサイトを参照してください

ちなみに、数百万レコード単位のテーブルから、条件を指定してExportしたい、という場合、

SQL> host expdp [USER]/[PW] directory=[DIR_NAME] dumpfile=[TABLE_NAME_YYYYMMDD.dump] logfile=[TABLE_NAME_YYYYMMDD.log] tables=[TABLE_NAME] QUERY='TABLE_NAME:WHERE ID >= ''1000000''';

のように、WHERE句を付与することで抽出出来ます。

また、下位バージョンから上位バージョンへのImport/Exportは問題ないのですが、上位バージョンから下位バージョンへのImport/Exportの場合、Exportする際にバージョンを指定してあげる必要があります。

SQL> host expdp [USER]/[PW] directory=[DIR_NAME] dumpfile=[TABLE_NAME_YYYYMMDD.dump] logfile=[TABLE_NAME_YYYYMMDD.log] tables=[TABLE_NAME] VERSION=10.2.0;

次に、ExportしたファイルをImportする場合、こちらもまずはディレクトリオブジェクトを設定する必要があります。

Importするファイルが存在するディレクトリを「C:\db\impdata」とした場合、
以下、SQL Plus にて、

SQL> create directory [DIR_NAME] as 'C:\db\impdata'

と設定します。

その後、

SQL> host impdp [USER]/[PW] directory=[DIR_NAME] dumpfile=[EXPORT_FILE_NAME] tables=[TABLE_NAME];

とやってあげると、指定されたテーブルにExportしたデータがImportされます。

Import時もExport時も、create directory で作成したディレクトリオブジェクト設定は、削除しないとずっと残ってしまうので、

SQL> drop directory [DIR_NAME];

として、削除してください。

imp/expコマンドより、impdp/expdpコマンドの方が全然早いので、こっちの方がオススメです。

では。

CodeIgniter 2.0.2 + Oracle 10.2.0.3 の接続について

あまり日本語のエントリが無かったので、ちょっと書いてみる。
PHP+Oracleの環境については、手前味噌ですがこちらの記事を参照。
CodeIgniterの環境設定については、ユーザガイドを参照。

動作検証を実施したサーバ環境は、以下。
・CentOS 4.8
・Oracle 10.2.0.3
・Oracle Instant Client 11.0.2
・PHP 5.3.2
・CodeIgniter 2.0.2

設定したコンフィグの内容は以下。
application/config/database.php


$db[‘default’][‘hostname’] = ‘//DB_SERVER_IP:PORT/SID‘;
$db[‘default’][‘username’] = ‘USER_ID‘;
$db[‘default’][‘password’] = ‘PASSWORD‘;
$db[‘default’][‘database’] = ‘DATABASE_NAME‘;
$db[‘default’][‘dbdriver’] = ‘oci8’; ← コレ。「OCI8」のドライバを指定する
$db[‘default’][‘dbprefix’] = ”;
$db[‘default’][‘pconnect’] = TRUE;
$db[‘default’][‘db_debug’] = TRUE;
$db[‘default’][‘cache_on’] = FALSE;
$db[‘default’][‘cachedir’] = ”;
$db[‘default’][‘char_set’] = ‘utf8’;
$db[‘default’][‘dbcollat’] = ‘utf8_general_ci’;
$db[‘default’][‘swap_pre’] = ”;
$db[‘default’][‘autoinit’] = TRUE;
$db[‘default’][‘stricton’] = FALSE;


こんな感じで。

これであとはModel作ってSQL発行すればOK。
ActiveRecordでも問題無し。
簡単でした。

ちなみに、Oracleでシーケンスを取得するのにはこんな感じで。

function get_seq() {
  $this->db->SELECT(‘SEQUENCE_NAME.nextval as nextval’,FALSE)->FROM(‘dual’);
  $query = $this->db->get();
  return $query->result();
}

SELECT に 「FALSE」付けてあげないと、うまく取得出来ないです。
※勝手に「”」「’」とか付けちゃうので

では。

Oracle10g → 11g へのデータ移行

※2017/04/25 追記
こっちの記事の方がいいかも。
OracleのImport/Exportについて

32bit版Oracle10gから64bit版Oracle11gへのデータ移行手順を。
忘れない内に。

まず、10gの方でExport。

次に、11gの方でDB作成、ユーザ作成。

で、11gの方でImport。

Importオプションは以下。

imp system/manager@[インスタンス名] fromuser=[ユーザ名] touser=[ユーザ名] file=[Dumpデータファイルパス] log=[ログファイルパス]

以上で完了。

細かいオプションやら何やらは、環境に依って変わると思うので、マニュアル等で調べてくださいな。

では。

PHP(PDO)+Oracle=too large for buffer and was truncated

ハマったので。

PHP 5.1.6

Oracle 10.2.3

にて。

PDO_OCIでPHPとOracleとを繋いでる環境でエラーじゃないけど、Warningが出た。

Warning: PDOStatement::fetch(): column X data was too large for buffer and was truncated to fit it in test.php on line XXX

VARCHAR2のカラムからデータを取得すると出た。

正常にデータが取得出来てるっぽかったけど、おしりの何バイトかが切れてた。

おぉ、trancateされてる。

色々調べてみたところ、全角文字が入ってるとダメだった。

さらに調べてみると、原因が分かった。

Oracle:SJIS

PHP:UTF-8

これが原因だった。

OracleはSJISなので、全角文字は2バイト。

PHPはUTF-8なので、全角文字は3バイト。

PDO_OCIの場合、テーブルのカラムの型と長さを参照してバッファを決めるようで。

全角文字が入っていた場合、そのバッファが溢れる事があるのです。

なんせ、2バイトだと思っていた全角文字が3バイトだったので。

VARCHAR2(20)のカラムに、全角文字が10文字入っていた場合、SJISならば20バイトなので、OK。

しかし、UTF-8だと30バイトになってしまうので、受け取る側のバッファが溢れてしまう、という事。

対応どうしようか・・・

と考え、

/etc/sysconfig/httpd

をちょっと編集してみた。

# cd /etc/sysconfig/

# vi httpd

export NLS_LANG=Japanese_Japan.UTF8

↓に変更

export NLS_LANG=Japanese_Japan.JA16SJIS

# /etc/rc.d/init.d/httpd restart

Warnningは出なくなったけど、文字化けした。

DBから取得してる根っこの部分でSJIS→UTF-8の変換をかけようかと考えたのですが、symfony+doctorineという事もあり、断念。

だって、調べるの面倒だから・・・

テーブルのカラム長の定義を1.5倍すれば回避出来るけど、運用案件では無理なので断念。

結果、PDO_OCIのソースをちょっと直して対応する事に。

# cd /usr/local/src

# cd PDO_OCI-1.0

# vi oci_statement.c

510行目付近に有る記述

col->maxlen = data_size;

col->maxlen = data_size*1.5;

# ./configure

# make

# make install

PDOがOracleのテーブルのカラムの長さを取得してる部分で、その長さを1.5倍してあげれば大丈夫。

この対応方法が良いかどうかは疑問が残るが、とりあえずはこれで回避しよう。

でわ。