Mac De Oracle Heterogeneous! #22 Tweet
つづきです。前回は、MySQL側で日付、時刻型がどのように登録され、どのような癖があるのかを確認した。
今回は、Generic Connectivity経由でアクセスした場合、Oracle側ではMySQLの日付、時刻型がどのようにどのように扱われるか確認する。
以下のような経路でアクセスしている。
MySQL4.1.13aには以下のようなデータが登録済み。気になるところは0000年00月00日が許容されている点だろう。
Last login: Thu Jan 26 00:32:31 on console
Welcome to Darwin!
G5Server:˜ discus$ mysql -u discus -p mysqldb41
Enter password:
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Welcome to the MySQL monitor. Commands end with ; or ¥g.
Your MySQL connection id is 1 to server version: 4.1.13a
Type 'help;' or '¥h' for help. Type '¥c' to clear the buffer.
mysql>
mysql>
mysql> select * from date_test;
+---------------------+------------+---------------------+----------+--------+
| r_datetime | r_date | r_timestamp | r_time | r_year |
+---------------------+------------+---------------------+----------+--------+
| 1990-01-01 00:00:00 | NULL | 2006-01-20 23:04:22 | NULL | NULL |
| 2000-12-01 00:00:00 | NULL | 2006-01-20 23:04:35 | NULL | NULL |
| NULL | 1800-01-01 | 2006-01-20 23:04:51 | NULL | NULL |
| NULL | 1810-12-01 | 2006-01-20 23:05:06 | NULL | NULL |
| NULL | NULL | 2002-12-01 00:00:00 | NULL | NULL |
| NULL | NULL | 2006-01-20 23:05:33 | NULL | NULL |
| 0000-00-00 00:00:00 | 0000-00-00 | 0000-00-00 00:00:00 | 00:00:00 | 0000 |
| NULL | NULL | 2006-01-24 23:12:32 | NULL | NULL |
| 2006-01-24 23:13:19 | 2006-01-24 | 2006-01-24 23:13:19 | 23:13:19 | 2006 |
| 0000-00-00 00:00:00 | 0000-00-00 | 0000-00-00 00:00:00 | 00:00:00 | 0000 |
| 0000-00-00 00:00:00 | NULL | 2006-01-24 23:30:56 | NULL | NULL |
| 0000-00-00 00:00:00 | NULL | 2006-01-24 23:32:31 | NULL | NULL |
| 2006-00-00 00:00:00 | NULL | 2006-01-24 23:43:53 | NULL | NULL |
| NULL | NULL | 0000-00-00 00:00:00 | NULL | NULL |
| 0000-00-00 00:00:00 | 0000-00-00 | 0000-00-00 00:00:00 | 00:00:00 | 0000 |
| 2006-00-00 00:00:00 | NULL | 2006-01-25 00:06:11 | NULL | NULL |
+---------------------+------------+---------------------+----------+--------+
16 rows in set (0.02 sec)
mysql>
まず、単純に問い合わせてみる。datetime型、date型、timestamp型、time型は、Oracleのdate型にマッピングされている。year型はnumber型にマッピングされている。OracleではMySQLのtime型もdate型として扱われている。一番まずいのは、timestamp型に 0000年00月00日が設定されている場合、オラクル側でも0000年00月00日となってしまう点である。Oracle側ではその後の処理で問題になる。尚、ODBCの仕様では、NULLになるのが正しいようなのでこのテストで利用している MyODBCドライバの問題である可能性が高いと思われる。(timestamp型以外ではNULLが返されている)
CORYDORAS> alter session set nls_date_format = 'yyyy/mm/dd hh24:mi:ss';
セッションが変更されました。
CORYDORAS> alter session set nls_timestamp_format = 'yyyy/mm/dd hh24:mi:ss.ff';
セッションが変更されました。
CORYDORAS> select * from date_test_mysql4113a_mac_sv@oracle10g_win;
r_datetime r_date r_timestamp r_time r_year
------------------- ------------------- ------------------- ------------------- ----------
1990/01/01 00:00:00 2006/01/20 23:04:22
2000/12/01 00:00:00 2006/01/20 23:04:35
1800/01/01 00:00:00 2006/01/20 23:04:51
1810/12/01 00:00:00 2006/01/20 23:05:06
2002/12/01 00:00:00
2006/01/20 23:05:33
0000/00/00 00:00:00 0001/01/01 00:00:00 0
2006/01/24 23:12:32
2006/01/24 23:13:19 2006/01/24 00:00:00 2006/01/24 23:13:19 0001/01/01 23:13:19 2006
0000/00/00 00:00:00 0001/01/01 00:00:00 0
2006/01/24 23:30:56
2006/01/24 23:32:31
2006/01/24 23:43:53
0000/00/00 00:00:00
0000/00/00 00:00:00 0001/01/01 00:00:00 0
2006/01/25 00:06:11
16行が選択されました。
CORYDORAS>
CORYDORAS> select
2 dump("r_datetime") as r_datetime,
3 dump("r_date") as r_date,
4 dump("r_timestamp") as r_timestamp,
5 dump("r_time") as r_time,
6 dump("r_year") as r_year
7 from
8 date_test_mysql4113a_mac_sv@oracle10g_win;
R_DATETIME R_DATE R_TIMESTAMP R_TIME R_YEAR
------------------------------------ ------------------------------------ ------------------------------------ ------------------------------------ ------------------------------------
Typ=12 Len=7: 119,190,1,1,1,1,1 NULL Typ=12 Len=7: 120,106,1,20,24,5,23 NULL NULL
Typ=12 Len=7: 120,100,12,1,1,1,1 NULL Typ=12 Len=7: 120,106,1,20,24,5,36 NULL NULL
NULL Typ=12 Len=7: 118,100,1,1,1,1,1 Typ=12 Len=7: 120,106,1,20,24,5,52 NULL NULL
NULL Typ=12 Len=7: 118,110,12,1,1,1,1 Typ=12 Len=7: 120,106,1,20,24,6,7 NULL NULL
NULL NULL Typ=12 Len=7: 120,102,12,1,1,1,1 NULL NULL
NULL NULL Typ=12 Len=7: 120,106,1,20,24,6,34 NULL NULL
NULL NULL Typ=12 Len=7: 100,100,0,0,1,1,1 Typ=12 Len=7: 100,101,1,1,1,1,1 Typ=2 Len=1: 128
NULL NULL Typ=12 Len=7: 120,106,1,24,24,13,33 NULL NULL
Typ=12 Len=7: 120,106,1,24,24,14,20 Typ=12 Len=7: 120,106,1,24,1,1,1 Typ=12 Len=7: 120,106,1,24,24,14,20 Typ=12 Len=7: 100,101,1,1,24,14,20 Typ=2 Len=3: 194,21,7
NULL NULL Typ=12 Len=7: 100,100,0,0,1,1,1 Typ=12 Len=7: 100,101,1,1,1,1,1 Typ=2 Len=1: 128
NULL NULL Typ=12 Len=7: 120,106,1,24,24,31,57 NULL NULL
NULL NULL Typ=12 Len=7: 120,106,1,24,24,33,32 NULL NULL
NULL NULL Typ=12 Len=7: 120,106,1,24,24,44,54 NULL NULL
NULL NULL Typ=12 Len=7: 100,100,0,0,1,1,1 NULL NULL
NULL NULL Typ=12 Len=7: 100,100,0,0,1,1,1 Typ=12 Len=7: 100,101,1,1,1,1,1 Typ=2 Len=1: 128
NULL NULL Typ=12 Len=7: 120,106,1,25,1,7,12 NULL NULL
16行が選択されました。
CORYDORAS>
nullを設定するのは問題なかった。次が問題、パススルーされているようで、MySQL側で空文字を設定した場合と同じ結果になる。MySQLではワーニングが表示されたりするが、generic connectivity 経由では正常に?処理されてしまう。(ワーニングを拾う方法はあるのか? 別途調べるか・・)
CORYDORAS> insert into date_test_mysql4113a_mac_sv@oracle10g_win values(null,null,null,null,null);
1行が作成されました。
CORYDORAS> insert into date_test_mysql4113a_mac_sv@oracle10g_win values('','','','','');
1行が作成されました。
CORYDORAS> set null 'NULL'
CORYDORAS> commit;
コミットが完了しました。
CORYDORAS> select * from date_test_mysql4113a_mac_sv@oracle10g_win;
r_datetime r_date r_timestamp r_time r_year
------------------------------ ------------------------------ ------------------------------ ------------------------------ ------
1990/01/01 00:00:00 NULL 2006/01/20 23:04:22 NULL NULL
2000/12/01 00:00:00 NULL 2006/01/20 23:04:35 NULL NULL
NULL 1800/01/01 00:00:00 2006/01/20 23:04:51 NULL NULL
NULL 1810/12/01 00:00:00 2006/01/20 23:05:06 NULL NULL
NULL NULL 2002/12/01 00:00:00 NULL NULL
NULL NULL 2006/01/20 23:05:33 NULL NULL
NULL NULL 0000/00/00 00:00:00 0001/01/01 00:00:00 0
NULL NULL 2006/01/24 23:12:32 NULL NULL
2006/01/24 23:13:19 2006/01/24 00:00:00 2006/01/24 23:13:19 0001/01/01 23:13:19 2006
NULL NULL 0000/00/00 00:00:00 0001/01/01 00:00:00 0
NULL NULL 2006/01/24 23:30:56 NULL NULL
NULL NULL 2006/01/24 23:32:31 NULL NULL
NULL NULL 2006/01/24 23:43:53 NULL NULL
NULL NULL 0000/00/00 00:00:00 NULL NULL
NULL NULL 0000/00/00 00:00:00 0001/01/01 00:00:00 0
NULL NULL 2006/01/25 00:06:11 NULL NULL
NULL NULL 2006/01/27 01:00:12 NULL NULL
NULL NULL 0000/00/00 00:00:00 0001/01/01 00:00:00 0
18行が選択されました。
CORYDORAS>
year型はnumber型にマップされているので仕方ないが、date型にマップされている各型でもオラクルではエラーになる0000年や、00月、00日は登録できてしまう。
CORYDORAS> insert into date_test_mysql4113a_mac_sv@oracle10g_win values('0000-00-00 00:00:00','0000-00-00','0000-00-00 00:00:00.123456','0000-00-00 00:00:00','0000');
1行が作成されました。
CORYDORAS> commit;
コミットが完了しました。
CORYDORAS> select * from date_test_mysql4113a_mac_sv@oracle10g_win;
r_datetime r_date r_timestamp r_time r_year
------------------------------ ------------------------------ ------------------------------ ------------------------------ ------
1990/01/01 00:00:00 NULL 2006/01/20 23:04:22 NULL NULL
2000/12/01 00:00:00 NULL 2006/01/20 23:04:35 NULL NULL
NULL 1800/01/01 00:00:00 2006/01/20 23:04:51 NULL NULL
NULL 1810/12/01 00:00:00 2006/01/20 23:05:06 NULL NULL
NULL NULL 2002/12/01 00:00:00 NULL NULL
NULL NULL 2006/01/20 23:05:33 NULL NULL
NULL NULL 0000/00/00 00:00:00 0001/01/01 00:00:00 0
NULL NULL 2006/01/24 23:12:32 NULL NULL
2006/01/24 23:13:19 2006/01/24 00:00:00 2006/01/24 23:13:19 0001/01/01 23:13:19 2006
NULL NULL 0000/00/00 00:00:00 0001/01/01 00:00:00 0
NULL NULL 2006/01/24 23:30:56 NULL NULL
NULL NULL 2006/01/24 23:32:31 NULL NULL
NULL NULL 2006/01/24 23:43:53 NULL NULL
NULL NULL 0000/00/00 00:00:00 NULL NULL
NULL NULL 0000/00/00 00:00:00 0001/01/01 00:00:00 0
NULL NULL 2006/01/25 00:06:11 NULL NULL
NULL NULL 2006/01/27 01:00:12 NULL NULL
NULL NULL 0000/00/00 00:00:00 0001/01/01 00:00:00 0
NULL NULL 0000/00/00 00:00:00 0001/01/01 00:00:00 0
19行が選択されました。
CORYDORAS>
MySQL側では以下のようになっている。timestamp型の0000−00−00がOracle側ではNULLにならないのでOracle側のクエリでNULLに強制的に変換してやる必要がありそうだ。(year型の場合も強制的にNULLにするか、0001年にするようなクエリにする必要はありそうだ)
mysql> select * from date_test;
+---------------------+------------+---------------------+----------+--------+
| r_datetime | r_date | r_timestamp | r_time | r_year |
+---------------------+------------+---------------------+----------+--------+
| 1990-01-01 00:00:00 | NULL | 2006-01-20 23:04:22 | NULL | NULL |
| 2000-12-01 00:00:00 | NULL | 2006-01-20 23:04:35 | NULL | NULL |
| NULL | 1800-01-01 | 2006-01-20 23:04:51 | NULL | NULL |
| NULL | 1810-12-01 | 2006-01-20 23:05:06 | NULL | NULL |
| NULL | NULL | 2002-12-01 00:00:00 | NULL | NULL |
| NULL | NULL | 2006-01-20 23:05:33 | NULL | NULL |
| 0000-00-00 00:00:00 | 0000-00-00 | 0000-00-00 00:00:00 | 00:00:00 | 0000 |
| NULL | NULL | 2006-01-24 23:12:32 | NULL | NULL |
| 2006-01-24 23:13:19 | 2006-01-24 | 2006-01-24 23:13:19 | 23:13:19 | 2006 |
| 0000-00-00 00:00:00 | 0000-00-00 | 0000-00-00 00:00:00 | 00:00:00 | 0000 |
| 0000-00-00 00:00:00 | NULL | 2006-01-24 23:30:56 | NULL | NULL |
| 0000-00-00 00:00:00 | NULL | 2006-01-24 23:32:31 | NULL | NULL |
| 2006-00-00 00:00:00 | NULL | 2006-01-24 23:43:53 | NULL | NULL |
| NULL | NULL | 0000-00-00 00:00:00 | NULL | NULL |
| 0000-00-00 00:00:00 | 0000-00-00 | 0000-00-00 00:00:00 | 00:00:00 | 0000 |
| 2006-00-00 00:00:00 | NULL | 2006-01-25 00:06:11 | NULL | NULL |
| NULL | NULL | 2006-01-27 01:00:12 | NULL | NULL |
| 0000-00-00 00:00:00 | 0000-00-00 | 0000-00-00 00:00:00 | 00:00:00 | 0000 |
| 0000-00-00 00:00:00 | 0000-00-00 | 0000-00-00 00:00:00 | 00:00:00 | 0000 |
+---------------------+------------+---------------------+----------+--------+
19 rows in set (0.00 sec)
mysql>
長くなるので次回につづく。
| 固定リンク | 0
コメント