2010年9月26日 (日)

pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? Season2 #4

Oracle10g R2 EE 10.2.0.4.0 for MacOS X x86-64で再確認の続き。

pga_aggregate_targetがどの程度になると、_pga_max_sizeが200MBをこえるんでしょうねぇ。調べてみましょう。わくわくです。

SYS> alter system set pga_aggregate_target=150m;

システムが変更されました。

SYS>
SYS> @show_hidden_pga_param

KSPPINM KSPPSTVL KSPPSTDF
------------------------------ ------------------------------ ---------
_pga_large_extent_size 1048576 TRUE
_pga_max_size 209715200 TRUE
_use_ism_for_pga TRUE TRUE
pga_aggregate_target 157286400 FALSE

SYS> alter system set pga_aggregate_target=200m;

システムが変更されました。

SYS> @show_hidden_pga_param

KSPPINM KSPPSTVL KSPPSTDF
------------------------------ ------------------------------ ---------
_pga_large_extent_size 1048576 TRUE
_pga_max_size 209715200 TRUE
_use_ism_for_pga TRUE TRUE
pga_aggregate_target 209715200 FALSE

SYS> alter system set pga_aggregate_target=500m;

システムが変更されました。

SYS> @show_hidden_pga_param

KSPPINM KSPPSTVL KSPPSTDF
------------------------------ ------------------------------ ---------
_pga_large_extent_size 1048576 TRUE
_pga_max_size 209715200 TRUE
_use_ism_for_pga TRUE TRUE
pga_aggregate_target 524288000 FALSE

SYS> alter system set pga_aggregate_target=1023m;

システムが変更されました。

SYS> @show_hidden_pga_param

KSPPINM KSPPSTVL KSPPSTDF
------------------------------ ------------------------------ ---------
_pga_large_extent_size 1048576 TRUE
_pga_max_size 214528000 TRUE
_use_ism_for_pga TRUE TRUE
pga_aggregate_target 1072693248 FALSE

SYS> alter system set pga_aggregate_target=1010m;

システムが変更されました。

SYS> @show_hidden_pga_param

KSPPINM KSPPSTVL KSPPSTDF
------------------------------ ------------------------------ ---------
_pga_large_extent_size 1048576 TRUE
_pga_max_size 211804160 TRUE
_use_ism_for_pga TRUE TRUE
pga_aggregate_target 1059061760 FALSE

SYS> alter system set pga_aggregate_target=1000m;

システムが変更されました。

SYS> @show_hidden_pga_param

KSPPINM KSPPSTVL KSPPSTDF
------------------------------ ------------------------------ ---------
_pga_large_extent_size 1048576 TRUE
_pga_max_size 209715200 TRUE
_use_ism_for_pga TRUE TRUE
pga_aggregate_target 1048576000 FALSE

SYS> alter system set pga_aggregate_target=1001m;

システムが変更されました。

SYS> @show_hidden_pga_param

KSPPINM KSPPSTVL KSPPSTDF
------------------------------ ------------------------------ ---------
_pga_large_extent_size 1048576 TRUE
_pga_max_size 209920000 TRUE
_use_ism_for_pga TRUE TRUE
pga_aggregate_target 1049624576 FALSE

SYS>

ということで、pga_aggreate_target=1000MBまでは、元々の値である200MBを維持しているようです。
1001MB以上で、_pga_max_sizeの値が動的に変化し始め、実際の値は、pga_aggregate_targetの19.999%程度になるようです。
丸めてしまえば、pga_aggregate_targetの20%なので、pga_aggregate_targetが1001MB以上の場合、その値の20%が、_pga_max_sizeに設定されるとしちゃっても特に問題ないかもしれませんけどね。

前回の結果も含めてまとめると、

  1. Oracle10g R2になると、10g R1までとは異なり_pga_max_sizeの値が、1000MBを超えると動的に変化し始める。
  2. pga_aggregate_targetが1GB近くまでだと、pga_aggregate_targetの20%。
  3. pga_aggregate_targetが1GB以上になると、_pga_max_sizeが、pga_aggregate_targetの19.999%程度の値に自動設定され、さらにその値の50%。結果的として、pga_aggregate_target値の10%をほんの少し下回る値が設定される。pga_aggregate_targetが10GBである場合、1GBをほんの少し下回るのサイズがpgaとして割り当てられる。
  4. pga_aggretate_targetが10GBを超えた場合、_pga_max_sizeが2GBで頭打ちとなり、結果的として1GBがPGAとして割り当てられる。つまり自動PGA管理における最大PGAサイズは1GBということになる。(64bit版ではね)

意図せず、_pga_max_sizeが固定化されてしまっていた以前のテストとは大きく異なる結果となってしまったが、_pga_max_sizeが動的に変化し最大2GBまで増えるってところを除けば仕組みは同じだよね。と :)

次回は、Oracle11g R1 EE 11.1.0.6.0 (x86) 32bit版で同様に再確認。次回へつづく。


前回までのあらすじ・・・
Mac De Oracle なんですが、Windows(32bit)でのOracleな話
Mac De Oracle なんですが、Windows(32bit)でのOracleな話 #2
Mac De Oracle なんですが、Windows(32bit)でのOracleな話 #3
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #1
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #2
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #3
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #4
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #5
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #6
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #7
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #8
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #9
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #10
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #11
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #12
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #13
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #14
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #15
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #16
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #17
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #18
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #19
_pga_max_sizeってOracle11gではどうなったっけ? という確認。
_pga_max_sizeってOracle11gではどうなったっけ? という確認。シーズン2
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? Season2 #1
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? Season2 #2
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? Season2 #3

| | | コメント (0) | トラックバック (0)

2010年9月24日 (金)

pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? Season2 #2

前回からのつづきです。Oracle10g R1 10.1.0.3.0 (32bit)で _pga_max_sizeパラメータ値がデフォルトの場合、pga_aggregate_targetパラメータ値を10MB/50MB/1GB/5GB/10GB/4095GBと変化させ、pgaに使用されるサイズがどのように変化するか、v$pgastatビューのglobal memory boundを見て確認していく。

結果は見ての通り。Oracle10g R1では、_pga_max_sizeパラメータはpga_aggregate_targetには影響されず、常に200MBで固定されている。従ってOracle10g R1では、以前のテスト結果の通り
pga_aggregate_targetの5%又は、_pga_max_size(200MB)の50%でいづれかの小さいサイズが利用されるというのは正しいようだ。

SYS> alter system set pga_aggregate_target=10m;

システムが変更されました。

SYS> @show_hidden_pga_param

KSPPINM KSPPSTVL KSPPSTDF
------------------------------ ------------------------------ ---------------------------
_pga_large_extent_size 1048576 TRUE
_pga_max_size 209715200 TRUE
_use_ism_for_pga TRUE TRUE
pga_aggregate_target 10485760 FALSE

SYS> @pgastat

NAME size(MB)
------------------------------ ----------
aggregate PGA target parameter 10
aggregate PGA auto target 4
global memory bound .5

SYS> alter system set pga_aggregate_target=50m;

システムが変更されました。

SYS> @show_hidden_pga_param

KSPPINM KSPPSTVL KSPPSTDF
------------------------------ ------------------------------ ---------------------------
_pga_large_extent_size 1048576 TRUE
_pga_max_size 209715200 TRUE
_use_ism_for_pga TRUE TRUE
pga_aggregate_target 52428800 FALSE

SYS> @pgastat

NAME size(MB)
------------------------------ ----------
aggregate PGA target parameter 50
aggregate PGA auto target 31.7548828
global memory bound 2.5


SYS> alter system set pga_aggregate_target=1g;

システムが変更されました。

SYS> @show_hidden_pga_param

KSPPINM KSPPSTVL KSPPSTDF
------------------------------ ------------------------------ ---------------------------
_pga_large_extent_size 1048576 TRUE
_pga_max_size 209715200 TRUE
_use_ism_for_pga TRUE TRUE
pga_aggregate_target 1073741824 FALSE

SYS> @pgastat

NAME size(MB)
------------------------------ ----------
aggregate PGA target parameter 1024
aggregate PGA auto target 908.358398
global memory bound 51.1992188

SYS> alter system set pga_aggregate_target=5g;

システムが変更されました。

SYS> @show_hidden_pga_param

KSPPINM KSPPSTVL KSPPSTDF
------------------------------ ------------------------------ ---------------------------
_pga_large_extent_size 1048576 TRUE
_pga_max_size 209715200 TRUE
_use_ism_for_pga TRUE TRUE
pga_aggregate_target 5368709120 FALSE

SYS> @pgastat

NAME size(MB)
------------------------------ ----------
aggregate PGA target parameter 5120
aggregate PGA auto target 4594.71973
global memory bound 100

SYS> alter system set pga_aggregate_target=10g;

システムが変更されました。

SYS> @show_hidden_pga_param

KSPPINM KSPPSTVL KSPPSTDF
------------------------------ ------------------------------ ---------------------------
_pga_large_extent_size 1048576 TRUE
_pga_max_size 209715200 TRUE
_use_ism_for_pga TRUE TRUE
pga_aggregate_target 10737418240 FALSE

SYS> @pgastat

NAME size(MB)
------------------------------ ----------
aggregate PGA target parameter 10240
aggregate PGA auto target 9202.67578
global memory bound 100

SYS> alter system set pga_aggregate_target=4095g;

システムが変更されました。

SYS> @show_hidden_pga_param

KSPPINM KSPPSTVL KSPPSTDF
------------------------------ ------------------------------ ---------------------------
_pga_large_extent_size 1048576 TRUE
_pga_max_size 209715200 TRUE
_use_ism_for_pga TRUE TRUE
pga_aggregate_target 4396972769280 FALSE

SYS> @pgastat

NAME size(MB)
------------------------------ ----------
aggregate PGA target parameter 4193280
aggregate PGA auto target 3773929.69
global memory bound 100

SYS>


Oracle10g R2で再確認へつづく。



前回までのあらすじ・・・
Mac De Oracle なんですが、Windows(32bit)でのOracleな話
Mac De Oracle なんですが、Windows(32bit)でのOracleな話 #2
Mac De Oracle なんですが、Windows(32bit)でのOracleな話 #3
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #1
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #2
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #3
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #4
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #5
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #6
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #7
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #8
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #9
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #10
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #11
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #12
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #13
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #14
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #15
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #16
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #17
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #18
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #19
_pga_max_sizeってOracle11gではどうなったっけ? という確認。
_pga_max_sizeってOracle11gではどうなったっけ? という確認。シーズン2
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? Season2 #1

| | | コメント (0) | トラックバック (0)

2010年9月23日 (木)

pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? Season2 #1

前回のネタ振りから随分間があいてしまいました。m(_ _)m

pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? 」シリーズで_pga_max_sizeが固定値の様に見えてしまっているのですが、そのようになってしまった、"大きなミス"ってどこかわかりますか?

ってところ、わかりますかね。

実は、行く先々で pga_aggregate_targetとか _pga_max_sizeの値を覗いてみてて、あれ、自分のMacやPCで確かめた値と違う???何故ってことが数回あって、あ、そういことかと気付いたわけです。

答えから先に言うと、

Oracle10g R1までは確かに _pga_max_sizeは200MBで固定値だった。ところが、Oracle10g R2以降は、Oracleが内部で動的に変更する隠しパラメータになったということ。

そして、_pga_max_sizeをalter system文で変更してしまうと、Oracle10g R2以降では、その値は動的に変更されず、ユーザが設定した値で固定されてしまう。


ということ。


この影響で、私が実施したテストケースでは全て_pga_max_sizeは200MBのままで固定値のように見えていたということ。。

orz... まあ、隠しパラメータですから、どんな仕様変更があっても文句はいいません。>< はい。


では、早速、alter system文で値を設定してしまった _pga_max_sizeパラメータを元の状態に戻しましょう!

手順としては、Oracleインスタンス起動、spfileからpfileを作り、pfileから_pga_max_sizeの部分を削除、インスタンス停止、pfileでOracleインスタンス起動、spfile作って再起動って感じです。

とりあえず、Oracle10g R1で。

SYS> select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.1.0.3.0 - Prod
PL/SQL Release 10.1.0.3.0 - Production
CORE 10.1.0.3.0 Production
TNS for MacOS X Server: Version 10.1.0.3.0 - Production
NLSRTL Version 10.1.0.3.0 - Production

SYS> show parameter pga

NAME TYPE VALUE
------------------------------------ --------------------------------- ------------------------------
_pga_max_size big integer 200M
pga_aggregate_target big integer 100M

SYS> @pgastat

NAME size(MB)
------------------------------ ----------
aggregate PGA target parameter 100
aggregate PGA auto target 76.1923828
global memory bound 5

SYS>
SYS> create pfile from spfile;

ファイルが作成されました。

SYS> !cat $ORACLE_HOME/dbs/initxtiger.ora

・・・中略・・・

xtiger.__large_pool_size=4194304
xtiger.__shared_pool_size=104857600
*._pga_max_size=209715200
*.background_dump_dest='/Volumes/Discus/4oracle/oracle/u01/app/oracle/admin/xtiger/bdump'
*.compatible='10.1.0.2.0'

・・・中略・・・

SYS> edit $ORACLE_HOME/dbs/initxtiger.ora



*._pga_max_sizeの行を削除!
SYS> !cat $ORACLE_HOME/dbs/initxtiger.ora

・・・中略・・・

xtiger.__large_pool_size=4194304
xtiger.__shared_pool_size=104857600
*.background_dump_dest='/Volumes/Discus/4oracle/oracle/u01/app/oracle/admin/xtiger/bdump'
*.compatible='10.1.0.2.0'

・・・中略・・・

SYS> shutdown
データベースがクローズされました。
データベースがディスマウントされました。
ORACLEインスタンスがシャットダウンされました。
SYS>
SYS> startup pfile=$ORACLE_HOME/dbs/initxtiger.ora
ORACLEインスタンスが起動しました。

Total System Global Area 293601280 bytes
Fixed Size 778888 bytes
Variable Size 120331640 bytes
Database Buffers 171966464 bytes
Redo Buffers 524288 bytes
データベースがマウントされました。
データベースがオープンされました。

SYS> create spfile from pfile;

ファイルが作成されました。

SYS> shutdown
データベースがクローズされました。
データベースがディスマウントされました。
ORACLEインスタンスがシャットダウンされました。

SYS> startup
ORACLEインスタンスが起動しました。

Total System Global Area 293601280 bytes
Fixed Size 778888 bytes
Variable Size 120331640 bytes
Database Buffers 171966464 bytes
Redo Buffers 524288 bytes
データベースがマウントされました。
データベースがオープンされました。

SYS> show parameter pga

NAME TYPE VALUE
------------------------------------ --------------------------------- ------------------------------
pga_aggregate_target big integer 100M

SYS> @pgastat

NAME size(MB)
------------------------------ ----------
aggregate PGA target parameter 100
aggregate PGA auto target 76.3242188
global memory bound 5

SYS> @show_hidden_pga_param

KSPPINM KSPPSTVL KSPPSTDF
------------------------------ ------------------------------ ---------------------------
_pga_large_extent_size 1048576 TRUE
_pga_max_size 209715200 TRUE
_use_ism_for_pga TRUE TRUE
pga_aggregate_target 104857600 FALSE

SYS>


戻った〜。 show parameter pgaで 隠しパラメータである_pga_max_sizeパラメータが表示されているということは、その値がデフォルト値と同じ値であっても、そのパラメータの値は、ユーザがセットした値ということ。show parameterで _pga_max_sizeが表示されなくなったらOK。

ちなみに、 show_hidden_pga_param.sqlは以下のようなクエリ。

select
a.ksppinm
,b.ksppstvl
,b.ksppstdf
from
x$ksppi a join x$ksppcv b
on a.indx = b.indx
where
a.ksppinm like '%pga%'
order by
a.ksppinm
/

次回へつづく。


前回までのあらすじ・・・
Mac De Oracle なんですが、Windows(32bit)でのOracleな話
Mac De Oracle なんですが、Windows(32bit)でのOracleな話 #2
Mac De Oracle なんですが、Windows(32bit)でのOracleな話 #3
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #1
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #2
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #3
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #4
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #5
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #6
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #7
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #8
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #9
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #10
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #11
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #12
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #13
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #14
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #15
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #16
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #17
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #18
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? #19
_pga_max_sizeってOracle11gではどうなったっけ? という確認。
_pga_max_sizeってOracle11gではどうなったっけ? という確認。シーズン2

| | | コメント (0) | トラックバック (0)

2010年3月28日 (日)

32bitと64bitのOracle10gでも_pga_max_sizeの値は同じ。

2010/11/25追記
実は_pga_max_sizeの扱いがOracle10g R2以降ひっそりと変更されていた!という事実。Season2という後付けのタイトルで後日談を書いておきましたので次いでに見ておくとちょっとは幸せになるかも…
pga_aggregate_targetでPGA?、_pga_max_sizeでPGA? Season2 #1

バージョンはOracle10g ですが、Oracle10g R1までとOracle10g R2以降では32bit版と64bit版のPGA関連で違いがあるという話を聞いたので、暇な時に調べようかなというネタのタネ。

久々にMac De Oracleらしく、MacOSX版Oracle10gでございます :)


まずは、Oracle10g R1 for MacOSX Server (PowerPC) 。こちらは32bitのはず。v$sessionのpaddr列からも確認できるように32bitだね

SYS> select * from v$version;

BANNER
----------------------------------------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.1.0.3.0 - Prod
PL/SQL Release 10.1.0.3.0 - Production
CORE 10.1.0.3.0 Production
TNS for MacOS X Server: Version 10.1.0.3.0 - Production
NLSRTL Version 10.1.0.3.0 - Production

SYS> !file $ORACLE_HOME/bin/oracle
/Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tigerx/bin/oracle: setuid setgid Mach-O executable ppc

SYS> select paddr from v$session where username='SYS';

PADDR
--------
610F79E8

SYS> col ksppinm for a30
SYS> col ksppstvl for a30
SYS> l
1 select
2 a.ksppinm
3 ,b.ksppstvl
4 ,b.ksppstdf
5 from
6 x$ksppi a join x$ksppcv b
7 on a.indx = b.indx
8 and a.ksppinm like '%pga%'
9 order by
10* a.ksppinm
SYS> /

KSPPINM KSPPSTVL KSPPSTDF
------------------------------ ------------------------------ ---------------------------
_pga_large_extent_size 1048576 TRUE
_pga_max_size 209715200 TRUE
_use_ism_for_pga TRUE TRUE
pga_aggregate_target 96468992 FALSE

SYS>



Powerpc32

次ぎは、Oracle10g R2 for MacOSX Server(Intel x86-64)。 v$sessionのpaddr列からも64bitだと確認できます。


SYS> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Prod
PL/SQL Release 10.2.0.4.0 - Production
CORE 10.2.0.4.0 Production
TNS for MacOS X Server: Version 10.2.0.4.0 - Production
NLSRTL Version 10.2.0.4.0 - Production

SYS>
SYS> !file $ORACLE_HOME/bin/oracle
/Users/shared/u01/app/oracle/oracle/product/10.2.0/db_1/bin/oracle: Mach-O 64-bit executable x86_64

SYS> select paddr from v$session where username='SYS';

PADDR
----------------
0000000194664920

SYS>
SYS> l
1 select
2 a.ksppinm
3 ,b.ksppstvl
4 ,b.ksppstdf
5 from
6 x$ksppi a join x$ksppcv b
7 on a.indx = b.indx
8 and a.ksppinm like '%pga%'
9 order by
10* a.ksppinm
SYS> /

KSPPINM KSPPSTVL KSPPSTDF
------------------------------ ------------------------------ ---------
_pga_large_extent_size 1048576 TRUE
_pga_max_size 209715200 TRUE
_use_ism_for_pga TRUE TRUE
pga_aggregate_target 203423744 FALSE

SYS>


Intelcore2duo64


バナーには 64bitという表記は無いOracle10g R2 for MacOSX Serverですが、32bitのMacOSX版Oracle10g R2は存在しないのでMacOSXに限っては 64bit Productionの表示はないのかな? と勝ってに思っている。
32/64bitの両リリースのあるプラットフォームではバナーに64bit表記がなければ32bit版となっているが、そもそも32bit版がないのだから区別する必要はないということかな。

上記結果からは間違いなくOracle10g R2 for MacOSX Serverは、64bit版ですね! キッパリ! 

で、本当に知りたかったのはそれじゃなくて…

64bit版、Oracle10g R2でも _pga_max_sizeは200MBなんだよね!ってこと。 64bit版でメモリ沢山積んでても今のところこの値は変わってないよねってこと。
あとで、いろいろと遊ぶつもりなのでそのネタの事前確認なのであるw

| | | コメント (0) | トラックバック (0)

2009年5月18日 (月)

Leopard de Oracle10g R2 (Intel x86-64) #11 (APEX3.2と遊ぶ #4)

Oracle10g R2 10.2.0.4.0 for MacOSX (Intel x68-64)でAPEX3.2と遊ぶの第四話。

前回、Rosettaの力を借りて、PowerPC版のMacへインストールしたOracle HTTP Server + PL/SQL gatewayをIntel x86版のMacへHomeディレクトリごと移動してしまえば動作するだろう。(但し、構成ファイル等は手動で手直しする必要あり)と書いたが、試してみたところ上手く動作した。Rosetta やっぱり、すげー!(Rosettaを作ったTransitive社はIBMに買収された。

手順は長くなるので次回にするが、環境と動作したスナップショットを。。。。


クリックで拡大表示します。


Ohs_apex_version1

Ohs_apex_version2


環境

Oracle HTTP ServerとPL/SQL gatewayをインストールしたMac (PowerPC)
 ---- PowerMac G5 (PowerPC G5 Dual 2.7Ghz / MacOSX Tiger Server 10.4.11)

PowerPCへインストールしたOracle HTTP ServerとPL/SQL gatewayの移動先のMac (Intel x86)
 ---- MacBook Pro (Intel Core 2 Duo 2.2Ghz / MacOSX Leopard 10.5.6)


今日はここまで、次回へつづく。:)




バックナンバー

Oracle10g R2 for MacOSX (Intel x86-64) released !!!
Leopard de Oracle10g release 2 (Intel x86-64)
Leopard de Oracle10g R2 (Intel x86-64) #1
Leopard de Oracle10g R2 (Intel x86-64) #2
Leopard de Oracle10g R2 (Intel x86-64) #3 (ちょいと寄り道)
Leopard de Oracle10g R2 (Intel x86-64) #4 (Companion CD installation)
Leopard de Oracle10g R2 (Intel x86-64) #5 (dbstart and dbshut does not work!! But....)
Leopard de Oracle10g R2 (Intel x86-64) #6 (onsがバグっている?件..)
Leopard de Oracle10g R2 (Intel x86-64) #7 (iSQL*Plusのメッセージがものすごく怖い件)
Leopard de Oracle10g R2 (Intel x86-64) #8 - (APEX3.2と遊ぶ #1)
Leopard de Oracle10g R2 (Intel x86-64) #9 - (APEX3.2と遊ぶ #2)
Leopard de Oracle10g R2 (Intel x86-64) #10 (APEX3.2と遊ぶ #3)

| | | コメント (0) | トラックバック (0)

2006年9月28日 (木)

Mac De PL/SQL RSS Reader #7

さて、RSS ReaderをネタにDBMS_XMLDOMパッケージなどでも遊ぼうとしていたら、こんなの見つけた。



Oracle10g R1/R2の PL/SQL Package and Type ReferenceマニュアルによればDBMS_XMLDOM.HASATTRIBUTEファンクションの戻り値は、VARCHAR2となっている。(以下、マニュアルより抜粋)
HASATTRIBUTE Functions


DBMS_XMLDOM.HASATTRIBUTE(
elem IN DOMELEMENT,
name IN VARCHAR2)
RETURN VARCHAR2;

DBMS_XMLDOM.HASATTRIBUTE(
elem IN DOMELEMENT,
name IN VARCHAR2,
ns IN VARCHAR2)
RETURN VARCHAR2;


しかし、実際には、

SYS> spo xmldom_desc.log
SYS> desc dbms_xmldom

中略

SYS> spo off
SYS> !cat xmldom_desc.log | grep HASATTRIBUTE
FUNCTION HASATTRIBUTE RETURNS BOOLEAN
FUNCTION HASATTRIBUTE RETURNS BOOLEAN
FUNCTION HASATTRIBUTES RETURNS BOOLEAN
SYS>

ということで、DBMS_XMLDOM.HASATTRIBUTEファンクションの戻り値は、 BOOLEAN なので注意するべし。

さらに、DBMS_XMLDOM.HASATTRIBUTE()を使ってみると、Oracle10g 10.1.0.3.0, 10.2.0.2.0、それぞれで試してみたが、常に FALSE が返される。

ちなみに、DBMS_XMLDOM.GETATTRIBUTENODE()では、指定した属性ノードが正しく取り出せた。こちらが使えるので、とりあえず、なんとかなるか。。。

今後仕事で使う際には要注意なので、備忘録として記録しておく。(そのうちファンクションの問題共々、修正されるとは思うが。。。。)



聞いている曲:Japan - Gentoemen Take Polaroids - Taking Islands in Africa Japan - Gentlemen Take Polaroids - Taking Islands In Africa
Japan - Gentlemen Take Polaroids - Taking Islands In Africa

| | | コメント (0) | トラックバック (0)

2006年9月 6日 (水)

Mac De Oracle (PL/SQL De COMPRESS/UNCOMPRESS)

OTN JapanCodeTipsに、Mac De Oracle (PL/SQL De UNCOMPRESS)及び、Mac De Oracle (PL/SQL De COMPRESS)に掲載したコードとほぼ同じコードを投稿しました。

| | | コメント (0) | トラックバック (0)

2006年8月29日 (火)

Mac De Oracle (PL/SQL De COMPRESS)

解凍につづき、圧縮を試す。


まずは gzip するテキストファイルは前回準備しておいたものを利用する。このテキストファイルをcompressed_file.gzとして圧縮してみる。尚、UTL_COMPRESS.LZ_COMPRESS()では、圧縮レベルが1〜9あり、デフォルトは、6。最も圧縮率が高いのは、9。この例では、圧縮率=6(デフォルト)で圧縮する。

G5Server:˜ oracle$ ls -l
total 48096
中略
-rw-r--r-- 1 oracle oinstall 559 Aug 20 06:35 org.txt
中略
G5Server:˜ oracle$
G5Server:˜ oracle$ cat org.txt
操作上の注意
■ LZ* ファンクションによって戻された一時 LOB は、コール元が
DBMS_ LOB.FREETEMPORARY コールを使用して解放する必要があります。
■ LZ_COMPRESS* または LZ_UNCOMPRESS* に渡された BFILE は、
DBMS_LOB.FILEOPENでオープンする必要があります。
■ 特別な状況(入力がすでに圧縮されている場合)では、UTL_COMPRESS サブプログラムの
1 つで生成された出力が、入力と同じ大きさかまたは入力よりもわずかに大きくなる
ことがあります。
■ UTL_COMPRESS で圧縮したデータの出力は、1 つのファイル上の gzip(-n オプション を指定)/gunzip と
互換性があります。
G5Server:˜ oracle$

早速取りかかる。今回も Oracle SQL Developer 1.0 for MacOSXを利用する。

だ〜〜〜〜っと、前回のコードを少々修正して実行(無名PL/SQLブロックにしてあるが、ストアドプロシージャでもファンクションでも、パッケージで実装しても全く問題はない。尚、事前にディレクトリオブジェクトは作成してある。)
Macdecompress1_1

圧縮ファイル(compressed_file.gz)が正しく作成できたか確認する。

G5Server:˜ oracle$ ls -l
total 48112
中略
-rw-r--r-- 1 oracle oinstall 408 Aug 20 13:11 compressed_file.gz
-rw-r--r-- 1 oracle oinstall 559 Aug 20 06:35 org.txt
中略
G5Server:˜ oracle$
G5Server:˜ oracle$ gunzip -lt compressed_file.gz
compressed uncompressed ratio uncompressed_name
408 559 30.2% compressed_file
G5Server:˜ oracle$
G5Server:˜ oracle$ gunzip -c compressed_file.gz
操作上の注意
■ LZ* ファンクションによって戻された一時 LOB は、コール元が
DBMS_ LOB.FREETEMPORARY コールを使用して解放する必要があります。
■ LZ_COMPRESS* または LZ_UNCOMPRESS* に渡された BFILE は、
DBMS_LOB.FILEOPENでオープンする必要があります。
■ 特別な状況(入力がすでに圧縮されている場合)では、UTL_COMPRESS サブプログラムの
1 つで生成された出力が、入力と同じ大きさかまたは入力よりもわずかに大きくなる
ことがあります。
■ UTL_COMPRESS で圧縮したデータの出力は、1 つのファイル上の gzip(-n オプション を指定)/gunzip と
互換性があります。
G5Server:˜ oracle$

前述のように、gunzipで解凍してしまうのもよいのだが、ダブルクリックして解凍しちゃいましょう。すばらしいGUIがあるんですから。
Macdecompress2_1 Macdecompress3


以下に今回作成したコードを示す。

DECLARE
v_src_text_file BFILE;
v_compressed_blob BLOB;
v_directory_name VARCHAR2(30);
v_src_text_file_name VARCHAR2(510);
v_dest_file_name VARCHAR2(510);

PROCEDURE close_bfile
(
i_bfile IN OUT NOCOPY BFILE
)
IS
BEGIN
IF DBMS_LOB.ISOPEN(i_bfile) = 1 THEN
DBMS_LOB.CLOSE(i_bfile);
END IF;
END close_bfile;

PROCEDURE write_blob_to_file
(
i_directory_name IN VARCHAR2,
i_file_name IN VARCHAR2,
i_src_blob IN OUT NOCOPY BLOB
)
IS
v_file UTL_FILE.FILE_TYPE;
BEGIN
v_file := UTL_FILE.FOPEN(
UPPER(i_directory_name),
i_file_name,
'wb',
32767
);

-- ファイルへ書き出すBLOBはオープンされていることを前提とする
DECLARE
c_chunk_size CONSTANT PLS_INTEGER := 32767;

v_buffer RAW(32767);
v_amount PLS_INTEGER := c_chunk_size;
v_num_of_chunk PLS_INTEGER;
BEGIN
v_num_of_chunk := CEIL(DBMS_LOB.GETLENGTH(i_src_blob)/c_chunk_size);
FOR chunk# IN 1..v_num_of_chunk LOOP
DBMS_LOB.READ(
i_src_blob,
v_amount,
(c_chunk_size * (chunk# - 1)) + 1, /*offset*/
v_buffer
);
UTL_FILE.PUT_RAW(v_file, v_buffer, TRUE);
END LOOP;
END;

UTL_FILE.FCLOSE(v_file);
END write_blob_to_file;
--
BEGIN
-- ディレクトリ名の設定
v_directory_name := 'MYDIR';
-- テキストファイル名
v_src_text_file_name := 'org.txt';
-- 出力ファイル名
v_dest_file_name := 'compressed_file.gz';

DBMS_OUTPUT.PUT_LINE('========== compress start ==========');

-- テキストファイルをBFILEとして開く。
v_src_text_file
:= BFILENAME(UPPER(v_directory_name), v_src_text_file_name);
DBMS_LOB.OPEN(v_src_text_file);

-- BFILEを圧縮し、一時BLOBへ (圧縮品質はデフォルトで圧縮する)
v_compressed_blob := UTL_COMPRESS.LZ_COMPRESS(v_src_text_file);

-- BLOB(圧縮済み)を書き出す
write_blob_to_file(
UPPER(v_directory_name),
v_dest_file_name,
v_compressed_blob
);

-- 一時LOBの解放及び、BFILEのクローズ
DBMS_LOB.FREETEMPORARY(v_compressed_blob);
close_bfile(v_src_text_file);

DBMS_OUTPUT.PUT_LINE('========== compress end ==========');

EXCEPTION
WHEN OTHERS THEN
-- 一時LOBの解放及び、BFILEのクローズ
DBMS_LOB.FREETEMPORARY(v_compressed_blob);
close_bfile(v_src_text_file);
RAISE;
END;
/

OTN JapanCodeTipsに公開してあります。
聞いている曲:
KraftWerk - Minimum - Maximum (live) Kraftwerk - Minimum - Maximum (Live)
Kraftwerk - Minimum - Maximum (Live)

| | | コメント (2) | トラックバック (0)

2006年8月28日 (月)

Mac De Oracle (PL/SQL De UNCOMPRESS)

Oracle10g R1から UTL_COMPRESSパッケージという、PL/SQLでデータの圧縮/解凍を行う為のパッケージが提供されているのをご存知だろうか?

恐らく、大きなデータを圧縮してBLOBとしてデータベースに格納し、取り出す時に解凍するというのが一般的な利用方法なのではないかと思うのだが、Mac De Oracle としては、そのまま試すのでは面白くない!
ということで、UTL_FILEパッケージを利用し、ディレクトリオブジェクトにある圧縮ファイルを解凍したり、テキストファイルを圧縮してみることにする。さて、うまくいきますかどうか。。。
尚、BLOBをディレクトリオブジェクト以下に書き出す方法は、PL/SQL De Phython Challengeでも利用した方法である。以前はコードを掲載していなかったが、今回は、それに近いコードも載せることにする。
(UTL_FILEパッケージでディレクトリオブジェクト以下にあるファイルを読み書きするには、Oracle9i R2以降が必要である。)

マニュアルにも書いてあるが、UTL_COMPRESSの圧縮、解凍は、gzip/gunzipと互換があるということなので素直に信じて試してみる!

まずは gzip するテキストファイルの準備から。
以下のようなテキストファイルを用意する。テキストファイルの内容は、「Oracle10g R1 PL/SQL タイプ及びパッケージリファレンス」のUTL_COMPRESSパッケージの解説を一部を引用することにした。(テキストファイルの文字コードは、SJIS、データベースキャラクタセットは、JA16SJISTILDEである。)

操作上の注意 
■ LZ* ファンクションによって戻された一時 LOB は、コール元が
DBMS_ LOB.FREETEMPORARY コールを使用して解放する必要があります。
■ LZ_COMPRESS* または LZ_UNCOMPRESS* に渡された BFILE は、
DBMS_LOB.FILEOPENでオープンする必要があります。
■ 特別な状況(入力がすでに圧縮されている場合)では、UTL_COMPRESS サブプログラムの
1 つで生成された出力が、入力と同じ大きさかまたは入力よりもわずかに大きくなる
ことがあります。
■ UTL_COMPRESS で圧縮したデータの出力は、1 つのファイル上の gzip(-n オプション を指定)/gunzip と
互換性があります。

Last login: Mon Aug 19 16:42:12 on ttyp1
Welcome to Darwin!
G5Server:˜ oracle$ gzip -cvn org.txt > org.gz
org.txt: 30.2%
G5Server:˜ oracle$ gzip -l org.gz
compressed uncompressed ratio uncompressed_name
408 559 30.2% org
G5Server:˜ oracle$ ls -l
total 48096
中略
-rw-r--r-- 1 oracle oinstall 408 Aug 20 06:35 org.gz
-rw-r--r-- 1 oracle oinstall 559 Aug 20 06:35 org.txt
中略
G5Server:˜ oracle$

準備は整ったので早速取りかかる。今回も Oracle SQL Developer 1.0 for MacOSXを利用する。


だ〜〜〜〜っと、コード書をきなぐり、即、実行!(無名PL/SQLブロックにしてあるが、ストアドプロシージャでもファンクションでも、パッケージで実装しても全く問題はない。尚、事前にディレクトリオブジェクトは作成してあり、無名PL/SQLブロックを実行するユーザへ読み込み権限と書き込み権限を付与してある。)
Macdecompress1


圧縮前のテキストファイル(org.txt)と、org.gzをUTL_COMPRESS.LZ_UNCOMPRESS()で解凍したファイル(uncompressed_file.txt)が同じ内容であることを確認する。(diffを取って見せるのがいいのだが、それだけだとMacOSXの奇麗なGUIが見れないので、ファイルを開いて確認する。)
Macdecompress2


以下に今回作成したコードを示す。

DECLARE
v_src_gzipped_file BFILE;
v_uncompressed_blob BLOB;
v_directory_name VARCHAR2(30);
v_src_gzipped_file_name VARCHAR2(510);
v_dest_file_name VARCHAR2(510);

PROCEDURE close_bfile
(
i_bfile IN OUT NOCOPY BFILE
)
IS
BEGIN
IF DBMS_LOB.ISOPEN(i_bfile) = 1 THEN
DBMS_LOB.CLOSE(i_bfile);
END IF;
END close_bfile;

PROCEDURE write_blob_to_file
(
i_directory_name IN VARCHAR2,
i_file_name IN VARCHAR2,
i_src_blob IN OUT NOCOPY BLOB
)
IS
v_file UTL_FILE.FILE_TYPE;
BEGIN
v_file := UTL_FILE.FOPEN(
UPPER(i_directory_name),
i_file_name,
'wb',
32767
);

-- ファイルへ書き出すBLOBはオープンされていることを前提とする
DECLARE
c_chunk_size CONSTANT PLS_INTEGER := 32767;

v_buffer RAW(32767);
v_amount PLS_INTEGER := c_chunk_size;
v_num_of_chunk PLS_INTEGER;
BEGIN
v_num_of_chunk := CEIL(DBMS_LOB.GETLENGTH(i_src_blob)/c_chunk_size);
FOR chunk# IN 1..v_num_of_chunk LOOP
DBMS_LOB.READ(
i_src_blob,
v_amount,
(c_chunk_size * (chunk# - 1)) + 1, /*offet*/
v_buffer
);
UTL_FILE.PUT_RAW(v_file, v_buffer, TRUE);
END LOOP;
END;

UTL_FILE.FCLOSE(v_file);
END write_blob_to_file;
--
BEGIN
-- ディレクトリ名の設定
v_directory_name := 'MYDIR';
-- 圧縮ファイル名
v_src_gzipped_file_name := 'org.gz';
-- 解凍ファイル名
v_dest_file_name := 'uncompressed_file.txt';

DBMS_OUTPUT.PUT_LINE('========== uncompress start ==========');

-- 圧縮ファイルをBFILEとして取り込む
v_src_gzipped_file
:= BFILENAME(UPPER(v_directory_name), v_src_gzipped_file_name);
DBMS_LOB.OPEN(v_src_gzipped_file);

-- BFILEを解凍し一時BLOBへ
v_uncompressed_blob := UTL_COMPRESS.LZ_UNCOMPRESS(v_src_gzipped_file);

-- BLOBを書き出す
write_blob_to_file(
UPPER(v_directory_name),
v_dest_file_name,
v_uncompressed_blob
);

-- 一時LOBの解放及び、BFILEのクローズ
DBMS_LOB.FREETEMPORARY(v_uncompressed_blob);
close_bfile(v_src_gzipped_file);

DBMS_OUTPUT.PUT_LINE('========== uncompress end ==========');

EXCEPTION
WHEN OTHERS THEN
-- 一時LOBの解放及び、BFILEのクローズ
DBMS_LOB.FREETEMPORARY(v_uncompressed_blob);
close_bfile(v_src_gzipped_file);
RAISE;
END;
/

さて、次回は、テキストファイルを読み込み圧縮してみることにする。

OTN JapanCodeTipsに公開してあります。

聞いている曲:
Marcus Miller - Silver Rain
Marcus Miller - Silver Rain - Silver Rain (Featuring Eric Clapton)

| | | コメント (0) | トラックバック (0)

2006年8月14日 (月)

Mac De PL/SQL RSS Reader #6

つづきです。
PL/SQLで日本語対応RSS Readerが作れる事が確認できたので HTMLDB 2.0 に組み込み確認する。

Oracle HTMLDB 2.0で PL/SQL RSS Reader作成中のスナップショットをQuickTimeムービーにしました。
再生には、Apple QuickTimeプラグインが必要です。


サウンドトラックの無い、ファイルサイズ:2.3MB版のQuickTimeムービーはこちらから。



Apple iLifeのGarage Bandでサウンドトラックを付けたバージョン。ファイルサイズ:38MB版QuickTimeムービーはこちら。


聞いている曲:
David Bowie - TVC 15 David Bowie - Station to Station - TVC 15

| | | コメント (0) | トラックバック (0)

2006年8月13日 (日)

Mac De PL/SQL RSS Reader #5

前回のつづきです。
当初のからmegawattさんのRSS 0.91フォーマットを対象にしているためその他のRSSフォーマットやATOMには対応していない。元ネタのようにXSLTスタイルシートを利用するのも良いだろう。
今回は、「元ネタの通りの方法で、日本語が文字化け無く処理できるのだろうか?」 という点を確認するということが目的であるため複数のRSSフォーマットに対応するつもりは無い。そのウチ試す予定だが。

ということで、最後に、今までほったらかしていた Oracle HTMLDB 2.0 を利用して RSS Reader を組み込んでみることにした。
Oracle HTMLDB 2.0については以前の記事を参考にして貰いたい。



HTMLDBに組み込んだコードはこれ。

DECLARE
TYPE rss_type IS RECORD
(
title VARCHAR2(2000),
link VARCHAR2(200)
);
v_rss_item rss_type;
v_rss_empty_item rss_type;

v_url VARCHAR2(32767)
:= 'http://megawatt.blogdns.net/blog/rdf91_xml';

v_myParser DBMS_XMLPARSER.Parser;
v_rssDoc DBMS_XMLDOM.DomDocument;
v_itemNode DBMS_XMLDOM.DomNode;
v_childnode DBMS_XMLDOM.DomNode;
v_rssEntryList DBMS_XMLDOM.DomNodeList;
v_rssItemFields DBMS_XMLDOM.DomNodeList;
v_childNodeText VARCHAR2(32767);

v_req UTL_HTTP.REQ;
v_resp UTL_HTTP.RESP;

v_source VARCHAR2(1024);
v_tempSourceClob CLOB;
v_tempXMLTYPE XMLTYPE;


PROCEDURE report_rss_item(p_rss_item IN rss_type)
IS
BEGIN
HTP.TABLEROWOPEN();
HTP.TABLEDATA(
'<a href="'
|| p_rss_item.link
|| '" style="color:#FF0000" target="_blank">'
|| p_rss_item.title
|| '</a>'
);
HTP.TABLEROWCLOSE();

EXCEPTION
WHEN OTHERS THEN
HTP.PRINT('Error occured in report_rss_item internal procedure');
RAISE;
END report_rss_item;

--****************************************************************************
-- Main procedure
--****************************************************************************
BEGIN
v_req := UTL_HTTP.BEGIN_REQUEST(v_url);
UTL_HTTP.SET_HEADER(v_req, 'User-Agent', 'Oracle UTL_HTTP/Oracle10g R1');
UTL_HTTP.SET_HEADER(v_req, 'Content-Type', 'text/xml;charset=UTF-8');
v_resp := UTL_HTTP.GET_RESPONSE(v_req);

DBMS_LOB.CREATETEMPORARY(v_tempSourceClob, FALSE);
BEGIN
LOOP
UTL_HTTP.READ_LINE(v_resp, v_source, true);

-- 改行コード強制的に付加。
-- xml_println()でDBMS_OUTPUT.PUT_LINE()が、最大255文字までしか
-- 表示できないことへの一時的な対策。(試しているサイトについてはこれで
-- 回避できているので今のところはこのままで。)
v_source := v_source || UTL_TCP.CRLF;
DBMS_LOB.WRITEAPPEND(v_tempSourceClob, LENGTH(v_source), v_source);

END LOOP;
EXCEPTION
WHEN UTL_HTTP.END_OF_BODY THEN
UTL_HTTP.END_RESPONSE(v_resp);
END;

v_myParser := DBMS_XMLPARSER.NEWPARSER();
DBMS_XMLPARSER.PARSECLOB(v_myParser, v_tempSourceClob);
v_rssDoc := DBMS_XMLPARSER.GETDOCUMENT(v_myParser);
v_tempXMLType := DBMS_XMLDOM.GETXMLTYPE(v_rssDoc);
v_rssEntryList := DBMS_XMLDOM.GETELEMENTSBYTAGNAME(v_rssDoc, 'item');
v_rss_item := v_rss_empty_item;

HTP.TABLEOPEN();
HTP.TABLEROWOPEN();
HTP.TABLEHEADER(
cvalue => v_tempXMLType.EXTRACT('/rss/channel/title/text()').GETSTRINGVAL
|| ' - most recent '
|| DBMS_XMLDOM.GETLENGTH(v_rssEntryList)
|| ' articles:',
cattributes => 'style="font-size:18px"',
calign => 'align="left"'
);
HTP.TABLEROWCLOSE();

FOR i IN 1..DBMS_XMLDOM.GETLENGTH(v_rssEntryList) LOOP
v_itemNode := DBMS_XMLDOM.ITEM(v_rssEntryList, i-1);
v_rssItemFields := DBMS_XMLDOM.GETCHILDNODES(v_itemNode);

FOR j IN 1..DBMS_XMLDOM.GETLENGTH(v_rssItemFields) LOOP
v_childnode := DBMS_XMLDOM.ITEM(v_rssItemFields, j-1);
v_childNodeText := DBMS_XMLDOM.GETNODEVALUE(
DBMS_XMLDOM.GETFIRSTCHILD(v_childnode)
);

CASE DBMS_XMLDOM.GETNODENAME(v_childnode)
WHEN 'title' THEN
v_rss_item.title := v_childNodeText;

WHEN 'link' THEN
v_rss_item.link := v_childNodeText;

ELSE
NULL;
END CASE;
END LOOP;
report_rss_item(v_rss_item);
END LOOP;

HTP.TABLECLOSE();
DBMS_LOB.FREETEMPORARY(v_tempSourceClob);
DBMS_XMLPARSER.FREEPARSER(v_myParser);

EXCEPTION
WHEN OTHERS THEN
HTP.PRINT(
'Main Procedure:'
|| sqlerrm()
);
RAISE;
END;



前回のストアドプロシージャのロジックとの違いはあまり無いが、無名PL/SQLブロックとして組み込むことと、DBMS_OUTPUTパッケージを利用している部分を、HTPパッケージを利用するように変更しなければならない。(やっつけ仕事的なコードになってしまったなが、文字化け回避の方法が見えればOKなので他には目をつぶってくださいませ。。。)

尚、
HTPパッケージについては、PL/SQL パッケージ・プロシージャおよびタイプ・リファレンス
HTMLDB 2.0についてはOracle HTMLDB 2.0(英語)や、HTMLDB 2.0のオンラインヘルプなどが参考になるだろう。
#今回は、オンラインヘルプしか利用ませんでした。そんな程度でも作れるくらい簡単です。。。


次回は、HTMLDB 2.0 に前述の無名PL/SQLブロックを組み込んで試すことにする。




これから見ようとしているDVD:
随分前、こんな記事を書いたが、なんと ザ・インターネット2がリリースされていた。
邦題:インターネットの続編?のようなのだが。。。。不覚にも全くしらなかった。でも主演はサンドラブロックではなさそうだな。。。そういえば、ザ・インターネットが公開されたのは1996年。10年も経ったのか・・・と。


ところで、インターネット2っていうと、次世代インターネットを指していたりする。


##############################
2006/08/13
ザ・インターネット2見ましたが、ぜんぜん面白くない。ザ・インターネットの続編だなんて、とんでもない無いですね。
ザ・インターネットの延長線上にあると思ってみてしまうとがっかりするので、完全に別ものと思って見てくださいね。

| | | コメント (0) | トラックバック (0)

2006年8月 9日 (水)

Mac De PL/SQL RSS Reader #4

前回のつづきです。
前回までで文字化けを回避できることが確認できたので、本題RSSリーダーの元ネタで試してみることにする。
尚、オリジナルになるべく近い形にしてある。(対象は、megawattさんRSS 0.91フォーマット)

まずは、結果から。(いつものように、Oracle SQL Developer 1.0 for MacOSXを使ってます)
Sqldevok



データベースOracle10g R1 grasscatfishに接続中です。
begin...
====================
メガ放談 - most recent 15 articles:
====================
TITLE: ギザ耳は地域猫の証し
URL : http://megawatt.blogdns.net/blog/254
—————————————-

TITLE: 亀田家親子夏休み日記
URL : http://megawatt.blogdns.net/blog/253
—————————————-

TITLE: 社会保険事務所に行ってきた
URL : http://megawatt.blogdns.net/blog/252
—————————————-

TITLE: 重なるときは重なる Part2
URL : http://megawatt.blogdns.net/blog/251
—————————————-

TITLE: 重なるときは重なる
URL : http://megawatt.blogdns.net/blog/250
—————————————-

TITLE: うしろすがた
URL : http://megawatt.blogdns.net/blog/249
—————————————-

TITLE: 猫のための写真講座/2006年度前期・4
URL : http://megawatt.blogdns.net/blog/248
—————————————-

TITLE: ワイン100mlが80キロカロリー!!
URL : http://megawatt.blogdns.net/blog/247
—————————————-

TITLE: はっちゃんではないはっちゃん
URL : http://megawatt.blogdns.net/blog/246
—————————————-

TITLE: ちょっと、走ってる
URL : http://megawatt.blogdns.net/blog/245
—————————————-

TITLE: 命名、じみへん
URL : http://megawatt.blogdns.net/blog/244
—————————————-

TITLE: 猫まんが at門前仲町
URL : http://megawatt.blogdns.net/blog/243
—————————————-

TITLE: 猫を拾った日
URL : http://megawatt.blogdns.net/blog/242
—————————————-

TITLE: お飲物なににしますか?
URL : http://megawatt.blogdns.net/blog/241
—————————————-

TITLE: 門前仲町・深川不動堂
URL : http://megawatt.blogdns.net/blog/240
—————————————-

...End
プロセス終了。
データベースOracle10g R1 glasscatfishから切断中です。

以下、プロシージャのソース。
比較し易いように、オリジナルのソースになるべく近い形式にしてある。

CREATE OR REPLACE PROCEDURE RSS_FEED_READER
(
i_url IN VARCHAR2
)
AS
--============ TYPEs/VARIABLEs ===============================================
TYPE rss_type IS RECORD
(
title VARCHAR2(2000),
link VARCHAR2(200),
pubDate VARCHAR2(200),
category VARCHAR2(500),
description VARCHAR2(4000)
);
v_rss_item rss_type;
v_rss_empty_item rss_type; -- v_rss_item初期化用

v_url VARCHAR2(32767);

-- XML PARSER
v_myParser DBMS_XMLPARSER.Parser;

-- RSSまたは、ATOMフォーマットのDOM
v_rssDoc DBMS_XMLDOM.DomDocument;

v_itemNode DBMS_XMLDOM.DomNode;
v_childnode DBMS_XMLDOM.DomNode;
v_rssEntryList DBMS_XMLDOM.DomNodeList;
v_rssItemFields DBMS_XMLDOM.DomNodeList;
v_childNodeText VARCHAR2(32767);

-- for UTL_HTTP
v_req UTL_HTTP.REQ;
v_resp UTL_HTTP.RESP;
-- HTTP経由でRSS/ATOMソースを取り込むためのワーク
v_source VARCHAR2(1024);
v_tempSourceClob CLOB;

-- RSS/ATOMをXMLTYPEで扱うためのワーク
v_tempXMLTYPE XMLTYPE;

--========== Internal PROCEDUREs/FUNCTIONs ===================================
--
--****************************************************************************
--* VARCHAR2の文字列を最大で255文字または、改行コード毎にプリントする内部プロシージャ
--*
--* NOTE:
--* Oracle10g R2では、DBMS_OUTPUT.PUT_LINEプロシージャの255文字制限がないため、
--* 255文字毎に分割出力する必要はなくなる
--****************************************************************************
PROCEDURE println
(
i_text IN VARCHAR2
)
IS
v_src VARCHAR2(32767);
v_tempStr VARCHAR2(32767);
BEGIN
v_src := i_text;
IF INSTR(v_src, UTL_TCP.CRLF) <> 0 THEN
v_tempStr := SUBSTR(v_src, 1, INSTR(v_src, UTL_TCP.CRLF)-1);
v_src := SUBSTR(v_src, INSTR(v_src, UTL_TCP.CRLF)+LENGTH(UTL_TCP.CRLF));
ELSE
v_tempStr := v_src;
END IF;

WHILE v_tempStr IS NOT NULL LOOP
IF LENGTH(v_tempStr)> 255 THEN
FOR i IN 1..(TRUNC(LENGTH(v_tempStr)/255)+1) LOOP
DBMS_OUTPUT.PUT_LINE(SUBSTR(v_tempStr,1+ 255*(i-1),255));
END LOOP;
ELSE
DBMS_OUTPUT.PUT_LINE(v_tempStr);
END IF;

IF INSTR(v_src, UTL_TCP.CRLF) <> 0 THEN
v_tempStr := SUBSTR(v_src, 1, INSTR(v_src, UTL_TCP.CRLF)-1);
v_src := SUBSTR(v_src, INSTR(v_src, UTL_TCP.CRLF)+LENGTH(UTL_TCP.CRLF));
ELSE
EXIT;
END IF;
END LOOP;

EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error Occured : println(VARCHAR2) internal procedure.');
DBMS_OUTPUT.PUT_LINE(sqlerrm());
RAISE;
END println;


PROCEDURE report_rss_item(p_rss_item IN rss_type)
IS
BEGIN
println('TITLE: '||p_rss_item.title);
println('URL : '||p_rss_item.link);

IF p_rss_item.pubDate IS NOT NULL THEN
println('Published on: '||p_rss_item.pubDate);
END IF;

IF p_rss_item.category IS NOT NULL THEN
println('Category: '||p_rss_item.category);
END IF;

IF p_rss_item.description IS NOT NULL THEN
println('==');
println('Summary: '||p_rss_item.description);
END IF;

println('—————————————-');
println(' ');

EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error occured : report_rss_item internal procedure');
DBMS_OUTPUT.PUT_LINE(sqlerrm());
RAISE;
END report_rss_item;

--****************************************************************************
--* Main procedure
--****************************************************************************
BEGIN
DBMS_OUTPUT.ENABLE(200000);
println('begin...');

v_url := i_url;
IF v_url IS NULL THEN
RAISE_APPLICATION_ERROR(-20000, 'URLを指定してください。');
END IF;

v_req := UTL_HTTP.BEGIN_REQUEST(v_url);
UTL_HTTP.SET_HEADER(v_req, 'User-Agent', 'Oracle UTL_HTTP/Oracle10g R1');
UTL_HTTP.SET_HEADER(v_req, 'Content-Type', 'text/xml;charset=UTF-8');
v_resp := UTL_HTTP.GET_RESPONSE(v_req);

-- RSSソースを一時CLOBへ書き出す
DBMS_LOB.CREATETEMPORARY(v_tempSourceClob, FALSE);
BEGIN
LOOP
UTL_HTTP.READ_LINE(v_resp, v_source, true);

-- 改行コード強制的に付加。
-- xml_println()でDBMS_OUTPUT.PUT_LINE()が、最大255文字までしか
-- 表示できないことへの一時的な対策。(試しているサイトについてはこれで
-- 回避できているので今のところはこのままで。)
v_source := v_source || UTL_TCP.CRLF;
DBMS_LOB.WRITEAPPEND(v_tempSourceClob, LENGTH(v_source), v_source);
END LOOP;
EXCEPTION
WHEN UTL_HTTP.END_OF_BODY THEN
UTL_HTTP.END_RESPONSE(v_resp);
END;

println('====================');
v_myParser := DBMS_XMLPARSER.NEWPARSER();
DBMS_XMLPARSER.PARSECLOB(v_myParser, v_tempSourceClob);
v_rssDoc := DBMS_XMLPARSER.GETDOCUMENT(v_myParser);
v_tempXMLType := DBMS_XMLDOM.GETXMLTYPE(v_rssDoc);
v_rssEntryList := DBMS_XMLDOM.GETELEMENTSBYTAGNAME(v_rssDoc, 'item');
v_rss_item := v_rss_empty_item;

println
(
v_tempXMLType.EXTRACT('/rss/channel/title/text()').GETSTRINGVAL
|| ' - most recent '
|| DBMS_XMLDOM.GETLENGTH(v_rssEntryList)
|| ' articles:'
);
println('====================');

FOR i IN 1..DBMS_XMLDOM.GETLENGTH(v_rssEntryList) LOOP
v_itemNode := DBMS_XMLDOM.ITEM(v_rssEntryList, i-1);
v_rssItemFields := DBMS_XMLDOM.GETCHILDNODES(v_itemNode);

FOR j IN 1..DBMS_XMLDOM.GETLENGTH(v_rssItemFields) LOOP
v_childnode := DBMS_XMLDOM.ITEM(v_rssItemFields, j-1);
v_childNodeText := DBMS_XMLDOM.GETNODEVALUE(
DBMS_XMLDOM.GETFIRSTCHILD(v_childnode)
);

CASE DBMS_XMLDOM.GETNODENAME(v_childnode)
WHEN 'title' THEN
v_rss_item.title := v_childNodeText;

WHEN 'link' THEN
v_rss_item.link := v_childNodeText;

WHEN 'published' THEN
v_rss_item.pubDate := v_childNodeText;

WHEN 'category' THEN
v_rss_item.category := v_childNodeText;

WHEN 'description' THEN
v_rss_item.description := v_childNodeText;

ELSE
NULL;
END CASE;
END LOOP;

report_rss_item(v_rss_item);
END LOOP;

DBMS_LOB.FREETEMPORARY(v_tempSourceClob);
DBMS_XMLPARSER.FREEPARSER(v_myParser);

println('...End');

EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(
'Main Procedure:'
|| sqlerrm()
);
RAISE;

END RSS_FEED_READER;


今聞いている曲:
これらの曲がリリースされた時期から随分経っているが、種々の問題は残されたままのような気がする。と考えつつ。。。

ALCATRAZZ -- Hiroshima mon amour

Human Leage - The LebanonThe Human League - Hysteria - The Lebanon
The Human League - Hysteria - The Lebanon

| | | コメント (0) | トラックバック (0)

2006年8月 8日 (火)

Mac De PL/SQL RSS Reader #3

前回のつづきです。
さて、文字化けを回避する方法はないかと考えてみた。
URL指定で、Oracle10g R1のDBMS_XMLPARSERパッケージのパーサーでパースする場合、裏で行われて言うHTTPで正しくエンコーディングされていないのが原因でだろうと考え、試しにUTL_HTTPパッケージを使いRSSソースを取得してみることにした。

尚、DBMS_XMLPARDERパッケージ、DBMS_XMLDOMパッケージ、UTL_HTTPパッケージ、UTL_TCPパッケージの詳細については、「PL/SQL パッケージ・プロシージャおよびタイプ・リファレンス」を参照のこと。

まずは、結果から。
以下のように、HTTPで取得したRSSを表示すると文字化けは発生しなかった。(思った通り!)

データベースOracle10g R1 glasscatfishに接続中です。<br>
begin...
====================
DBMS_XMLPARSERバージョン:10.1.0.2.0
DBMS_XMLDOMバージョン   :

<rss version="0.91">
  <channel>
    <title>メガ放談</title>
    <link>http://megawatt.blogdns.net/blog</link>
    <description>A Weblog Product for Zope</description>
    <item>
      <title>亀田家親子夏休み日記</title>
      <link>http://megawatt.blogdns.net/blog/253</link>
    </item>
    <item>
      <title>社会保険事務所に行ってきた</title>
      <link>http://megawatt.blogdns.net/blog/252</link>
    </item>
    <item>
      <title>重なるときは重なる Part2</title>
      <link>http://megawatt.blogdns.net/blog/251</link>
    </item>
    <item>
      <title>重なるときは重なる</title>
      <link>http://megawatt.blogdns.net/blog/250</link>
    </item>
    <item>
      <title>うしろすがた</title>
      <link>http://megawatt.blogdns.net/blog/249</link>
    </item>
    <item>
      <title>猫のための写真講座/2006年度前期・4</title>
      <link>http://megawatt.blogdns.net/blog/248</link>
    </item>
    <item>
      <title>ワイン100mlが80キロカロリー!!</title>
      <link>http://megawatt.blogdns.net/blog/247</link>
    </item>
    <item>
      <title>はっちゃんではないはっちゃん</title>
      <link>http://megawatt.blogdns.net/blog/246</link>
    </item>
    <item>
      <title>ちょっと、走ってる</title>
      <link>http://megawatt.blogdns.net/blog/245</link>
    </item>
    <item>
      <title>命名、じみへん</title>
      <link>http://megawatt.blogdns.net/blog/244</link>
    </item>
    <item>
      <title>猫まんが at門前仲町</title>
      <link>http://megawatt.blogdns.net/blog/243</link>
    </item>
    <item>
      <title>猫を拾った日</title>
      <link>http://megawatt.blogdns.net/blog/242</link>
    </item>
    <item>
      <title>お飲物なににしますか?</title>
      <link>http://megawatt.blogdns.net/blog/241</link>
    </item>
    <item>
      <title>門前仲町・深川不動堂</title>
      <link>http://megawatt.blogdns.net/blog/240</link>
    </item>
    <item>
      <title>う〜ん、まずい。</title>
      <link>http://megawatt.blogdns.net/blog/239</link>
    </item>
    <item>
      <title>短歌熱</title>
      <link>http://megawatt.blogdns.net/blog/238</link>
    </item>
  </channel>
</rss>
====================

...End
プロセス終了。<br>
データベースOracle10g R1 glasscatfishから切断中です。<br>

以下、変更後のプロシージャのソースを示す。
変更点は、
DBMS_XMLPARSERパッケージのパーサーで、URL直指定でパースするのではなく、HTTP経由でCLOBにRSSソースを取り込み、CLOBをパースするようにした。
XMLをプリントする内部プロシージャも変更し、println(CLOB)からxml_println(XMLTYPE)へ変更した。(XMLTYPEにしておいたほうがなにかと便利なので。尚、元ネタは、ここ) 

CREATE OR REPLACE PROCEDURE RSS_FEED_READER
(
  i_url IN VARCHAR2
)
AS
  --============ TYPEs/VARIABLEs ===============================================
  TYPE rss_type IS RECORD
  (
    title       VARCHAR2(2000),
    link        VARCHAR2(200),
    pubDate     VARCHAR2(200),
    category    VARCHAR2(500),
    description VARCHAR2(4000)
  );
  v_rss_item        rss_type;
  v_rss_empty_item  rss_type; -- v_rss_item初期化用

  v_url             VARCHAR2(32767);

 
    -- XML PARSER
  v_myParser        DBMS_XMLPARSER.Parser;

  -- RSSまたは、ATOMフォーマットのDOM
  v_rssDoc          DBMS_XMLDOM.DomDocument; 

    -- for UTL_HTTP
  v_req             UTL_HTTP.REQ;
  v_resp            UTL_HTTP.RESP;

  -- HTTP経由でRSS/ATOMソースを取り込むためのワーク
  v_source          VARCHAR2(1024);
  v_tempSourceClob  CLOB;
         
   --========== Internal PROCEDUREs/FUNCTIONs ===================================
  --
  --****************************************************************************
  --* VARCHAR2の文字列を最大で255文字または、改行コード毎にプリントする内部プロシージャ
  --*
  --* NOTE:
  --* Oracle10g R2では、DBMS_OUTPUT.PUT_LINEプロシージャの255文字制限が緩和され32767文字まで出力できるようになるためがないため
  --* 255文字毎に分割出力する必要はなくなるなぁ。
  --****************************************************************************
  PROCEDURE println
  (
    i_text IN VARCHAR2
  )
  IS
    v_src     VARCHAR2(32767);
    v_tempStr VARCHAR2(32767);
  BEGIN
    v_src := i_text;
    IF INSTR(v_src, UTL_TCP.CRLF) <> 0 THEN
      v_tempStr := SUBSTR(v_src, 1, INSTR(v_src, UTL_TCP.CRLF)-1);
      v_src := SUBSTR(v_src, INSTR(v_src, UTL_TCP.CRLF)+LENGTH(UTL_TCP.CRLF));
    ELSE
      v_tempStr := v_src;
    END IF;
   
    WHILE v_tempStr IS NOT NULL LOOP
      IF LENGTH(v_tempStr)> 255 THEN
        FOR i IN 1..(TRUNC(LENGTH(v_tempStr)/255)+1) LOOP
          DBMS_OUTPUT.PUT_LINE(SUBSTR(v_tempStr,1+ 255*(i-1),255));
        END LOOP;
      ELSE
        DBMS_OUTPUT.PUT_LINE(v_tempStr);
      END IF;

      IF INSTR(v_src, UTL_TCP.CRLF) <> 0 THEN
        v_tempStr := SUBSTR(v_src, 1, INSTR(v_src, UTL_TCP.CRLF)-1);
        v_src := SUBSTR(v_src, INSTR(v_src, UTL_TCP.CRLF)+LENGTH(UTL_TCP.CRLF));
      ELSE
        EXIT;
      END IF;
    END LOOP;
   
  EXCEPTION
    WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE('Error Occured : println(VARCHAR2) internal procedure.');
      DBMS_OUTPUT.PUT_LINE(sqlerrm());
      RAISE;
  END println;

  --****************************************************************************
  --* XMLTYPEに格納されたXMLソースをプリントする。
  --* (Oracle10g R1だと、255文字毎の分割プリントは必要かも。。。未実装)
  --*
  --* NOTE:
  --* Oracle10g R2では、DBMS_OUTPUT.PUT_LINEプロシージャの255文字制限がないため、
  --* 255文字毎に分割出力する必要はなくなる32767文字毎の分割出力でもOK.
  --****************************************************************************
  PROCEDURE xml_println
  (
    i_text IN XMLTYPE
  )
  IS
    v_str LONG;
  BEGIN
    v_str := i_text.EXTRACT('/*').GETSTRINGVAL();
    WHILE(v_str IS NOT NULL) LOOP
      DBMS_OUTPUT.PUB_LINE(SUBSTR(v_str, 1, INSTR(v_str, CHR(10)) - 1));
      v_str := SUBSTR(v_str, INSTR(v_str, CHR(10)) + 1);
    END LOOP;

  EXCEPTION
    WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE('Error Occured : xml_println(XMLTYPE) internal procedure.');
      DBMS_OUTPUT.PUT_LINE(sqlerrm());
      RAISE;
  END xml_println;

--****************************************************************************
--* Main Procedure
--****************************************************************************
BEGIN
  DBMS_OUTPUT.ENABLE(200000);
  println('begin...');

  v_url := i_url;
  IF v_url IS NULL THEN
    RAISE_APPLICATION_ERROR(-20000, 'URLを指定してください。');
  END IF;

  v_req := UTL_HTTP.BEGIN_REQUEST(v_url);
  UTL_HTTP.SET_HEADER(v_req, 'User-Agent', 'Oracle UTL_HTTP/Oracle10g R1');
  UTL_HTTP.SET_HEADER(v_req, 'Content-Type', 'text/xml;charset=UTF-8');
  v_resp := UTL_HTTP.GET_RESPONSE(v_req);
 
  -- RSSソースを一時CLOBへ書き出す
  DBMS_LOB.CREATETEMPORARY(v_tempSourceClob, FALSE);
  BEGIN
    LOOP
      UTL_HTTP.READ_LINE(v_resp, v_source, true);
      
      -- 改行コード強制的に付加。
      -- xml_println()でDBMS_OUTPUT.PUT_LINE()が、最大255文字までしか
      -- 表示できないことへの一時的な対策。(試しているサイトについてはこれで
      -- 回避できているので今のところはこのままで。)
      v_source := v_source || UTL_TCP.CRLF;
      DBMS_LOB.WRITEAPPEND(v_tempSourceClob, LENGTH(v_source), v_source);
    END LOOP;
  EXCEPTION
    WHEN UTL_HTTP.END_OF_BODY THEN
      UTL_HTTP.END_RESPONSE(v_resp);
  END;
 
  println('====================');
  v_myParser := DBMS_XMLPARSER.NEWPARSER();
  DBMS_XMLPARSER.PARSECLOB(v_myParser, v_tempSourceClob);
  v_rssDoc := DBMS_XMLPARSER.GETDOCUMENT(v_myParser);
 
  println('DBMS_XMLPARSERバージョン:'||DBMS_XMLPARSER.GETRELEASEVERSION());
  println('DBMS_XMLDOMバージョン   :'||DBMS_XMLDOM.GETVERSION(v_rssDoc));
  println(' ');
  xml_println(DBMS_XMLDOM.GETXMLTYPE(v_rssDoc));
  println('====================');
  println(' ');
  DBMS_LOB.FREETEMPORARY(v_tempSourceClob);
  DBMS_XMLPARSER.FREEPARSER(v_myParser);

  println('...End');

EXCEPTION
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE('Error Occured : main procedure.');
    DBMS_OUTPUT.PUT_LINE(sqlerrm());
    RAISE;

    END RSS_FEED_READER;

また、前述のようにした事で、Mac De Oracleなどで発生してたココログのATOM配信フォーマットのパースエラーも消えた!?(やはり文字化けが影響していたようだ。)
以下に、Mac De OracleのATOMを読み込んだOracle SQL Developer 1.0 for MacOSXのスナップショットを示す。


Jdevok

Oracle10g R1で、なんとか日本語対応のRSS Readerを作ることもできそうな感触。。。。Oracle10g R2は、MacOSX版がリリースされていないの(本当にリリースされるのか??)で、それまではLinux版のOracel10g R2で試してみるか。。。

今聞いている曲:
Malene Mortensen - Date with a DreamMalene Mortensen - デイト・ウィズ・ア・ドリーム GENAI - HAEVEN OF EARTHジェナイ - ヘブン・オン・アース

| | | コメント (0) | トラックバック (0)

2006年8月 7日 (月)

Mac De PL/SQL RSS Reader #2

前回のつづきです。

前回、


RSS Readerの実験に利用するBlogは、私の友人であるmegawattさんのサイトを利用させて頂いた。(自分のブログである、Mac De OracleのRSSを利用していないのだが、理由は後日!)

と書いたが、当初、私のブログ(Mac De Oracle)で試そうと思ったのだが、何故、利用しなかったのか書いておく。
ココログは、RSSフォーマットではなく、Atom配信フォーマット。これはXMLのフォーマットが異なるだけなので、利用しなかった理由ではない。問題は、ココログのATOM配信フォーマットをDBMS_XMLPARSERパッケージのParserでパースすると、パースエラーが発生するためだ。

以下、前回のプロシージャを利用してMac De OracleのATOMを解析した実行結果を示す。(実行には、Oracle PL/SQL Developer 1.0を利用した。)

データベースOracle10g Scottに接続中です。
ORA-31011: XML解析に失敗しました
ORA-19202: XML処理
LPX-00244: 小なり不等号 ('<')文字の使用が無効です。 (&lt;を使用します)
Error at line 63
中にエラーが発生しました
ORA-06512: "SCOTT.RSS_FEED_READER", 行155
ORA-06512: 行6
begin...
Main Procedure:ORA-31011: XML解析に失敗しました
ORA-19202: XML処理
LPX-00244: 小なり不等号 ('<')文字の使用が無効です。 (&lt;を使用します)
Error at line 63
中にエラーが発生しました
プロセス終了。
データベースOracle10g Scottから切断中です。

私のブログだけが問題なのか? 少々、心配になったので、私のお気に入りブログの一つである「鎌倉withLove」(現在は、ご自身で立ち上げたサイトに移行されているが、まだ、ココログにも残っているのでココログのATOMでも試させていただいた。)でも試してみた。やはり、同じエラーでXMLのパースエラーとなる。

Macdeoracleatom_error

新しい「鎌倉withLove」のサイトのATOMでも試してみたのだが、そちらではパースエラーは発生していない。文字化けは発生するが。。。(ココログもベースはMovableTypeだと思うのだが。。。随分カスタマイズされているようで。。)

Kamakurawithlove_ok

#尚、パースエラーの原因は、DBMS_XMLPARDERパッケージで行うURL直指定パースで発生する文字化けが絡んでいる可能性も捨てきれない。(これは後日確認する予定。)


今聞いている曲:
Najee - Tokyo Blue Kim Waters - All for Love

| | | コメント (0) | トラックバック (0)

2006年8月 6日 (日)

Mac De PL/SQL RSS Reader #1

Mac De Oracle、久々の投稿です。前回までの騒ぎはなんとか収束。(あとはベンダーさん次第。。)

ということで、以前から読んでいるこのブログの記事にあるPL/SQLでRSS Reader!
そのネタの一部?!を試してみようと思う。まず、手始めに一番気になっているエンコーディングの部分から始めることにする。

環境は、 いつもの Oracle10g R1 EE for MacOSX Serverを利用する。(インストール方法などは、こちらを参考にしてください。
尚、MacOS Xは、以下のように現在の最新版を利用している。なお、データベースキャラクタセットは、JA16SJISTILDEである。

Os

RSS Readerの実験に利用するBlogは、私の友人であるmegawattさんのサイトを利用させて頂いた。(自分のブログである、Mac De OracleのRSSを利用していないのだが、理由は後日!)
megawattさんRSSのバージョンは、RSS 0.91RSS 1.0を提供しているが、当面はRSS 0.91で遊ぶことにする。

megawattさん、いろいろと試していたので、アクセスログがタップリ吐かれていると思いますが、DOS攻撃ではないのでご安心を! (^^;;;;;

さて、本題。
結果を先に書いておくと、Oracle10g R1のDBMS_XMLPARSERパッケージのXMLパーサーでRSS FeedのURLを直指定しパースした場合、マルチバイト文字は文字化した。(Oracle10g R2ではどうなのかは後日確認する予定)。 なんとかエンコーディングを指定できないものかと調べてみたが、Oracle10g R1のDBMS_XMLPARSERでは、XMLパーサーに対してエンコーディングを指定することはできないようだ。(マニュアルをざっと読んでみたが、該当するプロシージャもファンクションも存在しない。)


以下は、Oracle10g R1 EE for MacOSX ServerのDBMS_XMLPARSERパッケージを利用してパース後、XMLDOMからRSSソースを取り出しリストした結果である。文字の化け方から想像すると、UTF-8をISO Latin 1としてエンコードしているのかもしれない。
尚、すべての操作はOracle SQL Developer 1.0を利用して行った。(便利なのだがMacOSXだと、debuggerの動作がかなり遅いかも。。実際にはdebuggerを起動しなくても試せるので問題は無かったのだが。。)


_1 _2

_3 _4



データベースOracle10g R1 glasscatfishに接続中です。
begin...
DBMS_XMLPARSERバージョン:10.1.0.2.0
DBMS_XMLDOMバージョン :1.0
=== パース済みDOMから取得したRSSソース ===
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE rss PUBLIC "-//Netscape Communications//DTD RSS 0.91//EN"
"http://my.netscape.com/publish/formats/rss-0.91.dtd">
<rss version="0.91">
<channel>
<title>a?!a?¬a??e≪?</title>
<link>http://megawatt.blogdns.net/blog</link>
<description>A Weblog Product for Zope</description>

<item>
<title>c??a??a??e?oao?a??a??a?≪e!?a?£a?|a??a??</title>
<link>http://megawatt.blogdns.net/blog/252</link>
</item>

<item>
<title>e??a?aa??a?¨a??a? ̄e??a?aa?? Part2</title>
<link>http://megawatt.blogdns.net/blog/251</link>
</item>

<item>
<title>e??a?aa??a?¨a??a? ̄e??a?aa??</title>
<link>http://megawatt.blogdns.net/blog/250</link>
</item>

<item>
<title>a??a??a??a??a??a??</title>
<link>http://megawatt.blogdns.net/blog/249</link>
</item>

<item>
<title>c?≪a?Ra??a??a?Ra??c??e¬?ao§i??2006a1´ao|a??a??a?≫i??</title>
<link>http://megawatt.blogdns.net/blog/248</link>
</item>

<item>
<title>a? ̄a??a?3100mla??80a?-a?-a?≪a?-a?aa??!!</title>
<link>http://megawatt.blogdns.net/blog/247</link>
</item>

<item>
<title>a? ̄a?£a?!a??a??a?§a? ̄a?aa??a? ̄a?£a?!a??a??</title>
<link>http://megawatt.blogdns.net/blog/246</link>
</item>


<item>
<title>a?!a??a?£a?¨a??eμ°a?£a?|a??</title>
<link>http://megawatt.blogdns.net/blog/245</link>
</item>

<item>
<title>a??a??a??a??a??a?,a??</title>
<link>http://megawatt.blogdns.net/blog/244</link>
</item>

<item>
<title>c?≪a??a??a?? ate??a??a≫2c?o</title>
<link>http://megawatt.blogdns.net/blog/243</link>
</item>

<item>
<title>c?≪a??a??a?£a??a?¥</title>
<link>http://megawatt.blogdns.net/blog/242</link>
</item>

<item>
<title>a??e£2c?ca?aa?≪a?≪a??a??a??a???</title>
<link>http://megawatt.blogdns.net/blog/241</link>
</item>

<item>
<title>e??a??a≫2c?oa?≫a・±a・?a,?a??a??</title>
<link>http://megawatt.blogdns.net/blog/240</link>
</item>

<item>
<title>a??a??a??a??a??a??a??a??</title>
<link>http://megawatt.blogdns.net/blog/239</link>
</item>

<item>
<title>c?-a-?c?±</title>
<link>http://megawatt.blogdns.net/blog/238</link>
</item>

<item>
<title>a??a??a??a??a??a??a?aa??a?§</title>
<link>http://megawatt.blogdns.net/blog/237</link>
</item>

</channel>
</rss>
====================
...End
プロセス終了。
データベースOracle10g R1 glasscatfishから切断中です。

以下は、AMIS Technology Blogのサンプルコードを参考にして作成したプロシージャのソースである。
URLで指定されたRSSソースをDBMS_XMLPARSERパッケージのXMLパーサーでパースし、生成されたXMLDOMオブジェクトからRSSソースをリストするしている。


CREATE OR REPLACE PROCEDURE RSS_FEED_READER
(
i_url IN VARCHAR2
)
AS
--============ TYPEs/VARIABLEs ===============================================
TYPE rss_type IS RECORD
(
title VARCHAR2(2000),
link VARCHAR2(200),
pubDate VARCHAR2(200),
category VARCHAR2(500),
description VARCHAR2(4000)
);
v_rss_item rss_type;
v_rss_empty_item rss_type; -- v_rss_item初期化用


v_url VARCHAR2(32767);

-- XML PARSER
v_myParser DBMS_XMLPARSER.Parser;

-- XMLDOM
v_rssDoc DBMS_XMLDOM.DomDocument;

-- for UTL_HTTP
v_req UTL_HTTP.REQ;
v_resp UTL_HTTP.RESP;
v_source VARCHAR2(1024);

-- RSSソース用CLOB(SYS.XMLTYPE型にしたほうがよかったかもしれないが、現時点ではCLOBで!)
v_tempClob CLOB;

--========== Internal PROCEDUREs/FUNCTIONs ===================================
--
--****************************************************************************
--* VARCHAR2の文字列を最大で255文字または、改行コード毎にプリントする内部プロシージャ
--****************************************************************************
--
PROCEDURE println
(
i_text IN VARCHAR2
)
IS
v_src VARCHAR2(32767);
v_tempStr VARCHAR2(32767);
BEGIN
v_src := i_text;
IF INSTR(v_src, UTL_TCP.CRLF) <> 0 THEN
v_tempStr := SUBSTR(v_src, 1, INSTR(v_src, UTL_TCP.CRLF)-1);
v_src := SUBSTR(v_src, INSTR(v_src, UTL_TCP.CRLF)+LENGTH(UTL_TCP.CRLF));
ELSE
v_tempStr := v_src;
END IF;

WHILE v_tempStr IS NOT NULL LOOP
IF LENGTH(v_tempStr)> 255 THEN
FOR i IN 1..(TRUNC(LENGTH(v_tempStr)/255)+1) LOOP
DBMS_OUTPUT.PUT_LINE(SUBSTR(v_tempStr,1+ 255*(i-1),255));
END LOOP;
ELSE
DBMS_OUTPUT.PUT_LINE(v_tempStr);
END IF;

IF INSTR(v_src, UTL_TCP.CRLF) <> 0 THEN
v_tempStr := SUBSTR(v_src, 1, INSTR(v_src, UTL_TCP.CRLF)-1);
v_src := SUBSTR(v_src, INSTR(v_src, UTL_TCP.CRLF)+LENGTH(UTL_TCP.CRLF));
ELSE
EXIT;
END IF;
END LOOP;

EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(
'println(VARCHAR2) internal procedure:'
|| sqlerrm()
);
RAISE;
END println;

--****************************************************************************
--* CLOBの文字列を最大で255文字または、改行コード毎にプリントする内部プロシージャ
--****************************************************************************
--
PROCEDURE println
(
i_text IN CLOB
)
IS
v_src CLOB;
v_tempStr CLOB;
BEGIN
v_src := i_text;
IF INSTR(v_src, UTL_TCP.CRLF) = 0 THEN
v_src := REPLACE(v_src, '><', '>'||UTL_TCP.CRLF||'<');
END IF;

v_tempStr := SUBSTR(v_src, 1, INSTR(v_src, UTL_TCP.CRLF)-1);
v_src := TRIM(LEADING UTL_TCP.CRLF FROM SUBSTR(v_src, INSTR(v_src, UTL_TCP.CRLF)));

WHILE v_tempStr IS NOT NULL LOOP
IF LENGTH(v_tempStr) > 255 THEN
FOR i IN 1..(TRUNC(LENGTH(v_tempStr)/255)+1) LOOP
DBMS_OUTPUT.PUT_LINE(SUBSTR(v_tempStr,1+ 255*(i-1),255));
END LOOP;
ELSE
DBMS_OUTPUT.PUT_LINE(v_tempStr);
END IF;
v_tempStr := SUBSTR(v_src, 1, INSTR(v_src, UTL_TCP.CRLF)-1);
v_src := TRIM(LEADING UTL_TCP.CRLF FROM SUBSTR(v_src, INSTR(v_src, UTL_TCP.CRLF)));
END LOOP;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(
'println(CLOB) internal procedure:'
|| sqlerrm()
);
RAISE;
END println;

--****************************************************************************
--* Main Procedure
--****************************************************************************
BEGIN
DBMS_OUTPUT.ENABLE(200000);
println('begin...');


v_url := i_url;
IF v_url IS NULL THEN
RAISE_APPLICATION_ERROR(-20000, 'URLを指定してください。');
END IF;

v_myParser := DBMS_XMLPARSER.NEWPARSER();
DBMS_XMLPARSER.PARSE(v_myParser, v_url);
v_rssDoc := DBMS_XMLPARSER.GETDOCUMENT(v_myParser);
DBMS_LOB.CREATETEMPORARY(v_tempClob, FALSE);
DBMS_XMLDOM.WRITETOCLOB(v_rssDoc, v_tempClob);
println('DBMS_XMLPARSERバージョン:'||DBMS_XMLPARSER.GETRELEASEVERSION());
println('DBMS_XMLDOMバージョン :'||DBMS_XMLDOM.GETVERSION(v_rssDoc));
println(' ');
println('=== パース済みDOMから取得したRSSソース ===');
println(v_tempClob);
println('====================');
println(' ');
DBMS_LOB.FREETEMPORARY(v_tempClob);

DBMS_XMLPARSER.FREEPARSER(v_myParser);

println('...End');

EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(
'Main Procedure:'
|| sqlerrm()
);
RAISE;

END RSS_FEED_READER;


次回は、RSSをパースする際、RSS FEEDのURLを直指定したパースではなく、一旦、UTL_HTTPパッケージを利用してRSSを取得、CLOB変換する。そのCLOBをDBMS_XMLPARSERパッケージのパーサーでパースし、結果を確認してみることにする。
(ちなみに、WindowsのOracle10g R2 EEではXMLDOMが修正されたのか、DBMS_XMLPARSERパッケージかDBMS_XMLDOMパッケージが改良されたのか?。異なる結果をしてしている。それに関しては別記事にて書く予定)


今聞いている曲:
Dave Koz - Lucky Man Dave Koz - The Dance Richard Elliot - Metro Blue

| | | コメント (0) | トラックバック (0)

2006年5月27日 (土)

Mac De Mac De Oracle Heterogeneous! #80

久々のGeneric Connectivityネタです

今回は、Firebird 1.5と Heterogeneous! 。 ただ、ODBCドライバに影響されやすい
Generic Connectivityなので、Firebird_ODBC_1.2.0.69-Win32だと問題があるようだ。

踏み台にするWindowsには、Oracle10g EE R2を利用した。前回までは、Oracle10g EE R1。

踏み台側の環境は以下。
Windows XP Professional SP2
  Firebird V1.5.3.4870 for Windows
  Firebird_ODBC_1.2.0.69-Win32
 
  Oracle10g EE R2 10.2.0.1.0 for Windows

Mac側は以前の記事を参考にしてほしい。

1.ODBC

システムDSN
DSN:
firebird_windows

ここがポイント!
For a Windows server:
servername:DriveLetter:¥filesystem-path¥database-file

という形式で指定しないとデータベースを 見つけられない。

以下のようにFirebirdのサンプルデータベースを指定した。
Database:
catfish:C:¥Program Files¥Firebird¥Firebird_1_5¥examples¥EMPLOYEE.FDB

ユーザ名とパスワードはサンプルデータベースのユーザとパスワードを指定した。

Odbc

2. init.ora

initfirebird_windows.ora

#
# HS init parameters
#
HS_FDS_CONNECT_INFO = firebird_windows
HS_FDS_TRACE_LEVEL = off
HS_FDS_SHAREABLE_NAME = C:¥WINNT¥system32¥IscDbc.dll

3.listener.ora

SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = PLSExtProc)
(ORACLE_HOME = E:¥oracle¥product¥10.2.0¥catfish)
(PROGRAM = extproc)
)

(SID_DESC =
(SID_NAME = mysqldb4026_windows)
(ORACLE_HOME = E:¥oracle¥product¥10.2.0¥catfish)
(PROGRAM = hsodbc)
)

(SID_DESC =
(SID_NAME = firebird_windows)
(ORACLE_HOME = E:¥oracle¥product¥10.2.0¥catfish)

(PROGRAM = hsodbc)
)
)

LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1))
(ADDRESS = (PROTOCOL = TCP)(HOST = catfish)(PORT = 1521))
)
)

4.tnsnames.ora

FIREBIRD_WIN =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = catfish)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SID = firebird_windows)
)
(HS = OK)
)

MYSQL4026_WIN =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = catfish)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SID = mysql4026_windows)
)
(HS = OK)
)

5. SQL*Plusから

以下のデータベースリンクを作成(パブリックデータベースリンクでもOK)
create database link firebird_win
connect to "SYSDBA" identified by "masterkey" using 'FIREBIRD_WIN';

Oracle10g R1では、指定したデータベースリンク名に一致する
データベースリンク名を作成することができたのだが、
Oracle10g R2では、.REGRESS.RDBMS.DEV.US.ORACLE.COMという
ドメイン名がご丁寧に付加される。(悪さはしていない模様。)

SQL> select db_link from user_db_links;

DB_LINK
---------------------------------------------------
FIREBIRD_WIN.REGRESS.RDBMS.DEV.US.ORACLE.COM
MYSQL4026_WIN.REGRESS.RDBMS.DEV.US.ORACLE.COM

SQL>

ディクショナリビューは問題なく問い合わせられる。が・・・

SQL> select table_name from user_tables@firebird_win;

TABLE_NAME
--------------------------------------------------------------

RDB$CHARACTER_SETS
RDB$CHECK_CONSTRAINTS
RDB$COLLATIONS
RDB$DATABASE

中略

DEPARTMENT
EMP
EMPLOYEE
EMPLOYEE_PROJECT
FISHES
JOB
PROJECT
PROJ_DEPT_BUDGET
SALARY_HISTORY
SALES

44行が選択されました。

SQL>
SQL>

一般の表では、文字型の表示がだめ。
(エンコーディング関連で逃げられるものなのか・・・???)

ODBCドライバ側の問題なのだろうかね。(可能性としては高そう)

SQL> select * from "FISHES"@firebird_win;

ID NAME
---------- ---------------------------------------------------
1 discus
2 atfish
3 on tetra

SQL>
SQL> insert into "FISHES"@firebird_win values(4,'guppy');

1行が作成されました。

SQL> commit;

コミットが完了しました。

SQL> select * from "FISHES"@firebird_win;

ID NAME
---------- -----------------------------------------------------------
1 discus
2 atfish
3 on tetragu
4 py

SQL>

Firebirdの isqlから fishes表を問合せた結果をみると
Oracle側から insertしたデータでも正しく問い合わせられる。

SQL> select * from fishes;

ID NAME
============ ==========

1 discus
2 catfish
3 neon tetra
4 guppy

SQL>

と現時点ではこんな感じなので、FirebirdとHeterogeneous! ネタはいずれまた。
今回は、Firebird_ODBC_1.2.0.69-Win32 というODBCドライバを利用したが
v2.0のODBCドライバもリリースされているようなので時間があったら 
ODBCドライバ v2.0でも試してみましょうかね。

尚、この内容は OTN-Jの掲示板FirebirdへのODBC接続に投稿したものとほぼ同じ内容です。 

| | | コメント (0) | トラックバック (0)

2006年3月28日 (火)

Mac De Oracle Heterogeneous! #79

前回のつづき

Generic Connectivyty経由でMySQL4.0.x、MySQL4.1.13aの文字型にアクセス最終回

この検証でそれなりにネタは仕入れる事ができたので、この辺りでGeneric Connectivityは一旦終了する。

=========まとめ=======

利用している MyODBCドライバなどはこちら

Generic Connectivityの文字型マッピング
MySQL Oracle10g R1 Generic Connectivityでの利用 備 考
サイズ binary属性 文字長セマンティクス version サイズ 文字長セマンティクス
char型 20 -- バイト 4.0.25 char型 20 バイト

問合せ、登録、更新とも問題ないのだが、MySQL側でbinary属性が指定されていない場合には、DMLの書き方により、リモートソートが実行され、英字の大文字小文字が区別されなかったり、nullや空文字は、昇順ソートの場合先頭に置かれる。検証では、リモートマップされるクエリをインラインビューに書き換え、そのインラインビューに対して、NO_MERGEヒントを付加することで回避することができた。Oracleは空文字をnullとして扱うので、その点には注意。

定義したサイズを超える文字列を登録した場合には、エラーとなる。但し、char(20)まででしか確認していない。データディクショナリで確認したところ、char(255)では、MySQL側がバイトセマンティクスであるはずなのに、Oracle側では文字セマンティクスで、32512文字とマッピングされている。今回の検証ではこの件については深く検証していないので要注意。

binary バイト
255 -- バイト 32512 文字
binary 文字
20 -- 文字 4.1.13a char型 40 バイト

問合せ、登録、更新とも問題ないのだが、MySQL側でbinary属性が指定されていない場合には、DMLの書き方により、リモートソートが実行され、英字の大文字小文字が区別されなかったり、nullや空文字は、昇順ソートの場合先頭に置かれる。検証では、リモートマップされるクエリをインラインビューに書き換え、そのインラインビューに対して、NO_MERGEヒントを付加することで回避することができた。Oracleは空文字をnullとして扱うので、その点には注意。

定義したサイズを超える文字列を登録した場合には、エラーとなる。但し、char(20)まででしか確認していない。データディクショナリで確認したところ、char(255)では、MySQL側がバイトセマンティクスであるはずなのに、Oracle側では文字セマンティクスで、32256文字とマッピングされ、MySQL4.0.25の場合とより多少少ない。今回の検証ではこの件については深く検証していないので要注意。

binary バイト
255 -- 文字 varchar2型 32256 文字
binary 文字
127 -- 文字 char型 32256 文字

char(127)はSJISで254バイトのchar(254)でなく、なんと、char(32256 char)としてマッピングされている。登録に関しては未テスト。

128 -- 文字 varchar2型 256 バイト char(255)とchar(128)の差からは想像できない、varchar2(32256 char)とvarchar2(256)というマッピングの差があるので要注意。
varchar型 20 -- バイト 4.0.25 varchar2型 20 バイト

問合せ、登録、更新とも問題ないのだが、MySQL側でbinary属性が指定されていない場合には、DMLの書き方により、リモートソートが実行され、英字の大文字小文字が区別されなかったり、nullや空文字は、昇順ソートの場合先頭に置かれる。検証では、リモートマップされるクエリをインラインビューに書き換え、そのインラインビューに対して、NO_MERGEヒントを付加することで回避することができた。Oracleは空文字をnullとして扱うので、その点には注意。

定義したサイズを超える文字列を登録した場合には、エラーとなる。但し、varchar(20)まででしか確認していない。データディクショナリで確認したところ、varchar(255)では、MySQL側がバイトセマンティクスであるはずなのに、Oracle側では文字セマンティクスで、32512文字とマッピングされている。今回の検証ではこの件については深く検証していないので要注意。

binary バイト
255 -- バイト varchar2型 32512 文字
binary 文字
20 -- 文字 4.1.13a varchar2型 40 バイト

問合せ、登録、更新とも問題ないのだが、MySQL側でbinary属性が指定されていない場合には、DMLの書き方により、リモートソートが実行され、英字の大文字小文字が区別されなかったり、nullや空文字は、昇順ソートの場合先頭に置かれる。検証では、リモートマップされるクエリをインラインビューに書き換え、そのインラインビューに対して、NO_MERGEヒントを付加することで回避することができた。Oracleは空文字をnullとして扱うので、その点には注意。

定義したサイズを超える文字列を登録した場合には、エラーとなる。但し、varchar(20)まででしか確認していない。データディクショナリで確認したところ、varchar(255)では、MySQL側がバイトセマンティクスであるはずなのに、Oracle側では文字セマンティクスで、32256文字とマッピングされ、MySQL4.0.25の場合とより多少少ない。今回の検証ではこの件については深く検証していないので要注意。

binary バイト
255 -- 文字 varchar2型 32256 文字
binary
256 -- 文字 long型 -- バイト × varchar(256)を超えるとlong型にマッピングされてしまうので、tinytext型、text型と同じ扱いになる。binary属性が付いていれば、tinyblob型やblob型と同じ扱いになる。
tinytext型 -- -- バイト 4.0.25 long型 -- バイト × tinytext型の最大サイズは255バイト。登録、更新は可能なのだが、long型にマッピングされているためほとんどの関数は利用できない。ソートは未確認だが、binary属性の無いchar型又は、varchar型と同じであると考えている。また、問合せについて、この検証ではまったく問い合わせることができなかったため、Generic Connectivity経由での利用は諦めたほうがよいと思われる。(ODBCドライバなどを替えれば動作する可能せもあるだろうが、その検証にかかるコストも考慮する必要あり。)Oracleは空文字をnullとして扱うので注意。
-- -- バイト 4.1.13a long型 -- バイト
tinyblob型 -- -- バイト 4.0.25 long raw型 -- バイト × tinyblob型の最大サイズは255バイト。登録、更新は可能なのだが、long raw型にマッピングされているためほとんどの関数は利用できない。ソートは未確認だが、binary属性のchar型又は、varchar型と同じであると考えている。また、問合せに関して、この検証ではまったく問い合わせることができなかったため、Generic Connectivity経由での利用は諦めたほうがよいと思われる。(ODBCドライバなどを替えれば動作する可能せもあるだろうが、その検証にかかるコストも考慮する必要あり。)Oracleは空文字をnullとして扱うので注意。
-- -- バイト 4.1.13a long raw型 -- バイト
text型 -- -- バイト 4.0.25 long型 -- バイト × text型の最大サイズは65535バイト。登録、更新は可能なのだが、long型にマッピングされているためほとんどの関数は利用できない。ソートは未確認だが、binary属性の無いchar型又は、varchar型と同じであると考えている。また、問合せに関しては、この検証ではまったく問い合わせることができなかったため、Generic Connectivity経由での利用は諦めたほうがよいと思われる。(ODBCドライバなどを替えれば動作する可能せもあるだろうが、その検証にかかるコストも考慮する必要あり。)Oracleは空文字をnullとして扱うので注意。
-- -- バイト 4.1.13a long型 -- バイト
blob型 -- -- バイト 4.0.25 long raw型 -- バイト × blob型の最大サイズは65535バイト。登録、更新は可能なのだが、long raw型にマッピングされているためほとんどの関数は利用できない。ソートは未確認だが、binary属性のchar型又は、varchar型と同じであると考えている。また、問合せに関しては、この検証ではまったく問い合わせることができなかったため、Generic Connectivity経由での利用は諦めたほうがよいと思われる。(ODBCドライバなどを替えれば動作する可能せもあるだろうが、その検証にかかるコストも考慮する必要あり。)Oracleは空文字をnullとして扱うので注意。
-- -- バイト 4.1.13a long raw型 -- バイト


さて、久々にGeneric Connectivity以外のネタにしますかね。次回からは。

| | | コメント (0) | トラックバック (0)

2006年3月27日 (月)

Mac De Oracle Heterogeneous! #78

前回のつづき。Generic Connectivyty経由でMySQL4.1.13aの文字型にアクセス。八回目。

LONG型にマッピングされた列を問い合わせることができない! という挙動の調査#2

これまではDMLやDDLを利用してどの型にマッピングされているかを確認してきた。理由は、実際に問合せや更新が可能なのかという点も同時に確かめたかったからなのだが、データディクショナリを参照し、どの型にマッピングされているのか再確認してみることにした。

Generic Connectivityでも異機種データベース側のいくつかのディクショナリがマッピングされており、Oracleの user_tablesビューや、user_tab_columnsビューとして問い合わせることができる。
(尚、Genenric Connectivity経由で、利用できるディクショナリの解説は、マニュアル「Oracle Database Heterogeneous Connectivity 管理者ガイド」の付録Cを参照のこと。

ただ、今回は以下ようにな特殊な構成であるため、

gencon_blog_img1

各データディクショナリ毎にシノニムを作成しなければ、MacOSX上のOracle10gからそれらのディクショナリを参照することはできない。
(単に面倒だったからとうこともあるのだが)今回は、Window XP上のOracle10g上で各リモート表のシノニムに対して sql*plusの descコマンドで確認した。

以下、ディクショナリを確認した結果の型を見て、驚いたのだが、文字セマンティクスでマッピングされている箇所がある。MySQL4.0.25はバイトセマンティクスであるが、一部の型は、文字セマンティクスとしてマッピングされている。明らかに、これはまずいはず。

たとえば、 MySQL4.1.13aで、varchar(20)として定義した列は、VARCHAR2(40)とバイトセマンティクスでマッピングされているのだが、varchar(255)と定義してある列は、VARCHAR2(32256 CHAR)と文字セマンティクスでマッピングされていたのだ。
しかも、文字数も255でななく、32256なのである。

char(n)の nの値と文字セマンティクスか否かでキッチリ判断しているのかと考えていたのだが、それは”甘い”考えだったことに気付く。


SQL> desc varchar_test_mysql4113a_mac_sv;
名前 NULL? 型
----------------------------------------- -------- ----------------------------
id NOT NULL NUMBER(10)
r_varchar_20 VARCHAR2(40)
r_varchar_20_binary VARCHAR2(40)
r_varchar_255 VARCHAR2(32256 CHAR)
r_varchar_255_binary VARCHAR2(32256 CHAR)
r_tinytext LONG
r_tinyblob LONG RAW
r_text LONG
r_blob LONG RAW
r_varchar_256 LONG

マッピングを制御するようなパラメータは存在しないため、バイトセマンティクスになるのか、文字セマンティクスにマッピングするかを制御することはできない。

char_test_mysql4113a_mac_svというシノニムに対応するリモート表において、r_char_127は CHAR(127)、r_char_128は CHAR(128)と定義してあるのだが、Generic Connectivity経由でOracleにマッピングされた結果は、ご覧の通り。MySQL4.1.13aの r_char_127は、CHAR(32256 CHAR)と文字セマンティクス、 r_char_128は、VHARCHAR2(256)とバイトセマンティクスとなっている。

一方、PostgreSQL7.4.9の r_char_127 は、CHAR(127)、r_char_128 は、CHAR(128) と定義されているが、Generic Connectivity経由でOracleの型にマッピングされ、r_char_127は、CHAR(127)とバイトセマンティクス、r_char_128は、CHAR(128 CHAR)と文字セマンティクスとしてマッピングされてしまう。

Generic Connectity経由でアクセスする場合の一番の難所は数値型よりも、文字型のほうかもしれない。
256バイト未満の文字列しか扱っていない場合には、それほど気にしなくとも利用できる可能性は高いと思うが、それを超えるサイズを扱う場合(データベースのキャラクタセットも影響する)や、text型や、blob型を利用する場合には、事前に十分な評価テストは必須である。
(Oracle社とのサポート契約があれば、サポート等から関連する情報を入手したほうが良いだろう。開発コストや、運用保守コストなどを考えれば、Generic Connectivityより、Oracleに移行したほうがベターという結論になる場合もあるだろう。)


SQL> desc char_test_mysql4113a_mac_sv
名前 NULL? 型
----------------------------------------- -------- ----------------------------
id NOT NULL NUMBER(10)
r_char_20 CHAR(40)
r_char_20_binary CHAR(40)
r_char_255 VARCHAR2(32256 CHAR)
r_char_255_binary VARCHAR2(32256 CHAR)
r_char_127 CHAR(32256 CHAR)
r_char_128 VARCHAR2(256)

SQL> desc varchar_test_mysql4025_mac
名前 NULL? 型
----------------------------------------- -------- ----------------------------
id NOT NULL NUMBER(10)
r_varchar_20 VARCHAR2(20)
r_varchar_20_binary VARCHAR2(20)
r_varchar_255 VARCHAR2(32512 CHAR)
r_varchar_255_binary VARCHAR2(32512 CHAR)
r_tinytext LONG
r_tinyblob LONG RAW
r_text LONG
r_blob LONG RAW

SQL> desc char_test_mysql4025_mac
名前 NULL? 型
----------------------------------------- -------- ----------------------------
id NOT NULL NUMBER(10)
r_char_20 CHAR(20)
r_char_20_binary CHAR(20)
r_char_255 CHAR(32512 CHAR)
r_char_255_binary CHAR(32512 CHAR)

SQL> desc char_test_postgresql749_mac
名前 NULL? 型
----------------------------------------- -------- ----------------------------
id NUMBER(10)
r_char_20 CHAR(20)
r_char_2000 VARCHAR2(20480 CHAR)
r_char_2001 VARCHAR2(20736 CHAR)
r_varchar_20 VARCHAR2(20)
r_varchar_4000 VARCHAR2(8192 CHAR)
r_varchar_4001 LONG
r_text LONG
r_char_254 CHAR(32256 CHAR)
r_char_255 CHAR(32512 CHAR)
r_char_127 CHAR(127) 
r_char_128 CHAR(128 CHAR)
r_char_256 VARCHAR2(256)  

ところで、MySQLでは、LONGまたは、LONG RAW型にマッピングされていた列は全く問い合わせることができなかったのだが、PostgreSQLでは問い合わせることができる。

問題は、ODBC Driverなのかもしれないと疑い始めたのだが、Generic Connectivity側に何らかの問題があるという可能性を否定できる情報もない。。。

以下は、PostgreSQLで Generic Connectivity経由で long型にマッピングされる r_text列を問い合わせた結果(MySQLの場合と明らかに違う)


CORYDORAS> col r_text for a40
CORYDORAS> col r_varchar_4001 for a40
CORYDORAS> set linesize 132
CORYDORAS> set null "null"
CORYDORAS> l
1 select
2 "id","r_text","r_varchar_4001"
3 from
4 char_test_postgresql749_mac@oracle10g_win
5 where
6* "id" between 30 and 33

CORYDORAS> /

id r_text r_varchar_4001
---------- ---------------------------------------- ----------------------------------------
30 null null
31 null null
32 12345678901234567890 null
33 12345678901234567890 null

CORYDORAS>

今日はここまで、次回へづづく。

MySQL4.0.x、MySQL4.1.x、PostgreSQL7.4.9の基本的な型をGeneric Connecvitiy経由で Oracleかアクセスするというネタも、次回で一旦終了する。また確認したいことがあれば再開する予定である。

| | | コメント (0) | トラックバック (0)

2006年3月26日 (日)

Mac De Oracle Heterogeneous! #77

前回のつづき。Generic Connectivyty経由でMySQL4.1.13aの文字型にアクセス。七回目。

LONG型にマッピングされた列を問い合わせることができない!

7.TINYTEXT型、TINYBLOB型、TEXT型、BLOB型(追加検証)

以前簡単に触れた事なのだが、TINYTEXT型、TINYBLOB型、TEXT型、BLOB型は、 Generic Connectivity経由で、OracleのLONG型にマッピングされていると判断したのは以下のような結果からだった。
この判断間違っていたのか?・・・。


CORYDORAS> l
1* create table hoge as select "id","r_blob" from varchar_test_mysql4113a_mac_sv@oracle10g_win
CORYDORAS> /
create table hoge as select "id","r_blob" from varchar_test_mysql4113a_mac_sv@oracle10g_win
*
行1でエラーが発生しました。:
ORA-00997: LONGデータ型は使用できません。

CORYDORAS> l
1* create table hoge as select "id","r_tinytext" from varchar_test_mysql4113a_mac_sv@oracle10g_win
CORYDORAS> /
create table hoge as select "id","r_tinytext" from varchar_test_mysql4113a_mac_sv@oracle10g_win
*
行1でエラーが発生しました。:
ORA-00997: LONGデータ型は使用できません。

CORYDORAS> l
1* create table hoge as select "id","r_tinyblob" from varchar_test_mysql4113a_mac_sv@oracle10g_win
CORYDORAS> /
create table hoge as select "id","r_tinyblob" from varchar_test_mysql4113a_mac_sv@oracle10g_win
*
行1でエラーが発生しました。:
ORA-00997: LONGデータ型は使用できません。

CORYDORAS>

OracleのLONG型にマッピングされている、TINYTEXT型、TINYBLOB型、TEXT型、BLOB型の列には、Generic Connectivity経由でデータ登録可能なのだが、

OracleのLONG型にマッピングされている関係でほとんどのスカラ関数は利用できない。

さらに、MySQL4.0.25、MySQL4.1.13aともLONG型にマッピングされたデータを問い合わせることが出来ないという現象に遭遇してしまったのだ。(これはまずい)
LONG型ならば問い合わせることができるはずなのだが、TINYTEXT型、TINYBLOB型、TEXT型、BLOB型の単純なクエリ全てがエラーとなってしまうのだ。
以下の結果を観る限り、シンタックスエラーが返されているためGeneric Connectivity経由でリモートサイトに割り振っているSQL文がまずいのかもしれない。(MyODBCの問題なのか、OracleのGeneric Connectivityの問題なのか? いずれにしても、SQLが多少書き換えられているのは間違いないので、書き換えるための元の情報が間違っているのか、書き換える処理に問題があるのかのいずれかということになる。)


CORYDORAS> select "r_tinytext" from varchar_test_mysql4113a_mac_sv@oracle10g_win;
ERROR:
ORA-28500:
OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC][MySQL][ODBC 3.51 Driver][mysqld-4.1.13a]You
have an error in your SQL syntax; check the manual that corresponds to your
MySQL server version for the right syntax to use near '"varchar_test" WHERE
"id"=1' at line 1 (SQL State: 37000; SQL Code: 1064)
ORA-02063: 先行のエラー・メッセージを参照してください2
lines(MYSQL4113A_MAC_SV)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。

レコードが選択されませんでした。

前述のクエリに、条件を加えてみたところ興味深いエラーが返された。
The column 'A1.r_tinytext' is a chapter or a BLOB という部分である。
BLOBにマッピングされているのか?? と疑心暗鬼。 


CORYDORAS> l
1 select "r_tinytext" from varchar_test_mysql4113a_mac_sv@oracle10g_win
2* where "r_tinytext" = ''
CORYDORAS> /
select "r_tinytext" from varchar_test_mysql4113a_mac_sv@oracle10g_win
*
行1でエラーが発生しました。:
ORA-28500:
OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC][A03C] The column 'A1.r_tinytext' is a chapter
or a BLOB, it can't be used in expressions, ORDER/GROUP BY clause or DISTINCT
query
ORA-02063: 先行のエラー・メッセージを参照してください2
lines(MYSQL4113A_MAC_SV)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。

CORYDORAS>

どの型にマップされているのかを再確認した。
MySQL側で、TINYTEXT型だけの列を持つ表を作成しデータを登録しておく。(一意性制約や、主キー制約も付加していない点に注目)
次に、Generic Connectivity経由で該当する列を問い合わせてみると、やはりエラーになる。


mysql> create table hoge (test_tinytext tinytext);
Query OK, 0 rows affected (0.00 sec)

mysql> insert into hoge values('あいう');
Query OK, 1 row affected (0.01 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from hoge;
+---------------+
| test_tinytext |
+---------------+
| あいう |
+---------------+
1 row in set (0.00 sec)

mysql>

mysql> desc hoge
-> ;
+---------------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+----------+------+-----+---------+-------+
| test_tinytext | tinytext | YES | | NULL | |
+---------------+----------+------+-----+---------+-------+
1 row in set (0.00 sec)

Generic Connectivity経由で問い合わせた結果。


CORYDORAS> select "test_tinytext" from hoge_mysql4113a_mac_sv@oracle10g_win;
select "test_tinytext" from hoge_mysql4113a_mac_sv@oracle10g_win
*
行1でエラーが発生しました。:
ORA-28500:
OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC][D015] The table hoge contains a chapter or a
blob. It must also contain a column with unique index.
ORA-02063: 先行のエラー・メッセージを参照してください2
lines(MYSQL4113A_MAC_SV)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。

エラーメッセージに従い、主キー制約を追加してみた。。。


mysql> alter table hoge add column id int primary key;
Query OK, 1 row affected (0.38 sec)
Records: 1 Duplicates: 0 Warnings: 0

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> desc hoge;
+---------------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+----------+------+-----+---------+-------+
| test_tinytext | tinytext | YES | | NULL | |
| id | int(11) | | PRI | 0 | |
+---------------+----------+------+-----+---------+-------+
2 rows in set (0.00 sec)

mysql>
mysql> update hoge set id =1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

Generic Connectivity経由で問い合わせた結果。
主キー制約を追加したのだが、結果はやはりシンタックスエラーとなる。(だめだな、こりゃ)


CORYDORAS> select "id","test_tinytext" from hoge_mysql4113a_mac_sv@oracle10g_win;
ERROR:
ORA-28500:
OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC][MySQL][ODBC 3.51 Driver][mysqld-4.1.13a]You
have an error in your SQL syntax; check the manual that corresponds to your
MySQL server version for the right syntax to use near '"hoge" WHERE "id"=0' at
line 1 (SQL State: 37000; SQL Code: 1064)
ORA-02063: 先行のエラー・メッセージを参照してください2
lines(MYSQL4113A_MAC_SV)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。

LONG型ではなくLOB型にマッピングされているとすれば、主キー制約又一意制約が必要であると、マニュアルに記載されている通りの挙動だとは思うのだが・・・・。(尚、MySQL4.0.25でも同じ結果であった。)

今日はここまで、次回につづく。

| | | コメント (0) | トラックバック (0)

2006年3月25日 (土)

Mac De Oracle Heterogeneous! #76

前回のつづき。Generic Connectivyty経由でMySQL4.1.13aの文字型にアクセス。六回目。

6.文字列の登録

char(20)へのデータ登録。特に気になる点はない。


CORYDORAS> insert into
2 char_test_mysql4113a_mac_sv@oracle10g_win("id","r_char_20")
3 values(300,null);

1行が作成されました。

CORYDORAS> insert into
2 char_test_mysql4113a_mac_sv@oracle10g_win("id","r_char_20")
3 values(301,'');

1行が作成されました。

CORYDORAS> insert into
2 char_test_mysql4113a_mac_sv@oracle10g_win("id","r_char_20")
3 values(302,' あ ');

1行が作成されました。

CORYDORAS> insert into
2 char_test_mysql4113a_mac_sv@oracle10g_win("id","r_char_20")
3 values(303,'12345678901234567890');

1行が作成されました。

CORYDORAS> commit;

コミットが完了しました。

CORYDORAS> insert into
2 char_test_mysql4113a_mac_sv@oracle10g_win("id","r_char_20")
3 values(304,'123456789012345678901');

1行が作成されました。

CORYDORAS> edit
file afiedt.bufが書き込まれました。

1 insert into
2 char_test_mysql4113a_mac_sv@oracle10g_win("id","r_char_20")
3* values(305,'1234567890123456789012345678901234567890')
CORYDORAS> /

1行が作成されました。

CORYDORAS> edit
file afiedt.bufが書き込まれました。

1 insert into
2 char_test_mysql4113a_mac_sv@oracle10g_win("id","r_char_20")
3* values(305,'12345678901234567890123456789012345678901')
CORYDORAS> /
insert into
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC][A0C9] Value for column r_char_20 exceeds column's length.
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(MYSQL4113A_MAC_SV)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。

CORYDORAS> rollback;

ロールバックが完了しました。

CORYDORAS> insert into
2 char_test_mysql4113a_mac_sv@oracle10g_win("id","r_char_20")
3 values(304,'12345678901234567890');

1行が作成されました。

CORYDORAS> edit
file afiedt.bufが書き込まれました。

1 insert into
2 char_test_mysql4113a_mac_sv@oracle10g_win("id","r_char_20")
3* values(304,'123456789012345678901')
CORYDORAS> /
insert into
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC][A0C9] Value for column r_char_20 exceeds column's length.
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(MYSQL4113A_MAC_SV)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。

CORYDORAS>


varchar(20)へのデータ登録。特に気になる点はない。


CORYDORAS> insert into varchar_test_mysql4113a_mac_sv@oracle10g_win("id","r_varchar_20")
2 values(300,null);

1行が作成されました。

CORYDORAS> insert into varchar_test_mysql4113a_mac_sv@oracle10g_win("id","r_varchar_20")
2 values(301,'');

1行が作成されました。

CORYDORAS> insert into varchar_test_mysql4113a_mac_sv@oracle10g_win("id","r_varchar_20")
2 values(302,' あ ');

1行が作成されました。

CORYDORAS> insert into varchar_test_mysql4113a_mac_sv@oracle10g_win("id","r_varchar_20")
2 values(303,'12345678901234567890');

1行が作成されました。

CORYDORAS> insert into varchar_test_mysql4113a_mac_sv@oracle10g_win("id","r_varchar_20")
2 values(304,'12345678901234567890');

1行が作成されました。

CORYDORAS> commit;

コミットが完了しました。

CORYDORAS> insert into varchar_test_mysql4113a_mac_sv@oracle10g_win("id","r_varchar_20")
2 values(305,'1234567890123456789012345678901234567890');

1行が作成されました。

CORYDORAS> edit
file afiedt.bufが書き込まれました。

1 insert into varchar_test_mysql4113a_mac_sv@oracle10g_win("id","r_varchar_20")
2* values(305,'12345678901234567890123456789012345678901')
CORYDORAS> /
insert into varchar_test_mysql4113a_mac_sv@oracle10g_win("id","r_varchar_20")
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC][A0C9] Value for column r_varchar_20 exceeds column's length.
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(MYSQL4113A_MAC_SV)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。

CORYDORAS> commit;

コミットが完了しました。

CORYDORAS> insert into varchar_test_mysql4113a_mac_sv@oracle10g_win("id","r_varchar_20")
2 values(306,'123456789012345678901');
insert into varchar_test_mysql4113a_mac_sv@oracle10g_win("id","r_varchar_20")
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC][A0C9] Value for column r_varchar_20 exceeds column's length.
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(MYSQL4113A_MAC_SV)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。

CORYDORAS> rollback;

ロールバックが完了しました。

CORYDORAS>


今日は、ここまで、次回につづく。

| | | コメント (0) | トラックバック (0)

2006年3月24日 (金)

Mac De Oracle Heterogeneous! #75

前回のつづき。Generic Connectivyty経由でMySQL4.1.13aの文字型にアクセス。五回目。

5.ソート

MySQL4.0.xの場合と同じデータを登録してある。


CORYDORAS> col hex_sjis for a20
CORYDORAS> l
1 select
2 "id",
3 "r_varchar_20",
4 dump("r_varchar_20",16) as hex_sjis
5 from
6 varchar_test_mysql4113a_mac_sv@oracle10g_win
7 where
8* "id" between 1 and 18
CORYDORAS> /

id r_varchar_20 HEX_SJIS
---------- ---------------------------------------- --------------------
1 C Typ=1 Len=1: 43
2 c Typ=1 Len=1: 63
3 B Typ=1 Len=1: 42
4 b Typ=1 Len=1: 62
5 A Typ=1 Len=1: 41
6 a Typ=1 Len=1: 61
7 お Typ=1 Len=2: 82,a8
8 え Typ=1 Len=2: 82,a6
9 う Typ=1 Len=2: 82,a4
10 い Typ=1 Len=2: 82,a2
11 あ Typ=1 Len=2: 82,a0
12 ぉ Typ=1 Len=2: 82,a7
13 ぇ Typ=1 Len=2: 82,a5
14 ぅ Typ=1 Len=2: 82,a3
15 ぃ Typ=1 Len=2: 82,a1
16 ぁ Typ=1 Len=2: 82,9f
17 null NULL
18 null NULL

18行が選択されました。

CORYDORAS>

"r_varchar_20"は、binary属性がないため、MySQL側でソート処理が行われるとソート結果が異ってしまうのだが、以下のようにOracle側にしか存在しない関数があることでOracle側でソートされている。

CORYDORAS> l
1 select
2 "id",
3 "r_varchar_20",
4 dump("r_varchar_20",16) as hex_sjis
5 from
6 varchar_test_mysql4113a_mac_sv@oracle10g_win
7 where
8 "id" between 1 and 18
9 order by
10* "r_varchar_20"
CORYDORAS> /

id r_varchar_20 HEX_SJIS
---------- ---------------------------------------- --------------------
5 A Typ=1 Len=1: 41
3 B Typ=1 Len=1: 42
1 C Typ=1 Len=1: 43
6 a Typ=1 Len=1: 61
4 b Typ=1 Len=1: 62
2 c Typ=1 Len=1: 63
16 ぁ Typ=1 Len=2: 82,9f
11 あ Typ=1 Len=2: 82,a0
15 ぃ Typ=1 Len=2: 82,a1
10 い Typ=1 Len=2: 82,a2
14 ぅ Typ=1 Len=2: 82,a3
9 う Typ=1 Len=2: 82,a4
13 ぇ Typ=1 Len=2: 82,a5
8 え Typ=1 Len=2: 82,a6
12 ぉ Typ=1 Len=2: 82,a7
7 お Typ=1 Len=2: 82,a8
17 null NULL
18 null NULL

18行が選択されました。

dump()関数を取り去ると、文全てがリモートマップされ、ソート結果もMySQL側のソート結果となってしまう。


CORYDORAS> edit
file afiedt.bufが書き込まれました。

1 select
2 "id",
3 "r_varchar_20"
4 from
5 varchar_test_mysql4113a_mac_sv@oracle10g_win
6 where
7 "id" between 1 and 18
8 order by
9* "r_varchar_20"
CORYDORAS> /

id r_varchar_20
---------- ----------------------------------------
17 null
18 null
5 A
6 a
3 B
4 b
1 C
2 c
16 ぁ
11 あ
15 ぃ
10 い
14 ぅ
9 う
13 ぇ
8 え
12 ぉ
7 お

18行が選択されました。

さて、MySQL4.0.25の場合と同様、インラインビューに書き換え、NO_MERGEヒントを追加する。このように書き換えることでリモートソート回避を強制させることが出来る。


CORYDORAS> edit
file afiedt.bufが書き込まれました。

1 select *
2 from
3 (
4 select /*+ NO_MERGE */
5 "id",
6 "r_varchar_20"
7 from
8 varchar_test_mysql4113a_mac_sv@oracle10g_win
9 where
10 "id" between 1 and 18
11 )
12 order by
13* "r_varchar_20"
CORYDORAS> /

id r_varchar_20
---------- ----------------------------------------
5 A
3 B
1 C
6 a
4 b
2 c
16 ぁ
11 あ
15 ぃ
10 い
14 ぅ
9 う
13 ぇ
8 え
12 ぉ
7 お
17 null
18 null

18行が選択されました。

オートトレースで実行計画と統計情報を取得してみると、確かにOracle側でソートされている。


CORYDORAS> set null ""
CORYDORAS> set autot on
CORYDORAS> l
1 select *
2 from
3 (
4 select /*+ NO_MERGE */
5 "id",
6 "r_varchar_20"
7 from
8 varchar_test_mysql4113a_mac_sv@oracle10g_win
9 where
10 "id" between 1 and 18
11 )
12 order by
13* "r_varchar_20"
CORYDORAS> /

id r_varchar_20
---------- ----------------------------------------
5 A
3 B
1 C
6 a
4 b
2 c
16 ぁ
11 あ
15 ぃ
10 い
14 ぅ
9 う
13 ぇ
8 え
12 ぉ
7 お
17
18

18行が選択されました。

実行計画
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=53 Card=5 Bytes=275)
1 0 SORT (ORDER BY) (Cost=53 Card=5 Bytes=275)
2 1 VIEW (Cost=52 Card=5 Bytes=275)
3 2 REMOTE* (Cost=52 Card=5 Bytes=275) ORACLE10G_WIN

3 SERIAL_FROM_REMOTE SELECT "id","r_varchar_20" FROM "VARCHAR_TES
T_MYSQL4113A_MAC_SV" "VARCHAR_TEST_M

統計
----------------------------------------------------------
0 recursive calls
0 db block gets
0 consistent gets
0 physical reads
0 redo size
812 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
18 rows processed

CORYDORAS>

今日はここまで、次回へつづく。

| | | コメント (0) | トラックバック (0)

2006年3月23日 (木)

Mac De Oracle Heterogeneous! #74

前回のつづき

4.tinytext型、tinyblob型、text型、blob型

MySQL4.0.xの場合と同様の結果(length関数等が利用できない)であったためlong型にマッピングされていると思っていたのだが、ほんとうにlong型なのか?という挙動に気付いた。その挙動については別途まとめる予定であり、合わせてPostgreSQL7.4.9のtext型についても再検証する予定であるが、今回はlength()関数等の利用でエラーとなったログだけを載せておく。

CORYDORAS> select
2 "id",
3 "r_tinytext",
4 length("r_tinytext") as "文字数",
5 lengthb("r_tinytext") as "文字サイズ",
6 substr(
7 dump("r_tinytext",16),
8 1,
9 instr(dump("r_tinytext",16),' ')
10 ) as "dump"
11 from
12 varchar_test_mysql4113a_mac_sv@oracle10g_win
13 where
14 "id" = 30;
select
*
行1でエラーが発生しました。:
ORA-02070: データベースMYSQL4113A_MAC_SVはこのコンテキストではLENGTHをサポートしません。
ORA-02063: 先行のエラー・メッセージを参照してくださいline(ORACLE10G_WIN)。

CORYDORAS> l
1 select
2 "id",
3 "r_tinyblob",
4 length("r_tinyblob") as "文字数",
5 lengthb("r_tinyblob") as "文字サイズ",
6 substr(
7 dump("r_tinyblob",16),
8 1,
9 instr(dump("r_tinyblob",16),' ')
10 ) as "dump"
11 from
12 varchar_test_mysql4113a_mac_sv@oracle10g_win
13 where
14* "id" = 30
CORYDORAS> /
select
*
行1でエラーが発生しました。:
ORA-02070: データベースMYSQL4113A_MAC_SVはこのコンテキストではLENGTHをサポートしません。
ORA-02063: 先行のエラー・メッセージを参照してくださいline(ORACLE10G_WIN)。

CORYDORAS> l
1 select
2 "id",
3 "r_text",
4 length("r_text") as "文字数",
5 lengthb("r_text") as "文字サイズ",
6 substr(
7 dump("r_text",16),
8 1,
9 instr(dump("r_text",16),' ')
10 ) as "dump"
11 from
12 varchar_test_mysql4113a_mac_sv@oracle10g_win
13 where
14* "id" = 30
CORYDORAS> /
select
*
行1でエラーが発生しました。:
ORA-02070: データベースMYSQL4113A_MAC_SVはこのコンテキストではLENGTHをサポートしません。
ORA-02063: 先行のエラー・メッセージを参照してくださいline(ORACLE10G_WIN)。

CORYDORAS> l
1 select
2 "id",
3 "r_blob",
4 length("r_blob") as "文字数",
5 lengthb("r_blob") as "文字サイズ",
6 substr(
7 dump("r_blob",16),
8 1,
9 instr(dump("r_blob",16),' ')
10 ) as "dump"
11 from
12 varchar_test_mysql4113a_mac_sv@oracle10g_win
13 where
14* "id" = 30
CORYDORAS> /
select
*
行1でエラーが発生しました。:
ORA-02070: データベースMYSQL4113A_MAC_SVはこのコンテキストではLENGTHをサポートしません。
ORA-02063: 先行のエラー・メッセージを参照してくださいline(ORACLE10G_WIN)。

CORYDORAS>

今日はここまで。

Oracle, Oracle以外のデータベース, Mac, Tiger Server De Oracle10g, 異機種間接続サービス(Oracle Generic Connectivity) | | | コメント (0) | トラックバック (0)

Mac De Oracle Heterogeneous! #73

前回のつづき。Generic Connectivyty経由でMySQL4.1.13aの文字型にアクセス。三回目。

3.varchar型

MySQL4.0.xとは異なり、文字セマンティクスになっているという点以外は注意する点はないだろう。Oracleのvarchat2型にマッピングされている。

1)varchar(20)で、binary属性の有無のみ異なる2列。

CORYDORAS> set null "null"
CORYDORAS> col r_varchar_20 for a40
CORYDORAS> col dump for a20
CORYDORAS> set linesize 132
CORYDORAS> l
1 select
2 "id",
3 "r_varchar_20",
4 length("r_varchar_20") as "文字数",
5 lengthb("r_varchar_20") as "文字サイズ",
6 substr(
7 dump("r_varchar_20",16),
8 1,
9 instr(dump("r_varchar_20",16),' ')
10 ) as "dump"
11 from
12 varchar_test_mysql4113a_mac_sv@oracle10g_win
13 where
14* "id" between 19 and 23
CORYDORAS> /

id r_varchar_20 文字数 文字サイズ dump
---------- ---------------------------------------- ---------- ---------- --------------------
19 あ 2 3 Typ=1
20 null null null null
21 null null null null
22 12345678901234567890 20 20 Typ=1
23 12345678901234567890 20 40 Typ=1

CORYDORAS>
CORYDORAS> col r_varchar_20_binary for a40
CORYDORAS> l
1 select
2 "id",
3 "r_varchar_20_binary",
4 length("r_varchar_20_binary") as "文字数",
5 lengthb("r_varchar_20_binary") as "文字サイズ",
6 substr(
7 dump("r_varchar_20_binary",16),
8 1,
9 instr(dump("r_varchar_20_binary",16),' ')
10 ) as "dump"
11 from
12 varchar_test_mysql4113a_mac_sv@oracle10g_win
13 where
14* "id" between 24 and 28
CORYDORAS> /

id r_varchar_20_binary 文字数 文字サイズ dump
---------- ---------------------------------------- ---------- ---------- --------------------
24 あ 2 3 Typ=1
25 null null null null
26 null null null null
27 12345678901234567890 20 20 Typ=1
28 12345678901234567890 20 40 Typ=1

CORYDORAS>

2)varchar(255)で、binary属性の有無がことなる2列。
CORYDORAS> col r_varchar_255 for a40
CORYDORAS> l
1 select
2 "id",
3 "r_varchar_255",
4 length("r_varchar_255") as "文字数",
5 lengthb("r_varchar_255") as "文字サイズ",
6 substr(
7 dump("r_varchar_255",16),
8 1,
9 instr(dump("r_varchar_255",16),' ')
10 ) as "dump"
11 from
12 varchar_test_mysql4113a_mac_sv@oracle10g_win
13 where
14* "id" = 29
CORYDORAS> /

id r_varchar_255 文字数 文字サイズ dump
---------- ---------------------------------------- ---------- ---------- --------------------
29 **************************************** 255 255 Typ=1
****************************************
****************************************
****************************************
****************************************
****************************************
***************

CORYDORAS>
CORYDORAS> col r_varchar_255_binary for a40
CORYDORAS> l
1 select
2 "id",
3 "r_varchar_255_binary",
4 length("r_varchar_255_binary") as "文字数",
5 lengthb("r_varchar_255_binary") as "文字サイズ",
6 substr(
7 dump("r_varchar_255_binary",16),
8 1,
9 instr(dump("r_varchar_255_binary",16),' ')
10 ) as "dump"
11 from
12 varchar_test_mysql4113a_mac_sv@oracle10g_win
13 where
14* "id" = 29
CORYDORAS> /

id r_varchar_255_binary 文字数 文字サイズ dump
---------- ---------------------------------------- ---------- ---------- --------------------
29 **************************************** 255 255 Typ=1
****************************************
****************************************
****************************************
****************************************
****************************************
***************

CORYDORAS>

MySQL4.1.x以降ではvarchar(256)以上のサイズを定義すると、自動的に text型に変換されるので用注意。

mysql> alter table varchar_test add column r_varchar_256 varchar(256);
Query OK, 34 rows affected, 1 warning (0.92 sec)
Records: 34 Duplicates: 0 Warnings: 0

mysql> desc varchar_test;
+----------------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------------+--------------+------+-----+---------+-------+
| id | int(11) | | PRI | 0 | |
| r_varchar_20 | varchar(20) | YES | | NULL | |
| r_varchar_20_binary | varchar(20) | YES | | NULL | |
| r_varchar_255 | varchar(255) | YES | | NULL | |
| r_varchar_255_binary | varchar(255) | YES | | NULL | |
| r_tinytext | tinytext | YES | | NULL | |
| r_tinyblob | tinyblob | YES | | NULL | |
| r_text | text | YES | | NULL | |
| r_blob | blob | YES | | NULL | |
| r_varchar_256 | text | YES | | NULL | |
+----------------------+--------------+------+-----+---------+-------+
10 rows in set (0.01 sec)

mysql>


今日はここまで、次回へつづく。

| | | コメント (0) | トラックバック (0)

2006年3月22日 (水)

Mac De Oracle Heterogeneous! #72

前回のつづき。Generic Connectivyty経由でMySQL4.1.13aの文字型にアクセス。二回目。

さて、MySQl4.0.xと比べ、文字セマンティクスである点に注意が必要だと書いたが、char(255)及び、char(255) binaryとして定義した列ではその違いを再確認できる。

char(255)と定義すると、MySQL4.1.xでは、文字セマンティクスであることから、255文字(SJISでは510バイト)ということになる。
Generic Connectivity経由で問い合わせた以下結果を見てもらいたい。dump関数が返すデータ型がvarchar2型になっている点に気付いていただけただろうか? 
ODBC Driverが ODBCデータ型である、SQL_CHAR型とSQL_VARCHAR型とのマッピング変更をデータサイズにより変更している。

CORYDORAS> col r_char_255 for a40
CORYDORAS> l
1 select
2 "r_char_255",
3 length("r_char_255") as "文字数",
4 lengthb("r_char_255") as "文字サイズ",
5 substr(
6 dump("r_char_255"),
7 1,
8 instr(dump("r_char_255"),' ')
9 ) as "dump"
10 from
11 char_test_mysql4113a_mac_sv@oracle10g_win
12 where
13* "id" = 11
CORYDORAS> /

r_char_255 文字数 文字サイズ dump
---------------------------------------- ---------- ---------- --------------------
**************************************** 255 255 Typ=1
****************************************
****************************************
****************************************
****************************************
****************************************
***************

CORYDORAS>
CORYDORAS> col r_char_255_binary for a40
CORYDORAS> l
1 select
2 "r_char_255_binary",
3 length("r_char_255_binary") as "文字数",
4 lengthb("r_char_255_binary") as "文字サイズ",
5 substr(
6 dump("r_char_255_binary"),
7 1,
8 instr(dump("r_char_255_binary"),' ')
9 ) as "dump"
10 from
11 char_test_mysql4113a_mac_sv@oracle10g_win
12 where
13* "id" = 11
CORYDORAS> /

r_char_255_binary 文字数 文字サイズ dump
---------------------------------------- ---------- ---------- --------------------
**************************************** 255 255 Typ=1
****************************************
****************************************
****************************************
****************************************
****************************************
***************

CORYDORAS>

char_test表に char(127) と char(128)の2列を追加して検証した結果を以下に示す。
文字セマンティクスでは、キャラクタセットがSJISであれば127文字は254バイト、128文字は256バイトである。

mysql> desc char_test;
+-------------------+-----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+-----------+------+-----+---------+-------+
| id | int(11) | | PRI | 0 | |
| r_char_20 | char(20) | YES | | NULL | |
| r_char_20_binary | char(20) | YES | | NULL | |
| r_char_255 | char(255) | YES | | NULL | |
| r_char_255_binary | char(255) | YES | | NULL | |
| r_char_127 | char(127) | YES | | NULL | |
| r_char_128 | char(128) | YES | | NULL | |
+-------------------+-----------+------+-----+---------+-------+

CORYDORAS> set linesize 132
CORYDORAS>
CORYDORAS> l
1 select
2 "r_char_127",
3 length("r_char_127") as "文字数",
4 lengthb("r_char_127") as "文字サイズ",
5 substr(
6 dump("r_char_127",16),
7 1,
8 instr(dump("r_char_127",16),' ')
9 ) as "dump"
10 from
11 char_test_mysql4113a_mac_sv@oracle10g_win
12 where
13* "id" = 99
CORYDORAS> /

r_char_127 文字数 文字サイズ dump
---------------------------------------- ---------- ---------- --------------------
**************************************** 254 254 Typ=96
****************************************
****************************************
*******

CORYDORAS> col r_char_128 for a40
CORYDORAS> l
1 select
2 "r_char_128",
3 length("r_char_128") as "文字数",
4 lengthb("r_char_128") as "文字サイズ",
5 substr(
6 dump("r_char_128",16),
7 1,
8 instr(dump("r_char_128",16),' ')
9 ) as "dump"
10 from
11 char_test_mysql4113a_mac_sv@oracle10g_win
12 where
13* "id" = 100
CORYDORAS> /

r_char_128 文字数 文字サイズ dump
---------------------------------------- ---------- ---------- --------------------
**************************************** 128 128 Typ=1
****************************************
****************************************
********

CORYDORAS>

予想どおり、127×2=254までは、ODBCのSQL_CHAR型 -> OracleのCHAR型に、128×2=256で ODBCのSQL_VARCHAR型->OracleのVARCHAR2型に、ぞれぞれマッピングされている。

文字列の実サイズは、r_char_128列に登録しているデータの方が短い(この例では)ため、見た目は結構歪なマッピングに見えてしまう・・・・。文字セマンティクスになっている影響がここにも現れている。


今日はここまで、次回につづく。

| | | コメント (0) | トラックバック (0)

2006年3月21日 (火)

Mac De Oracle Heterogeneous! #71

前回のつづき。Generic Connectivyty経由でMySQL4.1.13aの文字型にアクセス。一回目。

2.char型


char(20)及び、char(20) binaryとして定義した列は、Generic Connectivity経由ではOracleのchar型にマッピングされる。
型のマッピングに関してはMySQL4.0.xと同じなので特に問題はなさそうだ。ただし、MySQL4.1.xでは、文字セマンティクスになっているため char(20)と定義した場合には、20文字という意味になり、キャラクタセットがSJISである下記例においては、最大40バイトであるという点に注意が必要である。

CORYDORAS> set null "null"
CORYDORAS> col dump for a20
CORYDORAS> l
1 select
2 "r_char_20",
3 length("r_char_20") as "文字数",
4 lengthb("r_char_20") as "文字サイズ",
5 substr(
6 dump("r_char_20",16),
7 1,
8 instr(dump("r_char_20",16),' ')
9 ) as "dump"
10 from
11 char_test_mysql4113a_mac_sv@oracle10g_win
12 where
13* "id" <=5
CORYDORAS> /

r_char_20 文字数 文字サイズ dump
---------------------------------------- ---------- ---------- --------------------
あ 39 40 Typ=96
null null null null
40 40 Typ=96
12345678901234567890 40 40 Typ=96
12345678901234567890 20 40 Typ=96

CORYDORAS>
CORYDORAS> col r_char_20_binary for a40
CORYDORAS> l
1 select
2 "r_char_20_binary",
3 length("r_char_20_binary") as "文字数",
4 lengthb("r_char_20_binary") as "文字サイズ",
5 substr(
6 dump("r_char_20_binary",16),
7 1,
8 instr(dump("r_char_20_binary",16),' ')
9 ) as "dump"
10 from
11 char_test_mysql4113a_mac_sv@oracle10g_win
12 where
13* "id" between 6 and 10
CORYDORAS> /

r_char_20_binary 文字数 文字サイズ dump
---------------------------------------- ---------- ---------- --------------------
あ 39 40 Typ=96
null null null null
40 40 Typ=96
12345678901234567890 40 40 Typ=96
12345678901234567890 20 40 Typ=96

CORYDORAS>

今日はここまで、次回につづく。

| | | コメント (0) | トラックバック (0)

2006年3月20日 (月)

Mac De Oracle Heterogeneous! #70

前回のつづき。Generic Connectivyty経由でMySQL4.1.13aの文字型にアクセス。準備。

MySQL4.0.13aは、Generic Connectivityを介して以下の経路でアクセスする。
(尚、MySQL4.0.25のまとめは、MySQL4.1.13aのまとめに含める予定である。)

gencon_blog_mac_my

1.準備

MacOSX Serverに構築したMySQL4.1.13aには、char_test表と、varchar_test表を作成してあり、以下のようなデータを登録しておいた。

mysql> select
-> id,
-> r_char_20,
-> r_char_20_binary
-> from
-> char_test;
+----+------------------------------------------+------------------------------------------+
| id | r_char_20 | r_char_20_binary |
+----+------------------------------------------+------------------------------------------+
| 1 | あ | NULL |
| 2 | NULL | NULL |
| 3 | | NULL |
| 4 | 12345678901234567890 | NULL |
| 5 | 12345678901234567890 | NULL |
| 6 | NULL | あ |
| 7 | NULL | NULL |
| 8 | NULL | |
| 9 | NULL | 12345678901234567890 |
| 10 | NULL | 12345678901234567890 |
+----+------------------------------------------+------------------------------------------+
10 rows in set (0.02 sec)

mysql>
mysql> select
-> id,
-> length(r_char_255),
-> length(r_char_255_binary)
-> from
-> char_test
-> where
-> id = 11;
+----+--------------------+---------------------------+
| id | length(r_char_255) | length(r_char_255_binary) |
+----+--------------------+---------------------------+
| 11 | 255 | 255 |
+----+--------------------+---------------------------+
1 row in set (0.07 sec)

mysql>
mysql> select
-> id,
-> r_varchar_20,
-> r_varchar_20_binary
-> from
-> varchar_test;
+----+--------------+---------------------+
| id | r_varchar_20 | r_varchar_20_binary |
+----+--------------+---------------------+
| 1 | C | C |
| 2 | c | c |
| 3 | B | B |
| 4 | b | b |
| 5 | A | A |
| 6 | a | a |
| 7 | お | お |
| 8 | え | え |
| 9 | う | う |
| 10 | い | い |
| 11 | あ | あ |
| 12 | ぉ | ぉ |
| 13 | ぇ | ぇ |
| 14 | ぅ | ぅ |
| 15 | ぃ | ぃ |
| 16 | ぁ | ぁ |
| 17 | NULL | NULL |
| 18 | | |
+----+--------------+---------------------+
18 rows in set (0.00 sec)

mysql>
mysql> select
-> id,
-> r_varchar_20,
-> r_varchar_20_binary
-> from
-> varchar_test
-> where
-> id between 19 and 28;
+----+------------------------------------------+------------------------------------------+
| id | r_varchar_20 | r_varchar_20_binary |
+----+------------------------------------------+------------------------------------------+
| 19 | あ | NULL |
| 20 | NULL | NULL |
| 21 | | NULL |
| 22 | 12345678901234567890 | NULL |
| 23 | 12345678901234567890 | NULL |
| 24 | NULL | あ |
| 25 | NULL | NULL |
| 26 | NULL | |
| 27 | NULL | 12345678901234567890 |
| 28 | NULL | 12345678901234567890 |
+----+------------------------------------------+------------------------------------------+
10 rows in set (0.02 sec)

mysql>
mysql> select
-> id,
-> length(r_varchar_255),
-> length(r_varchar_255_binary)
-> from
-> varchar_test
-> where
-> id = 29;
+----+-----------------------+------------------------------+
| id | length(r_varchar_255) | length(r_varchar_255_binary) |
+----+-----------------------+------------------------------+
| 29 | 255 | 255 |
+----+-----------------------+------------------------------+
1 row in set (0.00 sec)

mysql> select
-> id,
-> length(r_tinytext),
-> length(r_tinyblob)
-> from
-> varchar_test
-> where
-> id = 30;
+----+--------------------+--------------------+
| id | length(r_tinytext) | length(r_tinyblob) |
+----+--------------------+--------------------+
| 30 | 255 | 255 |
+----+--------------------+--------------------+
1 row in set (0.00 sec)

mysql> select
-> id,
-> length(r_text),
-> length(r_blob)
-> from
-> varchar_test
-> where
-> id between 31 and 34;
+----+----------------+----------------+
| id | length(r_text) | length(r_blob) |
+----+----------------+----------------+
| 31 | 2000 | 2000 |
| 32 | 2001 | 2001 |
| 33 | 4000 | 4000 |
| 34 | 4001 | 4001 |
+----+----------------+----------------+
4 rows in set (0.00 sec)

mysql>

今日はここまで、次回へつづく。

| | | コメント (0) | トラックバック (0)

2006年3月19日 (日)

Mac De Oracle Heterogeneous! #69

前回のつづき。Generic Connectivyty経由でMySQL4.0.25の文字型にアクセス。最終回。

3.文字列の登録

varchar型へ、NULL、空文字、' あ '、最大サイズの文字列登録。特に問題になるようなことは無さそうだ。

CORYDORAS> insert into varchar_test_mysql4025_mac@oracle10g_win("id","r_varchar_20") values(100,null);

1行が作成されました。

CORYDORAS> insert into varchar_test_mysql4025_mac@oracle10g_win("id","r_varchar_20") values(101,'');

1行が作成されました。

CORYDORAS> insert into varchar_test_mysql4025_mac@oracle10g_win("id","r_varchar_20") values(102,' あ ');

1行が作成されました。

CORYDORAS> insert into varchar_test_mysql4025_mac@oracle10g_win("id","r_varchar_20") values(103,'12345678901234567890');

1行が作成されました。

CORYDORAS> commit;

コミットが完了しました。


MySQL4.0.25上で実行した場合とは異なり文字列の切り捨てはエラーとして処理される。(バイトセマンティクスなので、varchar(20)では、20バイトを超える文字列はエラーとなる。Generic Connectivity経由でOracleと連携する場合には都合が良さそうだ。)

CORYDORAS> insert into varchar_test_mysql4025_mac@oracle10g_win("id","r_varchar_20")
2 values(104,'12345678901234567890');
insert into varchar_test_mysql4025_mac@oracle10g_win("id","r_varchar_20")
*
行1でエラーが発生しました。:
ORA-28500:
OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC][A0C9] Value for column r_varchar_20 exceeds
column's length.
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(MYSQL4025_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。

CORYDORAS> insert into varchar_test_mysql4025_mac@oracle10g_win("id","r_varchar_20")
2 values(104,'12345678901');
insert into varchar_test_mysql4025_mac@oracle10g_win("id","r_varchar_20")
*
行1でエラーが発生しました。:
ORA-28500:
OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC][A0C9] Value for column r_varchar_20 exceeds
column's length.
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(MYSQL4025_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


20バイト(SJISなので全角なら10文字まで)分のデータを登録しておく。

CORYDORAS> l
1 insert into varchar_test_mysql4025_mac@oracle10g_win("id","r_varchar_20")
2* values(104,'1234567890')
CORYDORAS> /

1行が作成されました。

CORYDORAS> commit;

コミットが完了しました。

CORYDORAS>

char型についても、varchar型と同じデータを登録。

CORYDORAS> insert into char_test_mysql4025_mac@oracle10g_win("id","r_char_20") values(200,null);

1行が作成されました。

CORYDORAS> insert into char_test_mysql4025_mac@oracle10g_win("id","r_char_20") values(201,'');

1行が作成されました。

CORYDORAS> insert into char_test_mysql4025_mac@oracle10g_win("id","r_char_20") values(202,' あ ');

1行が作成されました。

CORYDORAS> insert into char_test_mysql4025_mac@oracle10g_win("id","r_char_20") values(203,'12345678901234567890');

1行が作成されました。

CORYDORAS> insert into char_test_mysql4025_mac@oracle10g_win("id","r_char_20") values(204,'1234567890');

1行が作成されました。

CORYDORAS> commit;

コミットが完了しました。


varchar型と同様、char型でも超過分の文字が切り捨てられて登録される危険性はないようだ。

CORYDORAS> insert into char_test_mysql4025_mac@oracle10g_win("id","r_char_20") values(205,'123456789012345678901');
insert into char_test_mysql4025_mac@oracle10g_win("id","r_char_20") values(205,'123456789012345678901')
*
行1でエラーが発生しました。:
ORA-28500:
OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC][A0C9] Value for column r_char_20 exceeds
column's length.
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(MYSQL4025_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。

CORYDORAS> rollback;

ロールバックが完了しました。


tinytext型、tinyblob型、text型、blob型にもデータを登録。

CORYDORAS> insert into varchar_test_mysql4025_mac@oracle10g_win("id","r_tinytext","r_tinyblob") values(205,'あいう','えお');

1行が作成されました。

CORYDORAS> insert into varchar_test_mysql4025_mac@oracle10g_win("id","r_text","r_blob") values(206,'かきく','けこ');

1行が作成されました。

CORYDORAS> commit;

コミットが完了しました。


Genericn Connectivity経由で登録したデータの確認。(tinytext型、tinyblob型、text型、blob型を除く)

CORYDORAS> select
2 "id",
3 "r_char_20",
4 lengthb("r_char_20") as "bytes"
5 from
6 char_test_mysql4025_mac@oracle10g_win
7 where
8 "id" >= 200;

id r_char_20 bytes
---------- ---------------------------------------- ----------
200 null null
201 20
202 あ 20
203 12345678901234567890 20
204 1234567890 20

CORYDORAS>
CORYDORAS> l
1 select
2 "id",
3 "r_varchar_20",
4 lengthb("r_varchar_20") as "bytes"
5 from
6 varchar_test_mysql4025_mac@oracle10g_win
7 where
8* "id" between 100 and 104
CORYDORAS> /

id r_varchar_20 bytes
---------- ---------------------------------------- ----------
100 null null
101 null null
102 あ 3
103 12345678901234567890 20
104 1234567890 20

CORYDORAS>

tinytext型、tinyblob型、text型、blob型についてはデータ登録だけを行った。MySQL4.1.13aの同型の検証に含める予定である。
次回は、Generic Connectivity経由で、MySQL4.1.13aの文字型にアクセス。

| | | コメント (0) | トラックバック (0)

2006年3月18日 (土)

Mac De Oracle Heterogeneous! #68

前回のつづき。Generic Connectivyty経由でMySQL4.0.25の文字型にアクセス。五回目。

前回のおさらい。
リモートソートが行われる場合と、そうでない場合があるということであった。
異機種間接続サービスにおいて、コストベースオプティマイザが行う最適化に、リモートソートの排除という記述があるのだが、なにもせず常にそれが行われるということでないようだ。

下記、クエリでは、DML全体がリモートで実行されているため、ソートもリモートソートとなり MySQLのbinary属性のないvarchar型のソート結果(つまり、NULLや空文字が昇順で先頭になり、英字大文字小文字を区別しない)となっている。 

CORYDORAS> l
1 select
2 "id",
3 "r_varchar_20"
4 from
5 varchar_test_mysql4025_mac@oracle10g_win
6 where
7 "id" between 1 and 18
8 order by
9* "r_varchar_20"
CORYDORAS> /

id r_varchar_20
---------- ----------------------------------------
17
18
5 A
6 a
3 B
4 b
1 C
2 c
16 ぁ
11 あ
15 ぃ
10 い
14 ぅ
9 う
13 ぇ
8 え
12 ぉ
7 お

18行が選択されました。

実行計画
----------------------------------------------------------
0 SELECT STATEMENT (REMOTE) Optimizer=ALL_ROWS (Cost=53 Card=5 Bytes=175)
1 0 SORT (ORDER BY) (Cost=53 Card=5 Bytes=175)
2 1 REMOTE* (Cost=52 Card=5 Bytes=175) MYSQL4025_MAC

2 SERIAL_FROM_REMOTE SELECT "id","r_varchar_20" FROM "varchar_tes
t" WHERE "id">=1 AND "id"<=18

統計
----------------------------------------------------------
1 recursive calls
0 db block gets
0 consistent gets
0 physical reads
0 redo size
755 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
18 rows processed

ということで、コストベースオプティマイザの動きを制御できないか? といろいろ調べるた結果、下記の書き換えと、ヒントを利用することにした。
ヒントを利用しなくとも、利用する関数によっては Oracle(ローカル)側でソートするようになるのだが、これも状況次第なので、ご自分の環境で十分なテストを行うことをお勧めする。

まず、該当部分だけをインラインビューに書き換える。(これだけでは全てリモートマップされてしまう)

CORYDORAS> l
1 select *
2 from
3 (
4 select
5 "id",
6 "r_varchar_20"
7 from
8 varchar_test_mysql4025_mac@oracle10g_win
9 where
10 "id" between 1 and 18
11 )
12 order by
13* "r_varchar_20"
CORYDORAS> /

id r_varchar_20
---------- ----------------------------------------
17
18
5 A
6 a
3 B
4 b
1 C
2 c
16 ぁ
11 あ
15 ぃ
10 い
14 ぅ
9 う
13 ぇ
8 え
12 ぉ
7 お

18行が選択されました。

実行計画
----------------------------------------------------------
0 SELECT STATEMENT (REMOTE) Optimizer=ALL_ROWS (Cost=53 Card=5 Bytes=175)
1 0 SORT (ORDER BY) (Cost=53 Card=5 Bytes=175)
2 1 REMOTE* (Cost=52 Card=5 Bytes=175) MYSQL4025_MAC

2 SERIAL_FROM_REMOTE SELECT "id","r_varchar_20" FROM "varchar_tes
t" WHERE "id">=1 AND "id"<=18

統計
----------------------------------------------------------
1 recursive calls
0 db block gets
0 consistent gets
0 physical reads
0 redo size
755 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
18 rows processed

CORYDORAS>

次に、異機種間接続機能向けに使えそうなヒントは NO_MERGEヒント、DRIVING_SITEヒント、REMOTE_MAPPEDヒントのようなのだが、REMOTE_MAPPEDヒントは明文化されていないのとクエリをリモートサイトで実行させるためと思われる名称のヒントであるため対象外とした。

まずは、NO_MERGEヒントから試してみた、

CORYDORAS> set autot on
CORYDORAS> l
1 select *
2 from
3 (
4 select /*+ NO_MERGE */
5 "id",
6 "r_varchar_20"
7 from
8 varchar_test_mysql4025_mac@oracle10g_win
9 where
10 "id" between 1 and 18
11 )
12 order by
13* "r_varchar_20"
CORYDORAS> /

id r_varchar_20
---------- ----------------------------------------
5 A
3 B
1 C
6 a
4 b
2 c
16 ぁ
11 あ
15 ぃ
10 い
14 ぅ
9 う
13 ぇ
8 え
12 ぉ
7 お
17
18

18行が選択されました。

実行計画
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=53 Card=5 Bytes=175)
1 0 SORT (ORDER BY) (Cost=53 Card=5 Bytes=175)
2 1 VIEW (Cost=52 Card=5 Bytes=175)
3 2 REMOTE* (Cost=52 Card=5 Bytes=175) ORACLE10G_WIN

3 SERIAL_FROM_REMOTE SELECT "id","r_varchar_20" FROM "VARCHAR_TES
T_MYSQL4025_MAC" "VARCHAR_TEST_MYSQL

統計
----------------------------------------------------------
0 recursive calls
0 db block gets
0 consistent gets
0 physical reads
0 redo size
812 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
18 rows processed

CORYDORAS>
 
思い通りのソート結果を得られた。自動トレースの実行計画、統計情報からソートがローカルデータベース側(つまり、Oracle側)で実行されているという状況を確認できた。


NO_MERGEヒントで目的の結果を得られたので、DRIVING_SITEヒントの確認は省略。
NO_MERGEヒントを利用したクエリとそうでないクエリの実行計画を explain plan文と、utlxpls.sqlスクリプトでさらに確認した結果は以下。

CORYDORAS> l
1 explain plan for
2 select *
3 from
4 (
5 select
6 "id",
7 "r_varchar_20"
8 from
9 varchar_test_mysql4025_mac@oracle10g_win
10 where
11 "id" between 1 and 18
12 )
13 order by
14* "r_varchar_20"
CORYDORAS> /

解析されました。

CORYDORAS> @?/rdbms/admin/utlxpls

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 4028966153

-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT REMOTE| | 5 | 175 | 53 (2)| 00:00:01 |
| 1 | SORT ORDER BY | | 5 | 175 | 53 (2)| 00:00:01 |
| 2 | REMOTE | | 5 | 175 | 52 (0)| 00:00:01 |
-------------------------------------------------------------------------------

Note
-----
- fully remote statement

13行が選択されました。

CORYDORAS> select id,other from plan_table where operation='REMOTE';

ID OTHER
---------- --------------------------------------------------------------------------------
2 SELECT "id","r_varchar_20" FROM "varchar_test" WHERE "id">=1 AND "id"<=18

CORYDORAS>

以下は、NO_MERGEヒントを利用した結果。

CORYDORAS> l
1 explain plan for
2 select *
3 from
4 (
5 select /*+ NO_MERGE */
6 "id",
7 "r_varchar_20"
8 from
9 varchar_test_mysql4025_mac@oracle10g_win
10 where
11 "id" between 1 and 18
12 )
13 order by
14* "r_varchar_20"
CORYDORAS> /

解析されました。

CORYDORAS> @?/rdbms/admin/utlxpls

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 4108374534

-------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5 | 175 | 53 (2)| 00:00:01 |
| 1 | SORT ORDER BY | | 5 | 175 | 53 (2)| 00:00:01 |
| 2 | VIEW | | 5 | 175 | 52 (0)| 00:00:01 |
| 3 | REMOTE | | 5 | 175 | 52 (0)| 00:00:01 |
-------------------------------------------------------------------------

10行が選択されました。

CORYDORAS> select id,other from plan_table where operation='REMOTE';

ID OTHER
---------- --------------------------------------------------------------------------------
3 SELECT "id","r_varchar_20" FROM "VARCHAR_TEST_MYSQL4025_MAC" "VARCHAR_TEST_MYSQL
       4025_MAC" WHERE "id">=1 AND "id"<=18

CORYDORAS>

さらに、プランスタビリティ機能を利用すればアクセスプランを固定化できるはずである。
今日はここまで、次回へつづく。

| | | コメント (0) | トラックバック (0)

2006年3月16日 (木)

Mac De Oracle Heterogeneous! #67

前回のつづき。Generic Connectivyty経由でMySQL4.0.25の文字型にアクセス。四回目。

2.文字列のソート

ソートする前の状態

CORYDORAS> l
1 select
2 "id",
3 "r_varchar_20",
4 dump("r_varchar_20",16) as hex_sjis
5 from
6 varchar_test_mysql4025_mac@oracle10g_win
7 where
8* "id" between 1 and 18
CORYDORAS> /

id r_varchar_20 HEX_SJIS
---------- ---------------------------------------- --------------------
1 C Typ=1 Len=1: 43
2 c Typ=1 Len=1: 63
3 B Typ=1 Len=1: 42
4 b Typ=1 Len=1: 62
5 A Typ=1 Len=1: 41
6 a Typ=1 Len=1: 61
7 お Typ=1 Len=2: 82,a8
8 え Typ=1 Len=2: 82,a6
9 う Typ=1 Len=2: 82,a4
10 い Typ=1 Len=2: 82,a2
11 あ Typ=1 Len=2: 82,a0
12 ぉ Typ=1 Len=2: 82,a7
13 ぇ Typ=1 Len=2: 82,a5
14 ぅ Typ=1 Len=2: 82,a3
15 ぃ Typ=1 Len=2: 82,a1
16 ぁ Typ=1 Len=2: 82,9f
17 NULL
18 NULL

18行が選択されました。

昇順でソートした結果
CORYDORAS> l
1 select
2 "id",
3 "r_varchar_20",
4 dump("r_varchar_20",16) as hex_sjis
5 from
6 varchar_test_mysql4025_mac@oracle10g_win
7 where
8 "id" between 1 and 18
9 order by
10* "r_varchar_20"
CORYDORAS> /

id r_varchar_20 HEX_SJIS
---------- ---------------------------------------- --------------------
5 A Typ=1 Len=1: 41
3 B Typ=1 Len=1: 42
1 C Typ=1 Len=1: 43
6 a Typ=1 Len=1: 61
4 b Typ=1 Len=1: 62
2 c Typ=1 Len=1: 63
16 ぁ Typ=1 Len=2: 82,9f
11 あ Typ=1 Len=2: 82,a0
15 ぃ Typ=1 Len=2: 82,a1
10 い Typ=1 Len=2: 82,a2
14 ぅ Typ=1 Len=2: 82,a3
9 う Typ=1 Len=2: 82,a4
13 ぇ Typ=1 Len=2: 82,a5
8 え Typ=1 Len=2: 82,a6
12 ぉ Typ=1 Len=2: 82,a7
7 お Typ=1 Len=2: 82,a8
17 NULL
18 NULL

18行が選択されました。

MySQL側ではbinary属性がないと大文字小文字は区別されず、nullや、空文字の扱いも異なるためソート結果が異なるのだが、
Generic Connectivity経由ではbinary属性が無い場合でもソート順に問題はなさそうでだ。。
CORYDORAS> l
1 select
2 "id",
3 "r_varchar_20_binary",
4 dump("r_varchar_20_binary",16) as hex_sjis
5 from
6 varchar_test_mysql4025_mac@oracle10g_win
7 where
8 "id" between 1 and 18
9 order by
10* "r_varchar_20_binary"
CORYDORAS>
CORYDORAS>
CORYDORAS> /

id r_varchar_20_binary HEX_SJIS
---------- ---------------------------------------- --------------------
5 A Typ=1 Len=1: 41
3 B Typ=1 Len=1: 42
1 C Typ=1 Len=1: 43
6 a Typ=1 Len=1: 61
4 b Typ=1 Len=1: 62
2 c Typ=1 Len=1: 63
16 ぁ Typ=1 Len=2: 82,9f
11 あ Typ=1 Len=2: 82,a0
15 ぃ Typ=1 Len=2: 82,a1
10 い Typ=1 Len=2: 82,a2
14 ぅ Typ=1 Len=2: 82,a3
9 う Typ=1 Len=2: 82,a4
13 ぇ Typ=1 Len=2: 82,a5
8 え Typ=1 Len=2: 82,a6
12 ぉ Typ=1 Len=2: 82,a7
7 お Typ=1 Len=2: 82,a8
17 NULL
18 NULL

18行が選択されました。

と安心するのはまだ早い!
クエリの書き方によってソート結果が異なるのだ。
以下の結果を見る限り、リモートソート(以下の場合は、MySQL側でソート処理が行われ、リモートソートの排除が行われていない)が行われているということになる。
CORYDORAS> l
1 select
2 "id",
3 "r_varchar_20"
4 from
5 varchar_test_mysql4025_mac@oracle10g_win
6 where
7 "id" between 1 and 18
8 order by
9* "r_varchar_20"
CORYDORAS> /

id r_varchar_20
---------- ----------------------------------------
17 null
18 null
5 A
6 a
3 B
4 b
1 C
2 c
16 ぁ
11 あ
15 ぃ
10 い
14 ぅ
9 う
13 ぇ
8 え
12 ぉ
7 お

18行が選択されました。

以下に、MySQL側で行ったソート結果を示す。
mysql> edit
-> ¥p
--------------
select
id,
r_varchar_20
from
varchar_test
where
id between 1 and 18
order by
r_varchar_20
--------------

-> ¥g
+----+--------------+
| id | r_varchar_20 |
+----+--------------+
| 17 | NULL |
| 18 | |
| 5 | A |
| 6 | a |
| 3 | B |
| 4 | b |
| 1 | C |
| 2 | c |
| 16 | ぁ |
| 11 | あ |
| 15 | ぃ |
| 10 | い |
| 14 | ぅ |
| 9 | う |
| 13 | ぇ |
| 8 | え |
| 12 | ぉ |
| 7 | お |
+----+--------------+
18 rows in set (0.00 sec)

mysql>

常にリモートソートを排除するようなクエリの書き方は存在するのか?
今日はここまで、次回へつづく。

| | | コメント (0) | トラックバック (0)

2006年3月15日 (水)

Mac De Oracle Heterogeneous! #66

前回のつづき。Generic Connectivyty経由でMySQL4.0.25の文字型にアクセス。三回目。

3)tinytext型、tinyblob型、text型、blob型

Oracleで、blob型というとlob型(ラージオブジェクト)をイメージするが、MySQLでは文字型なので少々戸惑う。Generic Connectivity経由ではどの型にマッピングされているのかを確認したところ、PostgreSQLでlong型にマッピングされていた状況に類似したエラーが返される。

CORYDORAS> col r_tinytext for a40
CORYDORAS> l
1 select
2 "r_tinytext",
3 lengthb("r_tinytext") as "bytes",
4 substr(
5 dump("r_tinytext",16),
6 1,
7 instr(dump("r_tinytext",16),' ')
8 ) as "dump"
9 from
10 varchar_test_mysql4025_mac@oracle10g_win
11 where
12* "id" = 30
CORYDORAS> /
select
*
行1でエラーが発生しました。:
ORA-02070: データベースMYSQL4025_MACはこのコンテキストではLENGTHBをサポートしません。
ORA-02063: 先行のエラー・メッセージを参照してくださいline(ORACLE10G_WIN)。

CORYDORAS> col r_tinyblob for a40
CORYDORAS> l
1 select
2 "r_tinyblob",
3 lengthb("r_tinyblob") as "bytes",
4 substr(
5 dump("r_tinyblob",16),
6 1,
7 instr(dump("r_tinyblob",16),' ')
8 ) as "dump"
9 from
10 varchar_test_mysql4025_mac@oracle10g_win
11 where
12* "id" = 30
CORYDORAS> /
select
*
行1でエラーが発生しました。:
ORA-02070: データベースMYSQL4025_MACはこのコンテキストではLENGTHBをサポートしません。
ORA-02063: 先行のエラー・メッセージを参照してくださいline(ORACLE10G_WIN)。

CORYDORAS> col r_text for a40
CORYDORAS> l
1 select
2 "r_text",
3 lengthb("r_text") as "bytes",
4 substr(
5 dump("r_text",16),
6 1,
7 instr(dump("r_text",16),' ')
8 ) as "dump"
9 from
10 varchar_test_mysql4025_mac@oracle10g_win
11 where
12* "id" = 31
CORYDORAS> /
select
*
行1でエラーが発生しました。:
ORA-02070: データベースMYSQL4025_MACはこのコンテキストではLENGTHBをサポートしません。
ORA-02063: 先行のエラー・メッセージを参照してくださいline(ORACLE10G_WIN)。

CORYDORAS> col r_blob for a40
CORYDORAS> l
1 select
2 "r_blob",
3 lengthb("r_blob") as "bytes",
4 substr(
5 dump("r_blob",16),
6 1,
7 instr(dump("r_blob",16),' ')
8 ) as "dump"
9 from
10 varchar_test_mysql4025_mac@oracle10g_win
11 where
12* "id" = 31
CORYDORAS> /
select
*
行1でエラーが発生しました。:
ORA-02070: データベースMYSQL4025_MACはこのコンテキストではLENGTHBをサポートしません。
ORA-02063: 先行のエラー・メッセージを参照してくださいline(ORACLE10G_WIN)。

CORYDORAS>

create table文で確認してみると、はやり、long型にマッピングされている。

CORYDORAS> create table temp_tab as       
2 select "id","r_tinytext" from
3 varchar_test_mysql4025_mac@oracle10g_win
4 where "id" = 30;
select "id","r_tinytext" from
*
行2でエラーが発生しました。:
ORA-00997: LONGデータ型は使用できません。

CORYDORAS> create table temp_tab as
2 select "id","r_tinyblob" from
3 varchar_test_mysql4025_mac@oracle10g_win
4 where "id" = 30;
select "id","r_tinyblob" from
*
行2でエラーが発生しました。:
ORA-00997: LONGデータ型は使用できません。

CORYDORAS> create table temp_tab as
2 select "id","r_text" from
3 varchar_test_mysql4025_mac@oracle10g_win
4 where "id" = 31;
select "id","r_text" from
*
行2でエラーが発生しました。:
ORA-00997: LONGデータ型は使用できません。

CORYDORAS> create table temp_tab as
2 select "id","r_blob" from
3 varchar_test_mysql4025_mac@oracle10g_win
4 where "id" = 31;
select "id","r_blob" from
*
行2でエラーが発生しました。:
ORA-00997: LONGデータ型は使用できません。

CORYDORAS>

MyODBC Driverにはtext型や、blob型の文字列をOracleのvarchar2型にマッピングするようなオプションは存在しないため、直接利用するのであればlong型のまま利用することになる。
MySQL4.0.25 では、PostgreSQLのように、char型や、varchar型で2000バイトや、4000バイトを定義することはできないため、256バイト以上の文字列は、text型か、blob型で定義されている場合が多いと思われる。定義されている表をそのままGeneric Connecvity経由でアクセスするのであれば、long型で利用することになる。
long型で利用するのが不便であれば他の方法を検討するなり、Generic Connectivityを諦める必要はありそうだ。ちなみに、long型にマッピングされているので使いやすいlob型に変換しようと思ってもそう簡単には行かない。
to_lob()関数などの関数はリモート表には利用できないためだ。(long型をうまく扱うための方法を考えなければ。。。)

CORYDORAS> edit
file afiedt.bufが書き込まれました。

1 select
2 "id",to_lob("r_tinytext") as "r_tinytext"
3 from
4 varchar_test_mysql4025_mac@oracle10g_win
5 where
6* "id" = 30
CORYDORAS> /
"id",to_lob("r_tinytext") as "r_tinytext"
*
行2でエラーが発生しました。:
ORA-22992: リモート表から選択されたLOBロケータは使用できません。


今日はここまで。

===================================
いろいろな伏線を張ったまま、放置する可能性もあるので、ご注意を。m(_ _)m 
Generic Connectiviyを利用するどうかの判断は、MySQL、PostgreSQLやODBCのバージョン、プラットフォームに影響される上、実際にどのようなスキーマを持っているかがポイントになる。従って、一概にMySQL4.0.xだから適用できるとか、PostgreSQLだと今ひとつだとか、言い切ることができない。
実システム又は、同等のテスト環境を利用し検証した結果を元に判断するしか無い、というのが現実である。
うまくハマれば、便利な機能であるのも事実。その分かれ目を見極めるためにも検証作業が大切。

| | | コメント (0) | トラックバック (0)

2006年3月14日 (火)

Mac De Oracle Heterogeneous! #65

前回のつづき。Generic Connectivyty経由でMySQL4.0.25の文字型にアクセス。二回目。

1.マッピングされる型の確認

Generic Connectivity経由でMySQL4.0.25の文字型がOracleのどの型にマップされるかを確認。

1)char型

MySQL4.0.25でchar(20)、char(20) binary、char(255)、char(255) binaryとして定義した場合、Oracle側ではchar型にマッピングされる。

CORYDORAS> set null "null"
CORYDORAS> l
1 select
2 "r_char_20",
3 lengthb("r_char_20") as "bytes",
4 substr(
5 dump("r_char_20",16),
6 1,
7 instr(dump("r_char_20",16),' ')
8 ) as "dump"
9 from
10 char_test_mysql4025_mac@oracle10g_win
11 where
12* "id" <= 5
CORYDORAS> /

r_char_20 bytes dump
---------------------------------------- ---------- ----------
あ 20 Typ=96
null null null
20 Typ=96
12345678901234567890 20 Typ=96
1234567890 20 Typ=96

CORYDORAS>
CORYDORAS> l
1 select
2 "r_char_20_binary",
3 lengthb("r_char_20_binary") as "bytes",
4 substr(
5 dump("r_char_20_binary",16),
6 1,
7 instr(dump("r_char_20_binary",16),' ')
8 ) as "dump"
9 from
10 char_test_mysql4025_mac@oracle10g_win
11 where
12* "id" between 6 and 10
CORYDORAS> /

r_char_20_binary bytes dump
---------------------------------------- ---------- ----------
あ 20 Typ=96
null null null
20 Typ=96
12345678901234567890 20 Typ=96
1234567890 20 Typ=96

CORYDORAS>
CORYDORAS> l
1 select
2 "r_char_255",
3 lengthb("r_char_255") as "bytes",
4 substr(
5 dump("r_char_255",16),
6 1,
7 instr(dump("r_char_255",16),' ')
8 ) as "dump"
9 from
10 char_test_mysql4025_mac@oracle10g_win
11 where
12* "id" = 11
CORYDORAS> /

r_char_255 bytes dump
---------------------------------------- ---------- ----------
**************************************** 255 Typ=96
****************************************
****************************************
****************************************
****************************************
****************************************
***************

CORYDORAS>
CORYDORAS> col r_char_255_binary for a40
CORYDORAS> l
1 select
2 "r_char_255_binary",
3 lengthb("r_char_255_binary") as "bytes",
4 substr(
5 dump("r_char_255_binary",16),
6 1,
7 instr(dump("r_char_255_binary",16),' ')
8 ) as "dump"
9 from
10 char_test_mysql4025_mac@oracle10g_win
11 where
12* "id" = 11
CORYDORAS> /

r_char_255_binary bytes dump
---------------------------------------- ---------- ----------
**************************************** 255 Typ=96
****************************************
****************************************
****************************************
****************************************
****************************************
***************

CORYDORAS>


2)varchar型

MySQL4.0.25で、varchar(20)、varchar(20) binary、varchar(255)、varchar(255) binaryとして定義した場合、Oracle側では varchar2型にマッピングされる。

CORYDORAS> l
1 select
2 "r_varchar_20",
3 lengthb("r_varchar_20") as "bytes",
4 substr(
5 dump("r_varchar_20",16),
6 1,
7 instr(dump("r_varchar_20",16),' ')
8 ) as "dump"
9 from
10 varchar_test_mysql4025_mac@oracle10g_win
11 where
12* "id" between 19 and 23
CORYDORAS> /

r_varchar_20 bytes dump
---------------------------------------- ---------- ----------
あ 3 Typ=1
null null null
null null null
12345678901234567890 20 Typ=1
1234567890 20 Typ=1

CORYDORAS>
CORYDORAS> l
1 select
2 "r_varchar_20_binary",
3 lengthb("r_varchar_20_binary") as "bytes",
4 substr(
5 dump("r_varchar_20_binary",16),
6 1,
7 instr(dump("r_varchar_20_binary",16),' ')
8 ) as "dump"
9 from
10 varchar_test_mysql4025_mac@oracle10g_win
11 where
12* "id" between 24 and 28
CORYDORAS> /

r_varchar_20_binary bytes dump
---------------------------------------- ---------- ----------
あ 3 Typ=1
null null null
null null null
12345678901234567890 20 Typ=1
1234567890 20 Typ=1

CORYDORAS>
CORYDORAS> col r_varchar_255 for a40
CORYDORAS> l
1 select
2 "r_varchar_255",
3 lengthb("r_varchar_255") as "bytes",
4 substr(
5 dump("r_varchar_255",16),
6 1,
7 instr(dump("r_varchar_255",16),' ')
8 ) as "dump"
9 from
10 varchar_test_mysql4025_mac@oracle10g_win
11 where
12* "id" = 29
CORYDORAS> /

r_varchar_255 bytes dump
---------------------------------------- ---------- ----------
**************************************** 255 Typ=1
****************************************
****************************************
****************************************
****************************************
****************************************
***************

CORYDORAS>
CORYDORAS> col r_varchar_255_binary for a40
CORYDORAS> l
1 select
2 "r_varchar_255_binary",
3 lengthb("r_varchar_255_binary") as "bytes",
4 substr(
5 dump("r_varchar_255_binary",16),
6 1,
7 instr(dump("r_varchar_255_binary",16),' ')
8 ) as "dump"
9 from
10 varchar_test_mysql4025_mac@oracle10g_win
11 where
12* "id" = 29
CORYDORAS> /

r_varchar_255_binary bytes dump
---------------------------------------- ---------- ----------
**************************************** 255 Typ=1
****************************************
****************************************
****************************************
****************************************
****************************************
***************

CORYDORAS>

今日はここまで。

| | | コメント (0) | トラックバック (0)

2006年3月13日 (月)

Mac De Oracle Heterogeneous! #64

前回のつづき
今回から、Generic Connectivity経由でPowerBook G4 MacOSX 10.4.5のMySQL4.0.25及び、PowerMac G5 Dual2.7GhzのMySQL4.1.13aの文字型にアクセスし、その挙動を検証する。

アクセス経路は以下

gencon_blog_mac_my


MySQL4.0.25及び、MySQL4.1.13aには、以前の記事で解説したような理由から、このような2表を作成してある。

Generic Connectivyty経由でMySQL4.0.25の文字型にアクセス。一回目。

MySQL4.0.25のchar_test表には以下のデータを登録しておく。

mysql> select
-> id,
-> r_char_20,
-> r_char_20_binary
-> from
-> char_test;
+----+----------------------+----------------------+
| id | r_char_20 | r_char_20_binary |
+----+----------------------+----------------------+
| 1 | あ | NULL |
| 2 | NULL | NULL |
| 3 | | NULL |
| 4 | 12345678901234567890 | NULL |
| 5 | 1234567890 | NULL |
| 6 | NULL | あ |
| 7 | NULL | NULL |
| 8 | NULL | |
| 9 | NULL | 12345678901234567890 |
| 10 | NULL | 1234567890 |
+----+----------------------+----------------------+
10 rows in set (0.02 sec)

mysql>
mysql> select
-> id,
-> length(r_char_255),
-> length(r_char_255_binary)
-> from
-> char_test
-> where
-> id = 11;
+----+--------------------+---------------------------+
| id | length(r_char_255) | length(r_char_255_binary) |
+----+--------------------+---------------------------+
| 11 | 255 | 255 |
+----+--------------------+---------------------------+
1 row in set (0.26 sec)

mysql>

MySQL4.0.25のvarchar_test表には以下のデータを登録しておく。

mysql> select
-> id,
-> r_varchar_20,
-> r_varchar_20_binary
-> from
-> varchar_test;
+----+--------------+---------------------+
| id | r_varchar_20 | r_varchar_20_binary |
+----+--------------+---------------------+
| 1 | C | C |
| 2 | c | c |
| 3 | B | B |
| 4 | b | b |
| 5 | A | A |
| 6 | a | a |
| 7 | お | お |
| 8 | え | え |
| 9 | う | う |
| 10 | い | い |
| 11 | あ | あ |
| 12 | ぉ | ぉ |
| 13 | ぇ | ぇ |
| 14 | ぅ | ぅ |
| 15 | ぃ | ぃ |
| 16 | ぁ | ぁ |
| 17 | NULL | NULL |
| 18 | | |
+----+--------------+---------------------+
18 rows in set (0.00 sec)

mysql>
mysql> select
-> id,
-> r_varchar_20,
-> r_varchar_20_binary
-> from
-> varchar_test
-> where
-> id between 19 and 28;
+----+----------------------+----------------------+
| id | r_varchar_20 | r_varchar_20_binary |
+----+----------------------+----------------------+
| 19 | あ | NULL |
| 20 | NULL | NULL |
| 21 | | NULL |
| 22 | 12345678901234567890 | NULL |
| 23 | 1234567890 | NULL |
| 24 | NULL | あ |
| 25 | NULL | NULL |
| 26 | NULL | |
| 27 | NULL | 12345678901234567890 |
| 28 | NULL | 1234567890 |
+----+----------------------+----------------------+
10 rows in set (0.42 sec)

mysql>
mysql> select
-> id,
-> length(r_varchar_255),
-> length(r_varchar_255_binary),
-> length(r_tinytext),
-> length(r_tinyblob),
-> length(r_text),
-> length(r_blob)
-> from
-> varchar_test
-> where
-> id between 29 and 34;
+----+-----------------------+------------------------------+--------------------+--------------------+----------------+----------------+
| id | length(r_varchar_255) | length(r_varchar_255_binary) | length(r_tinytext) | length(r_tinyblob) | length(r_text) | length(r_blob) |
+----+-----------------------+------------------------------+--------------------+--------------------+----------------+----------------+
| 29 | 255 | 255 | NULL | NULL | NULL | NULL |
| 30 | NULL | NULL | 255 | 255 | NULL | NULL |
| 31 | NULL | NULL | NULL | NULL | 2000 | 2000 |
| 32 | NULL | NULL | NULL | NULL | 2001 | 2001 |
| 33 | NULL | NULL | NULL | NULL | 4000 | 4000 |
| 34 | NULL | NULL | NULL | NULL | 4001 | 4001 |
+----+-----------------------+------------------------------+--------------------+--------------------+----------------+----------------+
6 rows in set (0.01 sec)

mysql>


準備が出来たところで、つづきは次回。

| | | コメント (0) | トラックバック (0)

2006年3月12日 (日)

Mac De Oracle Heterogeneous! #63

続きです。Generic Connectivity経由でPostgreSQL7.4.9の文字型にアクセス 最終回のつづき(なんじゃそりゃ)。

=========まとめ=======

利用しているODBC driverはこちらで解説しているドライバー

Generic Connectivityの文字型マッピング
PostgreSQL7.4.9Oracle10g R1Generic Connectivityでの利用備 考
char型 char型 PostgreSQLでのchar型の定義とODBCデータソースのvarchar型最大サイズの設定によりマップされる型が異なる。

char(n)の n が、ODBC データソースの設定でVARCHAR型最大サイズ以下である場合、char型にマップされる。

ただし、本テストでは、n=1024でvarchar2型にマップされた。(255〜1024のどの値でchar型からvarchar2型に切り替わるのかは未確認。単なるバグなのか??)。

n > ODBCデータソースの設定のVARCHRA型最大サイズである場合には、long型にマップされる。

また、Oracle側にマッピングされる際は、常にバイトセマンティクスとして解釈されるため、PostgreSQL側の文字型にマルチバイトが格納されている場合且つ、バイトサイズが n を超える文字は切り捨てられる点に注意すること。そのような列をアクセスする必要がある場合には、PostgreSQL側の影響がなければ、PostgreSQL側の文字型の最大サイズを大きくすることで対応可能だろう。また、これも影響がないことが前提だが、text型に変更して文字の切り捨てを防ぐという方法も使えるかもしれないが、その場合、long型にマッピングされるので要注意。影響が大きくそのような対処ができないのならば、Generic Connectivityを利用せず、外部表を利用したり他の方法を考えたほうが無難。ストアドプロシージャを利用して解決する方法もあるかもしれないが未確認である。
varchar2型
long型
varchar型 varchar2型 PostgreSQLでのvarchar型の定義とODBCデータソースのvarchar型最大サイズの設定によりマップされる型が異なる。

varchar(n)の n が、ODBC データソースの設定でVARCHAR型最大サイズ以下である場合、varchar型にマップされる。

n > ODBCデータソースの設定のVARCHRA型最大サイズである場合には、long型にマップされる。

また、Oracle側にマッピングされる際は、常にバイトセマンティクスとして解釈されるため、PostgreSQL側の文字型にマルチバイトが格納されている場合且つ、バイトサイズが n を超える文字は切り捨てられる点に注意すること。そのような列をアクセスする必要がある場合には、PostgreSQL側の影響がなければ、PostgreSQL側の文字型の最大サイズを大きくすることで対応可能だろう。また、これも影響がないことが前提だが、text型に変更して文字の切り捨てを防ぐという方法も使えるかもしれないが、その場合、long型にマッピングされるので要注意。影響が大きくそのような対処ができないのならば、Generic Connectivityを利用せず、外部表を利用したり他の方法を考えたほうが無難。ストアドプロシージャを利用して解決する方法もあるかもしれないが未確認である。
long型
text型 long型 通常は、long型にマッピングされるが、ODBCデータソーソの設定で、「text型を長文字列として扱う」をチェックしなければ、varchar2型にマッピング(本当にマッピングされるか未確認。m(_ _)m )される。
varchar2型
(未確認)

ソート時の注意
PostgreSQLでは、空文字は、NULLとは区別されているが、Oracleは、空文字をNULLとして扱うので注意が必要である。例として検索時に、 where 列名 = '' 又は、 where 列名 != ''と記述した場合、Oracleでは、 列名 = NULL 又は、列名 != NULLと解釈され不定され正しい結果は得られない、 '' は利用せず、 列名 IS NULL又は、 列名 IS NOT NULLと書くべし。(Oracleを長年利用してきた方ならば間違うことはない事なのだが・・・)

次回、こんどこそ本当にMySQLの文字型にアクセスへつづく。

| | | コメント (0) | トラックバック (0)

2006年3月11日 (土)

Mac De Oracle Heterogeneous! #62

続きです。Generic Connectivity経由でPostgreSQL7.4.9の文字型にアクセス 最終回。

5)文字ソート

空文字は、Oracle側では、NULLとして扱われる点に注意。

CORYDORAS> l
1 select
2 "id",
3 "r_varchar_20",
4 lengthb("r_varchar_20"),
5 dump("r_varchar_20",16) as hex_sjis
6 from
7 char_test_postgresql749_mac@oracle10g_win
8 where
9 "id" between 1 and 18
10 order by
11* "r_varchar_20"
CORYDORAS> /

id r_varchar_20 LENGTHB("R_VARCHAR_20") HEX_SJIS
---------- -------------------- ----------------------- --------------------
5 A 1 Typ=1 Len=1: 41
3 B 1 Typ=1 Len=1: 42
1 C 1 Typ=1 Len=1: 43
6 a 1 Typ=1 Len=1: 61
4 b 1 Typ=1 Len=1: 62
2 c 1 Typ=1 Len=1: 63
16 ぁ 2 Typ=1 Len=2: 82,9f
11 あ 2 Typ=1 Len=2: 82,a0
15 ぃ 2 Typ=1 Len=2: 82,a1
10 い 2 Typ=1 Len=2: 82,a2
14 ぅ 2 Typ=1 Len=2: 82,a3
9 う 2 Typ=1 Len=2: 82,a4
13 ぇ 2 Typ=1 Len=2: 82,a5
8 え 2 Typ=1 Len=2: 82,a6
12 ぉ 2 Typ=1 Len=2: 82,a7
7 お 2 Typ=1 Len=2: 82,a8
17 NULL NULL NULL
18 NULL NULL NULL

18行が選択されました。

CORYDORAS>

=======おまけ========

6) 文字を登録。

利用できる関数はかなり制限されているのだが、DMLをパススルーしてやればなんとかなるだろうね。(以前実験済み

CORYDORAS> list
1 insert into char_test_postgresql749_mac@oracle10g_win("id","r_varchar_4000")
2 values(101,lpad('*',4000,'*'))
CORYDORAS> /
insert into char_test_postgresql749_mac@oracle10g_win("id","r_varchar_4000")
*
行1でエラーが発生しました。:
ORA-02070: データベースPOSTGRESQL749_MACはこのコンテキストではLPADをサポートしません。
ORA-02063: 先行のエラー・メッセージを参照してくださいline(ORACLE10G_WIN)。


CORYDORAS> insert into
2 char_test_postgresql749_mac@oracle10g_win("id","r_varchar_20")
3 values(101,'01234567890');
insert into
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC][A0C9] Value for column r_varchar_20 exceeds column's length.
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> edit
file afiedt.bufが書き込まれました。

1 insert into
2 char_test_postgresql749_mac@oracle10g_win("id","r_varchar_20")
3* values(101,'0123456789')
CORYDORAS> /

1行が作成されました。

CORYDORAS> rollback;

ロールバックが完了しました。

CORYDORAS>
CORYDORAS> insert into
2 char_test_postgresql749_mac@oracle10g_win("id","r_char_20")
3 values(101,'012345678901234567890');
insert into
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC][A0C9] Value for column r_char_20 exceeds column's length.
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> edit
file afiedt.bufが書き込まれました。

1 insert into
2 char_test_postgresql749_mac@oracle10g_win("id","r_char_20")
3* values(101,'01234567890123456789')
CORYDORAS> /

1行が作成されました。


次回、Generic Connectivity経由でPostgreSQL7.4.9の文字型をアクセスする場合の注意点などのまとめへつづく。

| | | コメント (0) | トラックバック (0)

2006年3月10日 (金)

Mac De Oracle Heterogeneous! #61

続きです。Generic Connectivity経由でPostgreSQL7.4.9の文字型にアクセス 五回目。

前回は、PostgreSQL7.4.9のchar(2000)がOracleのlong型にマッピングされているという状況だった。
ということで、PostgreSQL7.4.9のchar型、varchar型が、Oracleのchar型又は、varchar2型にマッピングされるのか、long型にマッピングされるのか? その境界値を探る。また、その値を変更することは可能なのかも合わせて調査する。(ODBCの影響が一番強いと思うのだが。。。)

4−1)100バイトは?
char(100)及び、varchar(100)として定義したデータは、それぞれ、Oracleのchar型、varchar2型として 問い合わせる事ができた。

CORYDORAS> select dump("char100") from char_len_tet_postgresql749_mac@oracle10g_win;

DUMP("CHAR100")
--------------------------------------------------------------------------------
Typ=96 Len=100: 42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,4
2,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,
42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42
,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42

CORYDORAS> select dump("varchar100") from char_len_tet_postgresql749_mac@oracle10g_win;

DUMP("VARCHAR100")
--------------------------------------------------------------------------------
Typ=1 Len=100: 42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42
,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,4
2,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,
42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42

4−2)255バイトではどう?
char(255)として定義した列は LONG型にマッピングされている。101文字以上255文字未満ということのようだ。

CORYDORAS> select dump("char255") from char_len_tet_postgresql749_mac@oracle10g_win;
select dump("char255") from char_len_tet_postgresql749_mac@oracle10g_win
*
行1でエラーが発生しました。:
ORA-02070:
データベースPOSTGRESQL749_MACはこのコンテキストではDUMPをサポートしません。
ORA-02063: 先行のエラー・メッセージを参照してくださいline(ORACLE10G_WIN)。


そこで、思い出したのが、psqlODBCのデータソースの設定。

odbc_before

4−3)じゃ、254バイトまでだな!!
varcharの最大サイズが254文字に設定されているので char(254)として定義した列を問い合わせると、正しく問い合わせる事ができた。

CORYDORAS> select dump("char254") from char_len_tet_postgresql749_mac@oracle10g_win;

DUMP("CHAR254")
--------------------------------------------------------------------------------
Typ=96 Len=254: 42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,4
2,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,

中略

,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,4
2,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,
42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42
,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42

4−4)ODBCのvarchar型の最大サイズを4000バイトにしてみた!

psqlODBCの設定を254から 4000に変更した。

odbc_after


char(254)はいままで通りで問題ない。

CORYDORAS> select dump("char254") from char_len_tet_postgresql749_mac@oracle10g_win;

DUMP("CHAR254")
--------------------------------------------------------------------------------
Typ=96 Len=254: 42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,4
2,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,
42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42
,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,4
2,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,

中略

42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42
,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42

さて、次が問題なのだが、お〜〜。うまく問い合わせることができた。

CORYDORAS> select dump("char255") from char_len_tet_postgresql749_mac@oracle10g_win;

DUMP("CHAR255")
--------------------------------------------------------------------------------
Typ=96 Len=255: 42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,4
2,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,

中略

42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42
,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42

char(1024)として定義した列なのでが、Oracle側のchar型ではなく、varchar2型にマッピングされてはいるものの、問題なく問い合わせることができた。(Oracleのchar型ではなく、varchar2型にマッピングされてしまったことによる問題は多少あるだろうね)
CORYDORAS> select dump("char1024") from char_len_tet_postgresql749_mac@oracle10g_win;

DUMP("CHAR1024")
--------------------------------------------------------------------------------
Typ=1 Len=1024: 42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,4
2,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,
42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42

中略

42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,4
2,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,
42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42

varchar(1024)として定義した列も正常に問い合わせることができた。こちらもvarchar2型にマッピングされた。

CORYDORAS> select dump("varchar1024") from char_len_tet_postgresql749_mac@oracle10g_win;

DUMP("VARCHAR1024")
--------------------------------------------------------------------------------
Typ=1 Len=1024: 42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,4
2,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,
42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42

中略

,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,4
2,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,
42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42

CORYDORAS>

PostgreSQL7.4.9のchar型及び、varchar型をGeneric Connectivity経由で利用する場合には、psqlODBCのvarchar型の最大サイズの調整しないと、255バイト以上のデータはSQL_LONGVARCHARというODBCデータ型にマッピングされ、結果的に、Oracle型ではLONG型にマッピングされる。psqlODBCのvarchar型最大サイズを調整すればなんとか対応できそうではある。(ODBC Driver次第なので、不安もあるが・・・ま、いいか。)
とちょっとだけ、ほっとしたところで、次回へつづく。

| | | コメント (0) | トラックバック (0)

2006年3月 9日 (木)

Mac De Oracle Heterogeneous! #60

続きです。Generic Connectivity経由でPostgreSQL7.4.9の文字型にアクセス 四回目。

4)Oracleのchar型、varchar2型の最大サイズ及び、それを超えるサイズで定義した列にアクセス。

以下、問い合わせた結果。

CORYDORAS> select 
2 "id",
3 lengthb("r_char_2000"),
4 lengthb("r_char_2001"),
5 lengthb("r_varchar_4000"),
6 lengthb("r_varchar_4001")
7 from
8 char_test_postgresql749_mac@oracle10g_win
9 where
10 "id" between 34 and 35;
select
*
行1でエラーが発生しました。:
ORA-02070: データベースPOSTGRESQL749_MACはこのコンテキストではLENGTHBをサポートしません。
ORA-02063: 先行のエラー・メッセージを参照してくださいline(ORACLE10G_WIN)。

おや? これは、text型の時と同じ症状?!にみえる。

CORYDORAS> edit
file afiedt.bufが書き込まれました。

1 select
2 "id",
3 "r_char_2000"
4 from
5 char_test_postgresql749_mac@oracle10g_win
6 where
7* "id" between 34 and 35
CORYDORAS> /

id r_char_2000
---------- --------------------------------------------------------------------------------
34 ********************************************************************************
35 NULL

単純に問い合わせる事はできるようだ。とすると・・・・・。

CORYDORAS> create table temp1
2 as select "id","r_char_2000"
3 from char_test_postgresql749_mac@oracle10g_win
4 where "id" = 34;
as select "id","r_char_2000"
*
行2でエラーが発生しました。:
ORA-00997: LONGデータ型は使用できません。

やっぱり! long型にマッピングされている!

ちなみに、以下すべてが long型にマッピングされている。char(20)やvarchar(20)ではchar型、varchar2型にマッピングされていたが、long型に切り替えられる境界は? その境界を調整できるのだろうか?(別途調査予定)

CORYDORAS> edit
file afiedt.bufが書き込まれました。

1 create table temp1
2 as select "id","r_char_2001"
3 from char_test_postgresql749_mac@oracle10g_win
4* where "id" = 34
CORYDORAS> /
as select "id","r_char_2001"
*
行2でエラーが発生しました。:
ORA-00997: LONGデータ型は使用できません。


CORYDORAS> edit
file afiedt.bufが書き込まれました。

1 create table temp1
2 as select "id","r_varchar_4000"
3 from char_test_postgresql749_mac@oracle10g_win
4* where "id" = 35
CORYDORAS> /
as select "id","r_varchar_4000"
*
行2でエラーが発生しました。:
ORA-00997: LONGデータ型は使用できません。


CORYDORAS> edit
file afiedt.bufが書き込まれました。

1 create table temp1
2 as select "id","r_varchar_4001"
3 from char_test_postgresql749_mac@oracle10g_win
4* where "id" = 35
CORYDORAS> /
as select "id","r_varchar_4001"
*
行2でエラーが発生しました。:
ORA-00997: LONGデータ型は使用できません。


CORYDORAS>

さてどうしよう・・・・。


次回へつづく。

| | | コメント (0) | トラックバック (0)

2006年3月 8日 (水)

Mac De Oracle Heterogeneous! #59

続きです。Generic Connectivity経由でPostgreSQL7.4.9の文字型にアクセス 三回目。

3)text型として定義した列を問い合わせる

以下、問い合わせた結果。

CORYDORAS> select
2 "id",
3 lengthb("r_text"),
4 length("r_text"),
5 substr(dump("r_text",16),1,7),
6 "r_text"
7 from
8 char_test_postgresql749_mac@oracle10g_win
9 where
10 "id" between 29 and 33;
select
*
行1でエラーが発生しました。:
ORA-02070: データベースPOSTGRESQL749_MACはこのコンテキストではLENGTHBをサポートしません。
ORA-02063: 先行のエラー・メッセージを参照してくださいline(ORACLE10G_WIN)。

CORYDORAS> edit
file afiedt.bufが書き込まれました。

1 select
2 "id",
3 substr(dump("r_text",16),1,7),
4 "r_text"
5 from
6 char_test_postgresql749_mac@oracle10g_win
7 where
8* "id" between 29 and 33
CORYDORAS> /
select
*
行1でエラーが発生しました。:
ORA-02070: データベースPOSTGRESQL749_MACはこのコンテキストではSUBSTRをサポートしません。
ORA-02063: 先行のエラー・メッセージを参照してくださいline(ORACLE10G_WIN)。

CORYDORAS> edit
file afiedt.bufが書き込まれました。

1 select
2 "id",
3 "r_text"
4 from
5 char_test_postgresql749_mac@oracle10g_win
6 where
7* "id" between 29 and 33
CORYDORAS> /

id r_text
---------- --------------------------------------------------------------------------------
29 あ
30 NULL
31 NULL
32 12345678901234567890
33 12345678901234567890

CORYDORAS> edit
file afiedt.bufが書き込まれました。

1 select
2 "id",
3 dump("r_text",16),
4 "r_text"
5 from
6 char_test_postgresql749_mac@oracle10g_win
7 where
8* "id" between 29 and 33
CORYDORAS> /
select
*
行1でエラーが発生しました。:
ORA-02070: データベースPOSTGRESQL749_MACはこのコンテキストではDUMPをサポートしません。
ORA-02063: 先行のエラー・メッセージを参照してくださいline(ORACLE10G_WIN)。

CORYDORAS> create table temp as
2 select
3 "id",
4 "r_text"
5 from
6 char_test_postgresql749_mac@oracle10g_win
7 where
8 "id" between 29 and 33;
"r_text"
*
行4でエラーが発生しました。:
ORA-00997: LONGデータ型は使用できません。

CORYDORAS>

PostgreSQLのtext型は、Oracleのlong型にマッピングされる。
単純に問い合わせるだけならchar(20)や、varchar(20)の場合のような文字の切り捨ては発生しないためよさそうなのだが、long型は対応している関数が少ないので注意が必要だ。(他の型、例えば、CLOB型などに変換してから利用すれば使い勝手もよくできるかもしれないが、さらに検証が必要だ。)


今日はここまで。次回へつづく。

| | | コメント (0) | トラックバック (0)

2006年3月 7日 (火)

Mac De Oracle Heterogeneous! #58

続きです。Generic Connectivity経由でPostgreSQL7.4.9の文字型にアクセス 二回目。

1. char型

1) char(20)として定義した列を問い合わせる

以下、問い合わせた結果。

CORYDORAS> set null 'NULL'
CORYDORAS> list
1 select
2 "id",
3 lengthb("r_char_20"),
4 length("r_char_20"),
5 substr(dump("r_char_20",16),1,7),
6 "r_char_20"
7 from
8 char_test_postgresql749_mac@oracle10g_win
9 where
10* "id" between 19 and 23
CORYDORAS> /

id LENGTHB("R_CHAR_20") LENGTH("R_CHAR_20") SUBSTR(DUMP("R r_char_20
---------- -------------------- ------------------- -------------- --------------------
19 20 19 Typ=96 あ
20 NULL NULL NULL NULL
21 20 20 Typ=96
22 20 20 Typ=96 12345678901234567890
23 20 10 Typ=96 1234567890

CORYDORAS>

char(20)は、Oracle側のchar型にマップされている。 
PostgreSQL上で問い合わせた結果と比較すると、文字数やバイト数が1文字及び1バイトづつ少ない。ODBCの問題である可能性も無いとは言えないが、Oracleはバイトセマンティクスでchar(20)をハンドリングしているようにみえる。id=19,23のデータは文字が切り捨てられている点に注意してもらいたい。ただ、20バイトで単純に切り捨てられているということではなく、文字列として20バイト以内に収まる文字数で切り捨てられているようにも見える。'1234567890123456789あ' という20文字を登録しておき、Generic Connectivity経由でOralce側から問い合わせると、'1234567890123456789'が返されたためだなのだが、状況証拠だけなので偶々という可能性もある。尚、alter session文で、バイトセマンティクスから文字セマンティクスに変更しても状況は変わらない。
PostgreSQLのchar(20)を Oracleのchar(20 char)にマッピングする回避方法はあるのか? 無理矢理だがPostgreSQL側のchar(20)をchar(40)へ変更してしまうという方法で回避できるようならそれでもよいかもしれないが、列サイズの変更により既存プログラムへの影響が懸念される。それ以外の方法としては外部表がお手軽かもしれない。他にはパススルークエリーを利用すればなんとかなるか??。(パススルークエリを利用した回避方法は別途調査してみるか・・)


2)varchar(20)として定義した列を問い合わせる

以下、問い合わせた結果

CORYDORAS> l
1 select
2 "id",
3 lengthb("r_varchar_20"),
4 length("r_varchar_20"),
5 substr(dump("r_varchar_20",16),1,7),
6 "r_varchar_20"
7 from
8 char_test_postgresql749_mac@oracle10g_win
9 where
10* "id" between 24 and 28
CORYDORAS> /

id LENGTHB("R_VARCHAR_20") LENGTH("R_VARCHAR_20") SUBSTR(DUMP("R r_varchar_20
---------- ----------------------- ---------------------- -------------- --------------------
24 4 3 Typ=1 L あ
25 NULL NULL NULL NULL
26 NULL NULL NULL NULL
27 20 20 Typ=1 L 12345678901234567890
28 20 10 Typ=1 L 1234567890

CORYDORAS>

varchar(20)は、Oracleのvarchar2型にマップされている。注意する点は、char(20)のid=23のデータと同じ。

今日はここまで。次回につづく。

| | | コメント (0) | トラックバック (0)

2006年3月 6日 (月)

Mac De Oracle Heterogeneous! #57

前回のつづき、Generic Connectivity経由でPostgreSQL7.4.9の文字型にアクセス 一回目。

アクセス経路は以下の通り。

gencon_blog_mac_pos

PostgreSQL7.4.9には以下のような表を作成した。
Oracleへのマッピングも考慮し、Oracleのchar型及び、varchar2型の最大サイズ及び、最大サイズを超えるサイズで定義した。

postgresql749=> ¥d char_test;
Table "scott.char_test"
Column | Type | Modifiers
----------------+-------------------------+-----------
id | integer | not null
r_char_20 | character(20) |
r_char_2000 | character(2000) |
r_char_2001 | character(2001) |
r_varchar_20 | character varying(20) |
r_varchar_4000 | character varying(4000) |
r_varchar_4001 | character varying(4001) |
r_text | text |
Indexes:
"char_test_pkey" primary key, btree (id)

postgresql749=>

事前に以下のデータを登録してある。

 id | r_varchar_20 | octet_length | hex_euc | hex_sjis | hex_utf8 
----+--------------+--------------+---------+----------+----------
18 | | 0 | | |
5 | A | 1 | 41 | 41 | 41
3 | B | 1 | 42 | 42 | 42
1 | C | 1 | 43 | 43 | 43
6 | a | 1 | 61 | 61 | 61
4 | b | 1 | 62 | 62 | 62
2 | c | 1 | 63 | 63 | 63
16 | ぁ | 2 | a4a1 | 829f | e38181
11 | あ | 2 | a4a2 | 82a0 | e38182
15 | ぃ | 2 | a4a3 | 82a1 | e38183
10 | い | 2 | a4a4 | 82a2 | e38184
14 | ぅ | 2 | a4a5 | 82a3 | e38185
9 | う | 2 | a4a6 | 82a4 | e38186
13 | ぇ | 2 | a4a7 | 82a5 | e38187
8 | え | 2 | a4a8 | 82a6 | e38188
12 | ぉ | 2 | a4a9 | 82a7 | e38189
7 | お | 2 | a4aa | 82a8 | e3818a
17 | | | | |
(18 rows)

postgresql749=>

postgresql749=> select
postgresql749-> id,
postgresql749-> r_char_20,
postgresql749-> length(r_char_20) as length,
postgresql749-> octet_length(r_char_20) as octet_length
postgresql749-> from
postgresql749-> char_test
postgresql749-> where
postgresql749-> id between 19 and 23;
id | r_char_20 | length | octet_length
----+------------------------------------------+--------+--------------
19 | あ | 20 | 21
20 | | |
21 | | 20 | 20
22 | 12345678901234567890 | 20 | 20
23 | 12345678901234567890 | 20 | 40
(5 rows)

postgresql749=>

postgresql749=> select
postgresql749-> id,
postgresql749-> r_varchar_20,
postgresql749-> length(r_varchar_20) as length,
postgresql749-> octet_length(r_varchar_20) as octet_length
postgresql749-> from
postgresql749-> char_test
postgresql749-> where
postgresql749-> id between 24 and 28;
id | r_varchar_20 | length | octet_length
----+------------------------------------------+--------+--------------
24 | あ | 3 | 4
25 | | |
26 | | 0 | 0
27 | 12345678901234567890 | 20 | 20
28 | 12345678901234567890 | 20 | 40
(5 rows)

postgresql749=>

postgresql749=> select
postgresql749-> id,
postgresql749-> r_text,
postgresql749-> length(r_text) as length,
postgresql749-> octet_length(r_text) as octet_length
postgresql749-> from
postgresql749-> char_test
postgresql749-> where
postgresql749-> id between 29 and 33;
id | r_text | length | octet_length
----+------------------------------------------+--------+--------------
29 | あ | 3 | 4
30 | | |
31 | | 0 | 0
32 | 12345678901234567890 | 20 | 20
33 | 12345678901234567890 | 20 | 40
(5 rows)

postgresql749=>

postgresql749=> select
postgresql749-> octet_length(r_char_2000),
postgresql749-> octet_length(r_char_2001),
postgresql749-> octet_length(r_varchar_4000),
postgresql749-> octet_length(r_varchar_4001)
postgresql749-> from
postgresql749-> char_test
postgresql749-> where
postgresql749-> id between 34 and 35;
octet_length | octet_length | octet_length | octet_length
--------------+--------------+--------------+--------------
2000 | 2001 | |
| | 4000 | 4001
(2 rows)

postgresql749=>

次回へつづく。

| | | コメント (0) | トラックバック (0)

2006年3月 5日 (日)

Mac De Oracle Heterogeneous! #56

前回からのつづき。Generic Connectivity経由でMySQL4.0.25、MySQL4.1.13a及び、PostgreSQL7.4.9の文字型にアクセス。(準備)

まず、Windows XP上で踏み台にするOracle10g にMySQL4.0.25、MySQL4.1.13a及び、PostgreSQL7.4.9の各表をアクセスするためのシノニムを作成する。(この例では、プライベートシノニム)

Generic Connectivity用のデータベースリンクを介してアクセスする各表をシノニムとして定義し、
そのシノニムへMacOSX上のOracle10gからOracleの分散データベース機能を利用してアクセスする。この方法で、現時点ではGeneric Connectivityが実装されていないMacOSX上のOracle10gから異機種データベースをアクセスする。

尚、Generic Connectivity経由で、MySQL4.1.13aへ発行する count()関数は正しい結果を得られないためrownum疑似列をmax()関数で取得するという方法で代用している。

作業は赤で囲んだOracle10g上で行っている。

gencon_blog_win_ora


SQL> create synonym char_test_postgresql749_mac for "char_test"@postgresql749_mac;

シノニムが作成されました。

SQL> create synonym char_test_mysql4025_mac for "char_test"@mysql4025_mac;

シノニムが作成されました。

SQL> create synonym varchar_test_mysql4025_mac for "varchar_test"@mysql4025_mac;

シノニムが作成されました。

SQL> create synonym char_test_mysql4113a_mac_sv for "char_test"@mysql4113a_mac_sv;

シノニムが作成されました。

SQL> create synonym varchar_test_mysql4113a_mac_sv for "varchar_test"@mysql4113a_mac_sv;

シノニムが作成されました。

SQL> select synonym_name,table_name,substr(db_link,1,20) as db_link from user_synonyms;

SYNONYM_NAME TABLE_NAME DB_LINK
------------------------------ -------------------- --------------------
EMP_MYSQL4025_MAC emp MYSQL4025_MAC
INNO_EMP_MYSQL4025_MAC inno_emp MYSQL4025_MAC
EMP_MYSQL4026_WIN emp MYSQL4026_WIN
EMP_MYSQL4113A_MAC_SV emp MYSQL4113A_MAC_SV
EMP_POSTGRESQL749_MAC emp POSTGRESQL749_MAC
ORACLE_EMP_MYSQL4026_WIN oracle_emp MYSQL4026_WIN
DATE_TEST_MYSQL4026_WIN date_test MYSQL4026_WIN
DATE_TEST_MYSQL4113A_MAC_SV date_test MYSQL4113A_MAC_SV
DATE_TEST_POSTGRESQL749_MAC date_test POSTGRESQL749_MAC
NUM_TEST_POSTGRESQL749_MAC num_test POSTGRESQL749_MAC
NUM_TEST_MYSQL4113A_MAC_SV num_test MYSQL4113A_MAC_SV
NUM_TEST_MYSQL4025_MAC num_test MYSQL4025_MAC
CHAR_TEST_POSTGRESQL749_MAC char_test POSTGRESQL749_MAC
CHAR_TEST_MYSQL4025_MAC char_test MYSQL4025_MAC
VARCHAR_TEST_MYSQL4025_MAC varchar_test MYSQL4025_MAC
CHAR_TEST_MYSQL4113A_MAC_SV char_test MYSQL4113A_MAC_SV
VARCHAR_TEST_MYSQL4113A_MAC_SV varchar_test MYSQL4113A_MAC_SV

17行が選択されました。

SQL>
SQL> select count(*) from char_test_postgresql749_mac;

COUNT(*)
----------
35

SQL> select count(*) from char_test_mysql4025_mac;

COUNT(*)
----------
11

SQL> select count(*) from varchar_test_mysql4025_mac;

COUNT(*)
----------
34

SQL> select count(*) from char_test_mysql4113a_mac_sv;

COUNT(*)
----------
12593

SQL> select count(*) from varchar_test_mysql4113a_mac_sv;

COUNT(*)
----------
13363

SQL> select max(rownum) from char_test_mysql4113a_mac_sv;

MAX(ROWNUM)
-----------
11

SQL> select max(rownum) from varchar_test_mysql4113a_mac_sv;

MAX(ROWNUM)
-----------
34

SQL>

Windows上で、Generic Connectivityの接続を確認できたので、MacOSXのOracle10gから、WindowsのOracle10g経由で各データベースへの接続を確認する。
Generic Connectivity経由でアクセスする経路は以下の通り。

gencon_blog_my_pos


尚、Generic Connectivity経由で、MySQL4.1.13aへ発行する count()関数は正しい結果を得られないためrownum疑似列をmax()関数で取得するという方法で代用している。

SYS> conn corydoras
パスワードを入力してください:
接続されました。
CORYDORAS>
CORYDORAS>
CORYDORAS>
CORYDORAS> select db_link from user_db_links;

DB_LINK
--------------------------------------------------------------------------------
ORACLE10G_WIN

CORYDORAS> select synonym_name from user_synonyms;

レコードが選択されませんでした。


CORYDORAS> select count(*) from char_test_postgresql749_mac@oracle10g_win;

COUNT(*)
----------
35

CORYDORAS> select count(*) from char_test_mysql4025_mac@oracle10g_win;

COUNT(*)
----------
11

CORYDORAS> select count(*) from varchar_test_mysql4025_mac@oracle10g_win;

COUNT(*)
----------
34

CORYDORAS> select count(*) from char_test_mysql4113a_mac_sv@oracle10g_win;

COUNT(*)
----------
12593

CORYDORAS> select max(rownum) from char_test_mysql4113a_mac_sv@oracle10g_win;

MAX(ROWNUM)
-----------
11

CORYDORAS> select count(*) from varchar_test_mysql4113a_mac_sv@oracle10g_win;

COUNT(*)
----------
13363

CORYDORAS> select max(rownum) from varchar_test_mysql4113a_mac_sv@oracle10g_win;

MAX(ROWNUM)
-----------
34

CORYDORAS>

Generic Connectivity経由の接続を確認することができた。
次回、Generic Connectivity経由でPostgreSQLの文字型にアクセス 一回目につづく。

| | | コメント (0) | トラックバック (0)

2006年3月 4日 (土)

Mac De Oracle Heterogeneous! #55

前回の続き。

MySQLの文字型の最終回。

今回はbinary属性の有無によるソート結果の違いを確認する。

登録したデータは以下。(id列は登録順に昇順とした)

insert into varchar_test(id, r_varchar_20) values(1,'C');
insert into varchar_test(id, r_varchar_20) values(2,'c');
insert into varchar_test(id, r_varchar_20) values(3,'B');
insert into varchar_test(id, r_varchar_20) values(4,'b');
insert into varchar_test(id, r_varchar_20) values(5,'A');
insert into varchar_test(id, r_varchar_20) values(6,'a');
insert into varchar_test(id, r_varchar_20) values(7,'お');
insert into varchar_test(id, r_varchar_20) values(8,'え');
insert into varchar_test(id, r_varchar_20) values(9,'う');
insert into varchar_test(id, r_varchar_20) values(10,'い');
insert into varchar_test(id, r_varchar_20) values(11,'あ');
insert into varchar_test(id, r_varchar_20) values(12,'ぉ');
insert into varchar_test(id, r_varchar_20) values(13,'ぇ');
insert into varchar_test(id, r_varchar_20) values(14,'ぅ');
insert into varchar_test(id, r_varchar_20) values(15,'ぃ');
insert into varchar_test(id, r_varchar_20) values(16,'ぁ');

binary属性が無い場合、char型、varchar型は英字大文字小文字を区別しない。(MySQL4.0.25、MySQL4.1.13aとも同じ)
mysql> 
mysql> select
-> id,
-> r_varchar_20,
-> hex(r_varchar_20) as hex_sjis
-> from
-> varchar_test
-> where
-> id between 1 and 16
-> order by
-> r_varchar_20;
+----+--------------+----------+
| id | r_varchar_20 | hex_sjis |
+----+--------------+----------+
| 5 | A | 41 |
| 6 | a | 61 |
| 3 | B | 42 |
| 4 | b | 62 |
| 1 | C | 43 |
| 2 | c | 63 |
| 16 | ぁ | 829F |
| 11 | あ | 82A0 |
| 15 | ぃ | 82A1 |
| 10 | い | 82A2 |
| 14 | ぅ | 82A3 |
| 9 | う | 82A4 |
| 13 | ぇ | 82A5 |
| 8 | え | 82A6 |
| 12 | ぉ | 82A7 |
| 7 | お | 82A8 |
+----+--------------+----------+
16 rows in set (0.07 sec)

mysql>

binary属性付きの場合、英字大文字に続き、英字小文字の順にソートされる。

mysql> select
-> id,
-> r_varchar_20_binary,
-> hex(r_varchar_20_binary) as hex_sjis
-> from
-> varchar_test
-> where
-> id between 17 and 32
-> order by
-> r_varchar_20_binary;
+----+---------------------+----------+
| id | r_varchar_20_binary | hex_sjis |
+----+---------------------+----------+
| 21 | A | 41 |
| 19 | B | 42 |
| 17 | C | 43 |
| 22 | a | 61 |
| 20 | b | 62 |
| 18 | c | 63 |
| 32 | ぁ | 829F |
| 27 | あ | 82A0 |
| 31 | ぃ | 82A1 |
| 26 | い | 82A2 |
| 30 | ぅ | 82A3 |
| 25 | う | 82A4 |
| 29 | ぇ | 82A5 |
| 24 | え | 82A6 |
| 28 | ぉ | 82A7 |
| 23 | お | 82A8 |
+----+---------------------+----------+
16 rows in set (0.00 sec)

mysql>



ちなみに、Oracleで同じことを行うとのと同じ結果になるのは、binary属性があるchar型又は、varchar型なのである。
SQL> list
1 select
2 string,
3 dump(string, 16) as "hex"
4 from
5 test
6 order by
7 string
SQL> /

STRING hex
------ ------------------------------
A Typ=1 Len=1: 41
B Typ=1 Len=1: 42
C Typ=1 Len=1: 43
a Typ=1 Len=1: 61
b Typ=1 Len=1: 62
c Typ=1 Len=1: 63
ぁ Typ=1 Len=2: 82,9f
あ Typ=1 Len=2: 82,a0
ぃ Typ=1 Len=2: 82,a1
い Typ=1 Len=2: 82,a2
ぅ Typ=1 Len=2: 82,a3
う Typ=1 Len=2: 82,a4
ぇ Typ=1 Len=2: 82,a5
え Typ=1 Len=2: 82,a6
ぉ Typ=1 Len=2: 82,a7
お Typ=1 Len=2: 82,a8

16行が選択されました。


さらにおまけ。
Oracleでは、nlssort()関数を利用した言語ソートを行うこともできる。

SQL> list
1 select
2 string,
3 dump(string, 16) as "hex"
4 from
5 test
6 order by
7 nlssort(string, 'NLS_SORT = japanese')
SQL> /

STRING hex
------ ------------------------------
a Typ=1 Len=1: 61
A Typ=1 Len=1: 41
b Typ=1 Len=1: 62
B Typ=1 Len=1: 42
c Typ=1 Len=1: 63
C Typ=1 Len=1: 43
ぁ Typ=1 Len=2: 82,9f
あ Typ=1 Len=2: 82,a0
ぃ Typ=1 Len=2: 82,a1
い Typ=1 Len=2: 82,a2
ぅ Typ=1 Len=2: 82,a3
う Typ=1 Len=2: 82,a4
ぇ Typ=1 Len=2: 82,a5
え Typ=1 Len=2: 82,a6
ぉ Typ=1 Len=2: 82,a7
お Typ=1 Len=2: 82,a8


ということで、簡単だったが、MySQL4.0.25及び、4.1.13aでの文字型の検証は終わり。(なんとなくPostgreSQLがステキに見えてくる。というのもMySQLが独特な世界を持っているからか?)

次回、PostgreSQLとMySQLの文字型をGeneric Connectivity経由でアクセスへつづく。

| | | コメント (0) | トラックバック (0)

2006年3月 3日 (金)

Mac De Oracle Heterogeneous! #54

前回の続き。

MySQLの文字型の四回目。

1.varchar型の検証

1−1 MySQL4.0.25での検証

1)' あ '、 null、 空文字、シングルバイト文字を20文字登録。

空白の扱いを確認するため、”あ”の前後に空白を付加し、' あ ' として登録した

mysql> insert into varchar_test(id, r_varchar_20) values(33,' ¥202¥240 ');
Query OK, 1 row affected (0.01 sec)
現在リリースされているMacOSXのTerminalは、マルチバイトを入力するとエスケープシーケンスになってしまう。実際に入力しているのは以下のDML。
insert into varchar_test(id, r_varchar_20) values(33, ' あ ');
mysql> 
insert into varchar_test(id, r_varchar_20) values(34,null);
Query OK, 1 row affected (0.00 sec)

mysql> insert into varchar_test(id, r_varchar_20) values(35,'');
Query OK, 1 row affected (0.00 sec)

mysql> insert into varchar_test(id, r_varchar_20) values(36,'12345678901234567890');
Query OK, 1 row affected (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

2)シングルバイト文字で21文字を登録

PostgreSQLとは異なりワーニングもエラーも発生しない。Generic Connectivity経由での登録は要注意だ。

mysql> insert into varchar_test(id, r_varchar_20) values(37,'123456789012345678901');
Query OK, 1 row affected (0.00 sec)

3)マルチバイト文字で20文字を登録。

データベースキャラクタセットはSJISなので実際には40バイトになる文字列なのだが、これも正常?に実行された。

mysql> 
mysql> insert into varchar_test(id, r_varchar_20)
-> values(38,'¥202P¥202Q¥202R¥202S¥202T¥202U¥202V¥202W¥202X¥202O¥202P¥202Q¥202R¥202S¥202T¥202U¥202V¥202W02X¥202O');
Query OK, 1 row affected (0.00 sec)
Terminalは、マルチバイトを入力するとエスケープシーケンスになってしまう。実際に入力しているのは以下のDML。
insert into varchar_test(id, r_varchar_20) values(38,'12345678901234567890');

4)マルチバイト文字で21文字を登録。

実際には42バイトになる文字列なのでだが正常の実行されてしまった。列は20バイトまでと定義しているのだが

mysql> 
mysql> insert into varchar_test(id, r_varchar_20)
-> values(39,'¥202P¥202Q¥202R¥202S¥202T¥202U¥202V¥202W¥202X¥202O¥202P¥202Q¥202R¥202S¥202T¥202U¥202V¥202W02X¥202O¥202P');
Query OK, 1 row affected (0.00 sec)
Terminalは、マルチバイトを入力するとエスケープシーケンスになってしまう。実際に入力しているのは以下のDML。
insert into varchar_test(id, r_varchar_20) values(39,'123456789012345678901');

5)文字数、バイトサイズの確認

PostgreSQLの場合と比べて文字数とバイト数が異なることに気付いただろうか?
MySQL4.0.25のchar型と同じなのだ。このリリースのMySQLでは、varchar型とchar型の差が無いことに改めて気付く。

mysql> 
mysql> select
-> id,
-> r_varchar_20,
-> char_length(r_varchar_20) as char_length,
-> length(r_varchar_20) as length
-> from
-> varchar_test
-> where
-> id between 33 and 39;
+----+----------------------+-------------+--------+
| id | r_varchar_20 | char_length | length |
+----+----------------------+-------------+--------+
| 33 | あ | 2 | 3 |
| 34 | NULL | NULL | NULL |
| 35 | | 0 | 0 |
| 36 | 12345678901234567890 | 20 | 20 |
| 37 | 12345678901234567890 | 20 | 20 |
| 38 | 1234567890 | 10 | 20 |
| 39 | 1234567890 | 10 | 20 |
+----+----------------------+-------------+--------+
7 rows in set (0.00 sec)

mysql>
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)

mysql>


1−2 MySQL4.1.13aでの検証

1)' あ '、 null、 空文字、シングルバイト文字を20文字登録。

空白の扱いを確認するため、”あ”の前後に空白を付加し、' あ ' として登録した。

mysql> insert into varchar_test(id, r_varchar_20) values(33,' ¥202¥240 ');
Query OK, 1 row affected (0.00 sec)
現在リリースされているMacOSXのTerminalは、マルチバイトを入力するとエスケープシーケンスになってしまう。実際に入力しているのは以下のDML。
insert into varchar_test(id, r_varchar_20) values(33, ' あ ');
mysql> insert into varchar_test(id, r_varchar_20) values(34,null);
Query OK, 1 row affected (0.00 sec)

mysql> insert into varchar_test(id, r_varchar_20) values(35,'');
Query OK, 1 row affected (0.00 sec)

mysql> insert into varchar_test(id, r_varchar_20) values(36,'12345678901234567890');
Query OK, 1 row affected (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.07 sec)

2)シングルバイト文字で21文字を登録

MySQL4.0.25とは異なりワーニングが発生するが、Generic Connectivity経由ではワーニングが拾えないので要注意だ。

mysql> insert into varchar_test(id, r_varchar_20) values(37,'123456789012345678901');
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> show warnings;
+---------+------+------------------------------------------------+
| Level | Code | Message |
+---------+------+------------------------------------------------+
| Warning | 1265 | Data truncated for column 'r_char_20' at row 1 |
+---------+------+------------------------------------------------+
1 row in set (0.00 sec)


3)マルチバイト文字を20文字登録(登録内容はMySQL4.0.25と同じ)

正常に実行される。

mysql> 
mysql> insert into varchar_test(id, r_varchar_20)
-> values(38,'¥202P¥202Q¥202R¥202S¥202T¥202U¥202V¥202W¥202X¥202O¥202P¥202Q¥202R¥202S¥202T¥202U¥202V¥202W¥202X¥202O');
Query OK, 1 row affected (0.00 sec)

4)マルチバイト文字を21文字登録(登録内容はMySQL4.0.25と同じ)

文字列が制限を超えるとワーニングがでるようにはなっているが、4.1.xではここまで。ワーニングを拾ってロールバックしなければ、commitされてしまうため文字列が切り捨てられたことすら、気がつかないという状況もありえるので要注意。MySQL5.0.2以降ならばsql_mode='TRADITIONAL'にすればエラー扱いにすることも可能なようだが、4.x台では無理だ。今までの経験から warningは、Generic Connectivity経由では拾えないので、Generic Connectivity経由での登録や更新は要注意だ。

mysql> 
mysql> insert into varchar_test(id, r_varchar_20)
-> values(39,'¥202P¥202Q¥202R¥202S¥202T¥202U¥202V¥202W¥202X¥202O¥202P¥202Q¥202R¥202S¥202T¥202U¥202V¥202W¥202X¥202O¥202P');
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> show warnings;
+---------+------+------------------------------------------------+
| Level | Code | Message |
+---------+------+------------------------------------------------+
| Warning | 1265 | Data truncated for column 'r_char_20' at row 1 |
+---------+------+------------------------------------------------+
1 row in set (0.00 sec)

5)文字数、バイトサイズの確認

MySQL4.1.x以降、varchar(n)の n は、文字数を意味するので MySQL4.0.xの文字列とは物理サイズが異なる点に注意。

mysql> 
mysql> select
-> id,
-> r_varchar_20,
-> char_length(r_varchar_20) as char_length,
-> length(r_varchar_20) as length
-> from
-> varchar_test
-> where
-> id between 33 and 39;
+----+------------------------------------------+-------------+--------+
| id | r_varchar_20 | char_length | length |
+----+------------------------------------------+-------------+--------+
| 33 | あ | 2 | 3 |
| 34 | NULL | NULL | NULL |
| 35 | | 0 | 0 |
| 36 | 12345678901234567890 | 20 | 20 |
| 37 | 12345678901234567890 | 20 | 20 |
| 38 | 12345678901234567890 | 20 | 40 |
| 39 | 12345678901234567890 | 20 | 40 |
+----+------------------------------------------+-------------+--------+
6 rows in set (0.00 sec)

mysql>
mysql> rollback;
Query OK, 0 rows affected (0.05 sec)

mysql>

MySQLのvarchar型でもchar型同様、後半の空白をトリムする仕様となっているので注意が必要だ。
マニュアルによると、後半の空白が必要な場合には、text型を利用する必要があるとの記述がある。なんだ?!


text型やblob型が、Generic Connectivity経由で利用できるか不明なのだが、簡単な検証を行っておく。

2.text型とblob型の検証

text型やblob型はOracleなどで言うラージオブジェクトとは別ものらしく、文字列型に分類されている。(ん〜〜〜〜〜。と、うなってみたりして・・)

mysql> insert into varchar_test(id,r_text) values(37,'¥202¥240¥202¥242¥202¥244');
Query OK, 1 row affected (0.00 sec)

mysql> insert into varchar_test(id,r_blob) values(38,'¥202¥240¥202¥242¥202¥244');
Query OK, 1 row affected (0.00 sec)


text型は文字数はマルチバイトで3文字と認識されているが、blob型では6文字と認識される。

mysql> select
-> id,
-> r_text,
-> hex(r_text),
-> char_length(r_text) as ¥203o¥203C¥203g¥220¥224,
-> length(r_text) as ¥225¥266¥216¥232¥220¥224
-> from
-> varchar_test
-> where
-> id = 37;
+----+--------+--------------+----------+----------+
| id | r_text | hex(r_text) | 文字数 | バイト数 |
+----+--------+--------------+----------+----------+
| 37 | あいう | 82A082A282A4 | 3 | 6 |
+----+--------+--------------+----------+----------+
1 row in set (0.00 sec)

mysql> select
-> id,
-> r_blob,
-> hex(r_blob),
-> char_length(r_blob) as ¥203o¥203C¥203g¥220¥224,
-> length(r_blob) as ¥225¥266¥216¥232¥220¥224
-> from
-> varchar_test
-> where
-> id = 38;
+----+--------+--------------+----------+----------+
| id | r_blob | hex(r_blob) | 文字数 | バイト数 |
+----+--------+--------------+----------+----------+
| 38 | あいう | 82A082A282A4 | 6 | 6 |
+----+--------+--------------+----------+----------+
1 row in set (0.00 sec)

mysql>


今日はここまで、次回につづく。

| | | コメント (0) | トラックバック (0)

2006年3月 2日 (木)

Mac De Oracle Heterogeneous! #53

前回の続き。

MySQLの文字型の三回目。

1.char型の検証

1−1 MySQL4.0.25での検証

1)' あ '、 null、 空文字、シングルバイト文字を20文字登録。

空白の扱いを確認するため、”あ”の前後に空白を付加し、' あ ' として登録した。

mysql> insert into char_test(id, r_char_20) values(1,' ¥202¥240 ');
Query OK, 1 row affected (0.00 sec)
現在リリースされているMacOSXのTerminalは、マルチバイトを入力するとエスケープシーケンスになってしまう。実際に入力しているのは以下のDML。
insert into char_test(id, r_char_20) values(1, ' あ ');
mysql> insert into char_test(id, r_char_20) values(2,null);
Query OK, 1 row affected (0.00 sec)

mysql> insert into char_test(id, r_char_20) values(3,'');
Query OK, 1 row affected (0.00 sec)

mysql> insert into char_test(id, r_char_20) values(4,'12345678901234567890');
Query OK, 1 row affected (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.01 sec)

2)シングルバイト文字で21文字を登録

PostgreSQLとは異なりワーニングもエラーも発生しない。Generic Connectivity経由での登録は要注意だ。

mysql> insert into char_test(id, r_char_20) values(5,'123456789012345678901');
Query OK, 1 row affected (0.00 sec)

3)マルチバイト文字で20文字を登録。

データベースキャラクタセットはSJISなので実際には40バイトになる文字列なのだが、これも正常?に実行された。

mysql> insert into char_test(id, r_char_20) 
-> values(6,'¥202P¥202Q¥202R¥202S¥202T¥202U¥202V¥202W¥202X¥202O¥202P¥202Q¥202R¥202S¥202T¥202U¥202V¥202W2X¥202O');
Query OK, 1 row affected (0.00 sec)
現在リリースされているMacOSXのTerminalは、マルチバイトを入力するとエスケープシーケンスになってしまう。実際に入力しているのは以下のDML。
insert into char_test(id, r_char_20) values(6,'12345678901234567890');

4)マルチバイト文字で21文字を登録。

実際には42バイトになる文字列なのでだが正常の実行されてしまった。列は20バイトまでと定義しているのだが。

mysql> 
mysql> insert into char_test(id, r_char_20)
-> values(7,'¥202P¥202Q¥202R¥202S¥202T¥202U¥202V¥202W¥202X¥202O¥202P¥202Q¥202R¥202S¥202T¥202U¥202V¥202W2X¥202O¥202P');
Query OK, 1 row affected (0.01 sec)
現在リリースされているMacOSXのTerminalは、マルチバイトを入力するとエスケープシーケンスになってしまう。実際に入力しているのは以下のDML。
insert into char_test(id, r_char_20) values(7,'123456789012345678901');

5)文字数、バイトサイズの確認

PostgreSQLの場合と比べて文字数とバイト数が異なることに気付いただろうか?
MySQL4.0.25のchar型では、文字につづく空白が切り捨てられる。空文字を設定した場合も空文字が設定されている。

mysql> 
mysql> select
-> id,
-> r_char_20,
-> char_length(r_char_20) as char_length,
-> length(r_char_20) as length
-> from
-> char_test
-> where
-> id <= 7;
+----+----------------------+-------------+--------+
| id | r_char_20 | char_length | length |
+----+----------------------+-------------+--------+
| 1 | あ | 2 | 3 |
| 2 | NULL | NULL | NULL |
| 3 | | 0 | 0 |
| 4 | 12345678901234567890 | 20 | 20 |
| 5 | 12345678901234567890 | 20 | 20 |
| 6 | 1234567890 | 10 | 20 |
| 7 | 1234567890 | 10 | 20 |
+----+----------------------+-------------+--------+
7 rows in set (0.00 sec)

mysql>
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)

mysql>


1−2 MySQL4.1.13aでの検証

1)' あ '、 null、 空文字、シングルバイト文字を20文字登録。

空白の扱いを確認するため、”あ”の前後に空白を付加し、' あ ' として登録した。

mysql> insert into char_test(id, r_char_20) values(1,' ¥202¥240 ');
Query OK, 1 row affected (0.00 sec)
現在リリースされているMacOSXのTerminalは、マルチバイトを入力するとエスケープシーケンスになってしまう。実際に入力しているのは以下のDML。
insert into char_test(id, r_char_20) values(1, ' あ ');
mysql> insert into char_test(id, r_char_20) values(2,null);
Query OK, 1 row affected (0.00 sec)

mysql> insert into char_test(id, r_char_20) values(3,'');
Query OK, 1 row affected (0.00 sec)

mysql> insert into char_test(id, r_char_20) values(4,'12345678901234567890');
Query OK, 1 row affected (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.06 sec)

2)シングルバイト文字を21文字登録

MySQL4.0.xとは異なり、ワーニングが返されるが、それ以外の違いはない。

mysql> insert into char_test(id, r_char_20) values(5,'123456789012345678901');
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> show warnings;
+---------+------+------------------------------------------------+
| Level | Code | Message |
+---------+------+------------------------------------------------+
| Warning | 1265 | Data truncated for column 'r_char_20' at row 1 |
+---------+------+------------------------------------------------+
1 row in set (0.00 sec)


3)マルチバイト文字を20文字登録(登録内容はMySQL4.0.25と同じ)

正常に実行される。

mysql> insert into char_test(id, r_char_20) 
-> values(6,'¥202P¥202Q¥202R¥202S¥202T¥202U¥202V¥202W¥202X¥202O¥202P¥202Q¥202R¥202S¥202T¥202U¥202V¥202W¥202X¥202O');
Query OK, 1 row affected (0.00 sec)


4)マルチバイト文字を21文字登録(登録内容はMySQL4.0.25と同じ)

文字列が制限を超えるとワーニングがでるようにはなっているが、4.1.xではここまで。ワーニングを拾ってロールバックしなければ、commitされてしまうため文字列が切り捨てられたことすら、気がつかないという状況もありえるので要注意。MySQL5.0.2以降ならばsql_mode='TRADITIONAL'にすればエラー扱いにすることも可能なようだが、4.x台では無理だ。今までの経験から warningは、Generic Connectivity経由では拾えないので、Generic Connectivity経由での登録や更新は要注意だ。

mysql> 
mysql> insert into char_test(id, r_char_20)
-> values(7,'¥202P¥202Q¥202R¥202S¥202T¥202U¥202V¥202W¥202X¥202O¥202P¥202Q¥202R¥202S¥202T¥202U¥202V¥202W¥202X¥202O¥202P');
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> show warnings;
+---------+------+------------------------------------------------+
| Level | Code | Message |
+---------+------+------------------------------------------------+
| Warning | 1265 | Data truncated for column 'r_char_20' at row 1 |
+---------+------+------------------------------------------------+
1 row in set (0.00 sec)


5)文字数、バイトサイズの確認

MySQL4.1.x以降、char(n)の n は、文字数を意味するので MySQL4.0.xとの違いは文字列が取りうる物理サイズということになる。

mysql> 
mysql>
mysql> select
-> id,
-> r_char_20,
-> char_length(r_char_20) as char_length,
-> length(r_char_20) as length
-> from
-> char_test
-> where
-> id <= 7;
+----+------------------------------------------+-------------+--------+
| id | r_char_20 | char_length | length |
+----+------------------------------------------+-------------+--------+
| 1 | あ | 2 | 3 |
| 2 | NULL | NULL | NULL |
| 3 | | 0 | 0 |
| 4 | 12345678901234567890 | 20 | 20 |
| 5 | 12345678901234567890           | 20 | 20 |
| 6 | 12345678901234567890 | 20 | 40 |
| 7 | 12345678901234567890 | 20 | 40 |
+----+------------------------------------------+-------------+--------+
7 rows in set (0.03 sec)

mysql>
mysql> rollback;
Query OK, 0 rows affected (0.05 sec)

mysql>


今日はここまで、次回につづく。

| | | コメント (0) | トラックバック (0)

2006年3月 1日 (水)

Mac De Oracle Heterogeneous! #52

前回の続き。

MySQLの文字型の二回目。

MySQL4.0.25、MySQL4.1.13aともに以下の表を作成した。

mysql> desc char_test;
+-------------------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+------------------+------+-----+---------+-------+
| id | int(11) | | PRI | 0 | |
| r_char_20 | char(20) | YES | | NULL | |
| r_char_20_binary | char(20) binary | YES | | NULL | |
| r_char_255 | char(255) | YES | | NULL | |
| r_char_255_binary | char(255) binary | YES | | NULL | |
+-------------------+------------------+------+-----+---------+-------+
5 rows in set (0.00 sec)

mysql> desc varchar_test;
+----------------------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------------+---------------------+------+-----+---------+-------+
| id | int(11) | | PRI | 0 | |
| r_varchar_20 | varchar(20) | YES | | NULL | |
| r_varchar_20_binary | varchar(20) binary | YES | | NULL | |
| r_varchar_255 | varchar(255) | YES | | NULL | |
| r_varchar_255_binary | varchar(255) binary | YES | | NULL | |
| r_tinytext | tinytext | YES | | NULL | |
| r_tinyblob | tinyblob | YES | | NULL | |
| r_text | text | YES | | NULL | |
| r_blob | blob | YES | | NULL | |
+----------------------+---------------------+------+-----+---------+-------+
9 rows in set (0.00 sec)

mysql>

MySQL4.0.xまでは、char型及び、varchar型は最大255バイト。4.1.x以降では65535文字
また、独特な仕様だが、char型とvarchar型は、大文字小文字を区別しない。大文字小文字を区別させるためには binary属性を付けなければならない。binary属性の無い文字型ではソート処理がどうなるのか気になるところだ。

ところで、255バイト以上の文字列はどのようにして格納するのか? とマニュアルを読んでいると、tinytext型、text型、mediumtext型、longtext型、そして、大文字小文字を区別できるtinyblob型、blob型、mediumblob型、longblob型があるとのこと。(blobだとbinary large objectなのかと思っていたのだが、マニュアルによると文字列という表現になっている。ところ変わればなんとやら。。なのだが、generic connectivity経由でOracleのvarchar2型にマッピングできるのかという点は不安材料だ。。)

また、MySQL4.1から文字列型の仕様がかなり変更されたらしく、MySQL4.0.xでは、char(n)又は、varchar(n)の n はバイトを意味していたものが、文字数に変わったようだ。
さらに、キャラクタセットがカラム毎に変えられるらしい、MySQL4.1以降ならば事前に表定義は、”しっかり”確認しておく事をお勧めする。もしそのような表定義であったなら generic connectivity で扱うのは諦めたほうがよいかもしれない。 

今日はここまで、次回につづく。

| | | コメント (0) | トラックバック (0)

2006年2月28日 (火)

Mac De Oracle Heterogeneous! #51

文字型のつづき。今回から、MySQLの文字型の特徴を簡単検証していく。

PowerBook G4 MacOSX Tiger 10.4.5のMySQL4.0.25及び、PowerMac G5 Dual2.7GhzのMySQL4.1.13aを利用した。


gencon_blog_img33

尚、データベース及び、クライアントキャラクタセットともにSJISである。

MySQL4.0.25及び、MySQL4.1.13aには、以下のような表を作成した。。。のだが・・・・・。

mysql> create table char_testA
-> (
-> id int primary key,
-> r_char_20 char(20),
-> r_char_20_binary char(20) binary,
-> r_char_255 char(255),
-> r_char_255_binary char(255) binary,
-> r_varchar_20 varchar(20),
-> r_varchar_20_binary varchar(20) binary,
-> r_varchar_255 varchar(255),
-> r_varchar_255_binary varchar(255) binary,
-> r_tinytext tinytext,
-> r_tinyblob tinyblob,
-> r_text text,
-> r_blob blob
-> ) engine=innodb;

Query OK, 0 rows affected (0.10 sec)

char型で定義した列が全て varchar型になっていたのである。あれれ、何故????

mysql> desc char_test;
+----------------------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------------+---------------------+------+-----+---------+-------+
| id | int(11) | | PRI | 0 | |
| r_char_20 | varchar(20) | YES | | NULL | |
| r_char_20_binary | varchar(20) binary | YES | | NULL | |
| r_char_255 | varchar(255) | YES | | NULL | |
| r_char_255_binary | varchar(255) binary | YES | | NULL | |
| r_varchar_20 | varchar(20) | YES | | NULL | |
| r_varchar_20_binary | varchar(20) binary | YES | | NULL | |
| r_varchar_255 | varchar(255) | YES | | NULL | |
| r_varchar_255_binary | varchar(255) binary | YES | | NULL | |
| r_tinytext | tinytext | YES | | NULL | |
| r_tinyblob | tinyblob | YES | | NULL | |
| r_text | text | YES | | NULL | |
| r_blob | blob | YES | | NULL | |
----------------------+---------------------+------+-----+---------+-------+
13 rows in set (0.00 sec)

DDLもvarcharに変更されている。
mysql> show create table char_test¥G
*************************** 1. row ***************************
Table: char_test
Create Table: CREATE TABLE `char_test` (
`id` int(11) NOT NULL default '0',
`r_char_20` varchar(20) default NULL,
`r_char_20_binary` varchar(20) binary default NULL,
`r_char_255` varchar(255) default NULL,
`r_char_255_binary` varchar(255) binary default NULL,
`r_varchar_20` varchar(20) default NULL,
`r_varchar_20_binary` varchar(20) binary default NULL,
`r_varchar_255` varchar(255) default NULL,
`r_varchar_255_binary` varchar(255) binary default NULL,
`r_tinytext` tinytext,
`r_tinyblob` tinyblob,
`r_text` text,
`r_blob` blob,
PRIMARY KEY (`id`)
) TYPE=InnoDB
1 row in set (0.00 sec)

mysql>

慌てて、マニュアルを確認してみると、

マニュアルから引用ここから


6.5.3.1. カラムの暗黙的な変更

場合によっては、CREATE TABLE ステートメントで指定されているカラムの型、属性が、MySQL によって暗黙的に変更されることがあります(このような変更は ALTER TABLE でも発生する場合があります)。

長さが 4 文字に満たない VARCHAR 型のカラムは CHAR 型に変更される。

テーブルのいずれかのカラムが可変長である場合は、結果的にそのレコード全体が可変長になる。したがって、テーブルに可変長のカラム(VARCHAR、TEXT、BLOB)が含まれている場合、長さが 3 文字を超す CHAR 型のカラムはいずれも VARCHAR 型カラムに変更される。これはカラムの使用方法には影響しない。MySQL では、VARCHAR 型は単に文字を格納するもう 1 つの手段として使用されている。MySQL でこの変換が実行される理由は、スペースを節約し、テーブル処理を迅速化するためである。 See 章 7. MySQL のテーブル型。

バージョン 4.1.0 以降では、255 文字を超える長さを持つ CHAR 型または VARCHAR 型のフィールドはいずれも TEXT 型に変換される。 これは互換性を考慮した機能。


マニュアルから引用ここまで


仕様なら仕方ない。(バグかと思ったよ。。。。)
ということで、char型本来の癖を見る為、char型だけの表とvarchar型、text型、blob型の表に分ける事にした。(尚、mediumtext型、mediumblob型、longtext型及び、longblob型は検証対象外とした。)

char(n) と char(n) binaryの違いは、'A'と'a'を区別するかしないかということ。binary属性を付けると大文字と小文字を区別するようになる。この特徴は要注意だ。PostgreSQLもOracleもDB2でも大文字小文字は区別される、区別したくない場合には、スカラ関数を使い大文字又は、小文字に統一してから比較するからだ。もし、Generic Connectivityを経由してアクセスするMySQLの表がbinary属性のないchar型やvarchar型だと、ソートは注意が必要かもしれない。(ソートについては、Generic Connectivity経由でも検証する)
また、blob型なのに何故、文字型の検証で登場するのかと感じる方もいると思うのだが、blob型は Oracleのlob型に対応するのでは? と思っているのだが、MySQLでは文字列型に分類されており、大文字小文字を区別したい文字列を格納するための型となっている、ちなみに、text型は大文字小文字を区別しない。これらの型の詳細は、MySQLのマニュアル又は、MySQLによる最速RDBMS構築ガイドを参照するとよいだろう。

mysql> create table char_test
-> (
-> id int primary key,
-> r_char_20 char(20),
-> r_char_20_binary char(20) binary,
-> r_char_255 char(255),
-> r_char_255_binary char(255) binary
-> ) engine=innodb;
Query OK, 0 rows affected (0.09 sec)

mysql>
mysql> create table varchar_test
-> (
-> id int primary key,
-> r_varchar_20 varchar(20),
-> r_varchar_20_binary varchar(20) binary,
-> r_varchar_255 varchar(255),
-> r_varchar_255_binary varchar(255) binary,
-> r_tinytext tinytext,
-> r_tinyblob tinyblob,
-> r_text text,
-> r_blob blob
-> ) engine=innodb;
Query OK, 0 rows affected (0.02 sec)


ちなみに、一旦, char型からvarchar型に変更されてしまうと、全列を固定長に戻したとしても、varchar型がchar型に戻されることは無いようだ。以下のログ参照。(ん〜〜〜〜・・・・。いろいろ書きたい気分だがノーコメント。) 
まず、char型だけの表を作成。この定義だとすべてchar型として定義されている。

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> create table char_test
-> (
-> id int primary key,
-> r_char_20 char(20),
-> r_char_20_binary char(20) binary,
-> r_char_255 char(255),
-> r_char_255_binary char(255) binary
-> ) engine=innodb;
Query OK, 0 rows affected (0.22 sec)

mysql> desc char_test;
+-------------------+-----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+-----------+------+-----+---------+-------+
| id | int(11) | | PRI | 0 | |
| r_char_20 | char(20) | YES | | NULL | |
| r_char_20_binary | char(20) | YES | | NULL | |
| r_char_255 | char(255) | YES | | NULL | |
| r_char_255_binary | char(255) | YES | | NULL | |
+-------------------+-----------+------+-----+---------+-------+
5 rows in set (0.01 sec)

固定長の文字列しかない表であれば、char型のままなのだが、char型とvarchar型(text型、blob型も含む)が混在すると、既存char型は全て、自動的にvarchar型に変更されてしまう。MySQLのchar型、varchar型の仕様からすると、どちらの型でもいいのかもしれないが、他の(PostgreSQLやOracleなど)RDBMSと互換を持たせた挙動にしたい場合には困るかもしれない。(Generic Connectivity経由の挙動確認ではこの辺りも忘れずに!)
mysql> alter table char_test add column r_varchar_20 varchar(20);
Query OK, 0 rows affected (0.52 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> desc char_test;
+-------------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+--------------+------+-----+---------+-------+
| id | int(11) | | PRI | 0 | |
| r_char_20 | varchar(20) | YES | | NULL | |
| r_char_20_binary | varchar(20) | YES | | NULL | |
| r_char_255 | varchar(255) | YES | | NULL | |
| r_char_255_binary | varchar(255) | YES | | NULL | |
| r_varchar_20 | varchar(20) | YES | | NULL | |
+-------------------+--------------+------+-----+---------+-------+
6 rows in set (0.03 sec)


一旦、char型からvarchar型に自動変更されてしまった表は、そのきっかけになった列を削除しても元には戻らない。
どうしても、char型に戻したいのなら表を再作成するしかない。

mysql> alter table char_test drop column r_varchar_20;
Query OK, 0 rows affected (0.71 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> desc char_test;
+-------------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+--------------+------+-----+---------+-------+
| id | int(11) | | PRI | 0 | |
| r_char_20 | varchar(20) | YES | | NULL | |
| r_char_20_binary | varchar(20) | YES | | NULL | |
| r_char_255 | varchar(255) | YES | | NULL | |
| r_char_255_binary | varchar(255) | YES | | NULL | |
+-------------------+--------------+------+-----+---------+-------+
5 rows in set (0.02 sec)

mysql> drop table char_test;
Query OK, 0 rows affected (0.05 sec)

mysql>

と、戸惑う仕様がいろいろあるのだが、なんとかやっている。ということで次回へつづく。

| | | コメント (0) | トラックバック (0)

2006年2月27日 (月)

Mac De Oracle Heterogeneous! #50

前回からのつづき。

PostgreSQLの文字型 最終回。

ソートの確認。ロケール関連パラメータをCに設定しているので特に問題ないと思うが、念のために確認。以下のデータを登録しておく。

dpostgresql749=> select id,r_varchar_20 from char_test;
id | r_varchar_20
----+--------------
1 | C
2 | c
3 | B
4 | b
5 | A
6 | a
7 | お
8 | え
9 | う
10 | い
11 | あ
12 | ぉ
13 | ぇ
14 | ぅ
15 | ぃ
16 | ぁ
(16 rows)

postgresql749=>

尚、文字列を16進数表示するユーザ定義関数 strtohex()を利用して文字コードも確認した。
strtohex()関数を作成したログ(抜粋)。詳細はstrtohexのソースに同胞されているドキュメントを参照のこと。
http://ring.atr.jp/archives/misc/db/postgresql-jp/strtohex/?C=M;O=Aからダウンロードできる。

pb17:/usr/local/pgsql/share/contrib postgres$ postmaster -S
pb17:/usr/local/pgsql/share/contrib postgres$ psql -e -f strtohex.sql postgresql749
SET search_path = scott;
SET
CREATE OR REPLACE FUNCTION strtohex(TEXT)
RETURNS TEXT
AS '$libdir/strtohex', 'strtohex'
LANGUAGE C STRICT;
CREATE FUNCTION
commit;
COMMIT
pb17:/usr/local/pgsql/share/contrib postgres$ psql -U scott postgresql749
Password:
Welcome to psql 7.4.9, the PostgreSQL interactive terminal.

Type: ¥copyright for distribution terms
¥h for help with SQL commands
¥? for help on internal slash commands
¥g or terminate with semicolon to execute query
¥q to quit

postgresql749=> select strtohex('a');
strtohex
----------
61
(1 row)

文字列を昇順にソートした結果。(変わったところはないようだ)

postgresql749=> ¥p
select
id,
r_varchar_20,
strtohex(r_varchar_20) as hex_euc,
strtohex(convert(r_varchar_20,'SJIS')) as hex_sjis,
strtohex(convert(r_varchar_20,'UTF-8')) as hex_utf8
from
char_test
order by
r_varchar_20;

postgresql749=> ¥g
id | r_varchar_20 | hex_euc | hex_sjis | hex_utf8
----+--------------+---------+----------+----------
5 | A | 41 | 41 | 41
3 | B | 42 | 42 | 42
1 | C | 43 | 43 | 43
6 | a | 61 | 61 | 61
4 | b | 62 | 62 | 62
2 | c | 63 | 63 | 63
16 | ぁ | a4a1 | 829f | e38181
11 | あ | a4a2 | 82a0 | e38182
15 | ぃ | a4a3 | 82a1 | e38183
10 | い | a4a4 | 82a2 | e38184
14 | ぅ | a4a5 | 82a3 | e38185
9 | う | a4a6 | 82a4 | e38186
13 | ぇ | a4a7 | 82a5 | e38187
8 | え | a4a8 | 82a6 | e38188
12 | ぉ | a4a9 | 82a7 | e38189
7 | お | a4aa | 82a8 | e3818a
(16 rows)


ちなみに、Oracleでソートを行った場合と同じ結果だ。
(言語ソートすると言語固有の文字順にソートされるが、PostgreSQLのロケール関連パラメータを設定した場合にはOracleの言語ソートと同じ結果になるのかは未確認。PostgreSQLのマニュアルを熟読しないと・・・・。

購入したPostgreSQL徹底入門「P.178」では詳細な解説はなく、簡単な解説だけだったのが残念。とはいっても言語ソースが必要になる状況は想定していないので特に問題なし。)

SCOTT> list
1 select
2 id#,
3 r_varchar2,
4 dump(r_varchar2,16) as hex_sjis,
5 dump(convert(r_varchar2,'ja16euc'),16) as hex_euc,
6 dump(convert(r_varchar2,'utf8'),16) as hex_utf8
7 from
8 char_test
9 order by
10* r_varchar2
SCOTT> /

ID# R_VARCHAR2 HEX_SJIS HEX_EUC HEX_UTF8
---------- -------------------- -------------------- -------------------- ----------------------
5 A Typ=1 Len=1: 41 Typ=1 Len=1: 41 Typ=1 Len=1: 41
3 B Typ=1 Len=1: 42 Typ=1 Len=1: 42 Typ=1 Len=1: 42
1 C Typ=1 Len=1: 43 Typ=1 Len=1: 43 Typ=1 Len=1: 43
6 a Typ=1 Len=1: 61 Typ=1 Len=1: 61 Typ=1 Len=1: 61
4 b Typ=1 Len=1: 62 Typ=1 Len=1: 62 Typ=1 Len=1: 62
2 c Typ=1 Len=1: 63 Typ=1 Len=1: 63 Typ=1 Len=1: 63
16 ぁ Typ=1 Len=2: 82,9f Typ=1 Len=2: a4,a1 Typ=1 Len=3: e3,81,81
11 あ Typ=1 Len=2: 82,a0 Typ=1 Len=2: a4,a2 Typ=1 Len=3: e3,81,82
15 ぃ Typ=1 Len=2: 82,a1 Typ=1 Len=2: a4,a3 Typ=1 Len=3: e3,81,83
10 い Typ=1 Len=2: 82,a2 Typ=1 Len=2: a4,a4 Typ=1 Len=3: e3,81,84
14 ぅ Typ=1 Len=2: 82,a3 Typ=1 Len=2: a4,a5 Typ=1 Len=3: e3,81,85
9 う Typ=1 Len=2: 82,a4 Typ=1 Len=2: a4,a6 Typ=1 Len=3: e3,81,86
13 ぇ Typ=1 Len=2: 82,a5 Typ=1 Len=2: a4,a7 Typ=1 Len=3: e3,81,87
8 え Typ=1 Len=2: 82,a6 Typ=1 Len=2: a4,a8 Typ=1 Len=3: e3,81,88
12 ぉ Typ=1 Len=2: 82,a7 Typ=1 Len=2: a4,a9 Typ=1 Len=3: e3,81,89
7 お Typ=1 Len=2: 82,a8 Typ=1 Len=2: a4,aa Typ=1 Len=3: e3,81,8a

16行が選択されました。
ちなみに(テストデータがよくないので申し訳ないのだが)、nlssort関数を利用した言語ソートでは小文字英字の順序の違いに気付くと思う。
SCOTT> 
SCOTT> list
1 select
2 r_varchar2
3 from
4 char_test
5 order by
6* nlssort(r_varchar2, 'nls_sort=japanese')
SCOTT> /

R_VARCHAR2
--------------------
a
A
b
B
c
C











16行が選択されました。

SCOTT>


次回は、MySQLの文字型について同様の検証を行う。

| | | コメント (0) | トラックバック (0)

2006年2月26日 (日)

Mac De Oracle Heterogeneous! #49

前回からのつづき。
PostgreSQLの文字型の四回目。

1.text型の検証

1)' あ '、 null、 空文字、シングルバイト文字及び、マルチバイト文字を20文字登録。

空白の扱いを確認するため、”あ”の前後に空白を付加し、' あ ' として登録した。

postgresql749=> 
postgresql749=> insert into char_test(id, r_text)
postgresql749-> values(1, ' ¥202¥240 ');
INSERT 33747 1
postgresql749=> insert into char_test(id, r_text)
postgresql749-> values(2, null);
INSERT 33748 1
postgresql749=> insert into char_test(id, r_text)
postgresql749-> values(3, '');
INSERT 33749 1
postgresql749=> insert into char_test(id, r_text)
postgresql749-> values(4, '12345678901234567890');
INSERT 33750 1
postgresql749=> insert into char_test(id, r_text)
postgresql749-> values(5, '¥202P¥202Q¥202R¥202S¥202T¥202U¥202V¥202W¥202X¥202O¥202P¥202Q¥202R¥202S¥202T¥202U¥202V¥202W¥202X;
INSERT 33751 1
現在リリースされているMacOSXのTerminalは、マルチバイトを入力するとエスケープシーケンスになってしまう。実際に入力しているのは以下のDML。
insert into char_test(id, r_text) values(5, '12345678901234567890');
postgresql749=> commit;
COMMIT

2)text型の最大サイズ

text型の最大サイズは、約1GB(要するに1GB未満)ということで、許容サイズを超えればエラー。

postgresql749=> insert into char_test(id,r_text) values(99,lpad('*',2048000000,'*'));
ERROR: requested length too large
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into char_test(id,r_text) values(99,lpad('*',1024000000,'*'));
ERROR: requested length too large
postgresql749=> rollback;
ROLLBACK

3)文字数、バイトサイズの確認

空白の扱いは、varchar型と同じだが、Generic Connectivity経由では、Oracleのどの型にマップされるのかがポイント。Generic Connectivity経由では利用できない可能性もあるし、利用できたとしてもVARCHAR2型の最大サイズである4000バイトを超えた場合にはどのような挙動になるのかという点も気になるところだ。
Generic Connectivityを利用せず、PostgreSQLのtext型からOracleへデータ移行するとした場合、PostgreSQLのtext型に登録されている文字列の最大サイズが4000バイトを超えるのならば、CLOB型に、4000バイト以下なら、VARCHAR2型にするのがベストだと思われる。
また、PostgreSQLの文字型は、NULL及び、空文字を設定できるが、Oracleでは、NULLと空文字が、NULLとして扱われているため、PostgreSQLの文字型に空文字を設定した場合は、Oracle側ではNULLとして扱われると予想している。

postgresql749-> ¥p
select
id,
r_text,
length(r_text) as 文字数,
octet_length(r_text) as バイト数
from
char_test

postgresql749-> ¥g
id | r_text | 文字数 | バイト数
----+------------------------------------------+-------+--------
1 | あ | 3 | 4
2 | | |
3 | | 0 | 0
4 | 12345678901234567890 | 20 | 20
5 | 12345678901234567890 | 20 | 40
(5 rows)

postgresql749=>

次回へつづく。

| | | コメント (0) | トラックバック (0)

2006年2月25日 (土)

Mac De Oracle Heterogeneous! #48

前回からのつづき。

PostgreSQLの文字型 三回目。

1.varchar型の検証

1)' あ '、 null、 空文字、シングルバイト文字を20文字登録。

空白の扱いを確認するため、”あ”の前後に空白を付加し、' あ ' として登録した。

postgresql749=> insert into char_test(id, r_varchar_20)
postgresql749-> values(1, ' ¥202¥240 ');
INSERT 33742 1
現在リリースされているMacOSXのTerminalは、マルチバイトを入力するとエスケープシーケンスになってしまう。実際に入力しているのは以下のDML。
insert into char_test(id, r_varchar_20) values(1, ' あ ');
postgresql749=> insert into char_test(id, r_varchar_20)
postgresql749-> values(2, null);
INSERT 33743 1
postgresql749=> insert into char_test(id, r_varchar_20)
postgresql749-> values(3, '');
INSERT 33744 1
postgresql749=> insert into char_test(id, r_varchar_20)
postgresql749-> values(4,'12345678901234567890');
INSERT 33745 1
postgresql749=> commit;
COMMIT


2)シングルバイト文字を21文字登録

20文字を超えるためエラー。(Oracleと連携しても問題になる事はないだろう)

postgresql749=> insert into char_test(id, r_varchar_20)
postgresql749-> values(5,'123456789012345678901');
ERROR: value too long for type character varying(20)
postgresql749=> rollback;
ROLLBACK


3)マルチバイト文字を20文字登録

20文字以内なので問題なく登録できる。

postgresql749=> insert into char_test(id, r_varchar_20)
postgresql749-> values(5,'¥202P¥202Q¥202R¥202S¥202T¥202U¥202V¥202W¥202X¥202O¥202P¥202Q¥202R¥202S¥202T¥202U¥202V¥202W¥202X¥202O');
INSERT 33746 1
postgresql749=> commit;
COMMIT
現在リリースされているMacOSXのTerminalは、マルチバイトを入力するとエスケープシーケンスになってしまう。実際に入力しているのは以下のDML。
insert into char_test(id, r_varchar_20) values(5,'12345678901234567890');


4)マルチバイト文字を21文字登録

20文字を超えるためエラー。

postgresql749=> insert into char_test(id, r_varchar_20)
postgresql749-> values(6,'¥202P¥202Q¥202R¥202S¥202T¥202U¥202V¥202W¥202X¥202O¥202P¥202Q¥202R¥202S¥202T¥202U¥202V¥202W¥202X¥202O2P');
ERROR: value too long for type character varying(20)
postgresql749=> rollback;
ROLLBACK
現在リリースされているMacOSXのTerminalは、マルチバイトを入力するとエスケープシーケンスになってしまう。実際に入力しているのは以下のDML。
insert into char_test(id, r_varchar_20) values(6,'123456789012345678901');


5)文字数、バイトサイズの確認

空白の扱いは、Oracleと同じようなので問題になることはないだろう。Oracleではvarchar2(20 char)か、varchar2(40)にマッピングすればよいと思うのだが、Generic Connectivity経由の場合はどの型にマッピングされるのか?、また、PostgreSQLの varchar型は、Oracleのvarchar2型より大きいサイズを定義できる(Oracleのvarchar2型は4000バイトが最大だが、PostgreSQLでは約1GBまで可能)ため、Generic Connectivity経由である場合はどのように扱われるのかがポイントになるだろう。

postgresql749=> ¥p
select
id,
r_varchar_20,
length(r_varchar_20) as 文字数,
octet_length(r_varchar_20) as バイト数
from
char_test;
postgresql749=> ¥g
id | r_varchar_20 | 文字数 | バイト数
----+------------------------------------------+-------+--------
1 | あ | 3 | 4
2 | | |
3 | | 0 | 0
4 | 12345678901234567890 | 20 | 20
5 | 12345678901234567890 | 20 | 40
(5 rows)

postgresql749=> delete from char_test;
DELETE 5
postgresql749=> commit;
COMMIT


今日はここまで、続きは次回。

| | | コメント (0) | トラックバック (0)

2006年2月24日 (金)

Mac De Oracle Heterogeneous! #47

前回からのつづき。

PostgreSQLの文字型の二回目。

1.char型の検証

1)' あ '、 null、 空文字、シングルバイト文字を20文字登録。

空白の扱いを確認するため、”あ”の前後に空白を付加し、' あ ' として登録した。

postgresql749=> insert into char_test(id, r_char_20)
postgresql749-> values(1, ' ¥202¥240 ');
INSERT 33737 1
postgresql749=> commit;
COMMIT
postgresql749=> insert into char_test(id, r_char_20)
postgresql749-> values(2, null);
INSERT 33738 1
postgresql749=> insert into char_test(id, r_char_20)
postgresql749-> values(3, '');
INSERT 33739 1
postgresql749=> insert into char_test(id, r_char_20)
postgresql749-> values(4,'12345678901234567890');
INSERT 33740 1
postgresql749=> commit;
COMMIT

2)シングルバイト文字を21文字登録

20文字を超えるためエラー。(Oracleと連携しても問題になる事はないだろう)

postgresql749=> insert into char_test(id, r_char_20)
postgresql749-> values(5,'123456789012345678901');
ERROR: value too long for type character(20)
postgresql749=> rollback;
ROLLBACK

3)マルチバイト文字を20文字登録

20文字以内なので問題なく登録できる。
(MacOSX TigerのTerminalからマルチバイト文字を入力するとエスケープシーケンスに変換されてしまうが表示上は問題ない。いつ改善されるやら。。)
ちなみに、実行したインサート文は以下。

insert into char_test(id, r_char_20) values(5,'12345678901234567890');

postgresql749=> insert into char_test(id, r_char_20)
postgresql749-> values(5,'¥202P¥202Q¥202R¥202S¥202T¥202U¥202V¥202W¥202X¥202O¥202P¥202Q¥202R¥202S¥202T¥202U¥202V¥202W¥202X¥202O');
INSERT 33741 1
postgresql749=> commit;
COMMIT

4)マルチバイト文字を21文字登録

20文字を超えるためエラー。
実行したインサート文は以下。

insert into char_test(id, r_char_20) values(27,'123456789012345678901');

postgresql749=> insert into char_test(id, r_char_20)
postgresql749-> values(6,'¥202P¥202Q¥202R¥202S¥202T¥202U¥202V¥202W¥202X¥202O¥202P¥202Q¥202R¥202S¥202T¥202U¥202V¥202W¥202X¥202O2P');
ERROR: value too long for type character(20)
postgresql749=> rollback;
ROLLBACK

5)文字数、バイトサイズの確認

空白の扱いは、Oracleと同じようなので問題になることはないだろう。Oracleではchar(20 char)か、varchar2(40)にマッピングすればよいと思うのだが、Generic Connectivity経由の場合はどの型にマッピングされるのか?、また、PostgreSQLの char型は、Oracleのchar型より大きいサイズを定義できる(Oracleのchar型は2000バイトが最大だが、PostgreSQLでは約1GBまで可能)ため、Generic Connectivity経由である場合はどのように扱われるのかがポイントになるだろう。

postgresql749=> ¥p
select
id,
r_char_20,
length(r_char_20) as 文字数,
octet_length(r_char_20) as バイト数
from
char_test;
postgresql749=> ¥g
id | r_char_20 | 文字数 | バイト数
----+------------------------------------------+-------+--------
1 | あ | 20 | 21
2 | | |
3 | | 20 | 20
4 | 12345678901234567890 | 20 | 20
5 | 12345678901234567890 | 20 | 40
(5 rows)

postgresql749=>
postgresql749=> delete from char_test;
DELETE 5
postgresql749=> commit;
COMMIT


次回につづく。

| | | コメント (0) | トラックバック (0)

2006年2月23日 (木)

Mac De Oracle Heterogeneous! #46

Generic Connectivityの検証も残すところ文字型のみ。ラージオブジェクトについてはおまけ程度に書く予定だが、その他、各データベースに特有の型は今のところ試す予定はない。(必要になりそうならやるかもしれないが・・)

まず、PostgreSQLとMySQLそれぞれの文字型について癖を把握しておく。
PostgreSQLの文字型 一回目。

PowerBook G4 MacOSX Tiger 10.4.5のPostgreSQL7.4.9を利用した。


gencon_blog_img_postgre

また、クライアントエンコーディングは、SJIS。
データベースキャラクタセットは、EUC。
ソートに影響するローケル関連パラメータLC_COLLATEパラメータ及び、LC_CTYPEパラメータは C とした。 
(ちなみに、LC_COLLATE及び、LC_CTYPEパラメータを設定すると Oracleの言語ソートのようなことができるような記述がマニュアルにはあるのだが、前述した書籍で「日本語を使う場合、initdbで--no-locale。。。」とあったため、この検証では C と設定することとした)

pb17:˜ postgres$ pg_controldata
pg_control version number: 72
Catalog version number: 200310211
Database cluster state: shut down

中略

LC_COLLATE: C
LC_CTYPE: C
pb17:˜ postgres$
pb17:˜ postgres$
pb17:˜ postgres$ echo $PGCLIENTENCODING
SJIS
pb17:˜ postgres$

以下の表を作成した。

postgresql749=> create table char_test
postgresql749-> (
postgresql749(> id int primary key,
postgresql749(> r_char_20 char(20),
postgresql749(> r_char_2000 char(2000),
postgresql749(> r_char_2001 char(2001),
postgresql749(> r_varchar_20 varchar(20),
postgresql749(> r_varchar_4000 varchar(4000),
postgresql749(> r_varchar_4001 varchar(4001),
postgresql749(> r_text text
postgresql749(> );
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "char_test_pkey" for table "char_test"
CREATE TABLE
postgresql749=> ¥d char_test
Table "scott.char_test"
Column | Type | Modifiers
----------------+-------------------------+-----------
id | integer | not null
r_char_20 | character(20) |
r_char_2000 | character(2000) |
r_char_2001 | character(2001) |
r_varchar_20 | character varying(20) |
r_varchar_4000 | character varying(4000) |
r_varchar_4001 | character varying(4001) |
r_text | text |
Indexes:
"char_test_pkey" primary key, btree (id)

postgresql749=>
postgresql749=> commit;
COMMIT
postgresql749=>

Oracleと違い点は、char(n)型及び、varchar(n)型の n は常に文字数ということ。
また、n の上限はなく、最大長が約1GBまで制限がある。
従って、データベースキャラクタセットにより n の上限が変わってくるということになる。
Generic Connectivity経由でアクセスする際にはこの辺りがポイントになるだろう。また、text型がどのような扱いになるのかも気になるところだ。

ちなみに、Oracleでは初期化パラメータ nls_length_semantics を char にしデフォルトを文字単位の長さにするか、列を定義する際に、CHAR修飾子を指定することと同じ。
nls_length_semanticsのデフォルトはBYTEなので、hoge_code1は10文字、hoge_code2は10バイトという意味になる、

create table hoge
(
hoge_code1 CHAR(10 CHAR),
hoge_code2 CHAR(10)
);

今日はここまで。次回につづく。

| | | コメント (0) | トラックバック (0)

2006年2月22日 (水)

Mac De Oracle Heterogeneous! #45

数値型のつづき。

Generic Connectivity経由でMySQL4.0.25及び、MySQL4.1.13aの数値型にアクセス 最終回。

Generic Connectivity経由でdecimal型と同型の符号なしにアクセスした結果。

ここでは、以下のように定義した。

decimal(38,0)と同型の符号なし。
decimal(38,16)と同型の符号なし。

MySQL4.1.13a、MySQL4.0.25では、Oracleのnumber型の精度より低い。これらの型もGeneric Connectivity経由で参照、更新するのは避けたほうがよさそうである。
(実際にはインサート文も検証しているが結果は同じであるため省略)

1)MySQL4.0.25の decimal(38,0)とdecimal(38,0) unsignedを
  Generic Connectivity経由で問い合わせた結果

CORYDORAS> set numwidth 40
CORYDORAS> select
2 "r_decimal_38",
3 "r_decimal_38_unsigned"
4 from
5 num_test_mysql4025_mac@oracle10g_win;

r_decimal_38 r_decimal_38_unsigned
---------------------------------------- ----------------------------------------
NULL NULL
0 0
0 0
NULL NULL

中略

NULL NULL
99999999999999997748809823456034029568 0
-99999999999999997748809823456034029568 99999999999999997748809823456034029568
NULL NULL

中略

NULL NULL

25行が選択されました。

2)MySQL4.1.13aの decimal(38,0)とdecimal(38,0) unsignedを
  Generic Connectivity経由で問い合わせた結果

MySQL4.1.13aでは、不具合では?と思える部分(99999999999999999999999999999999999999が100000000000000035527741686413195739136となり精度が39桁になってしまっている)もある。

CORYDORAS> list
1 select
2 "r_decimal_38",
3 "r_decimal_38_unsigned"
4 from
5* num_test_mysql4113a_mac_sv@oracle10g_win
CORYDORAS> /

r_decimal_38 r_decimal_38_unsigned
---------------------------------------- ----------------------------------------
NULL NULL
0 0
0 0
NULL NULL

中略

NULL NULL
100000000000000035527741686413195739136 0
-99999999999999999999999999999999999999 99999999999999999999999999999999999999
NULL NULL
NULL NULL

27行が選択されました。

CORYDORAS>

3)MySQL4.0.25のdecimal(38,16)とdecimal(38,16) unsignedを
  Generic Connectivity経由で問い合わせた結果

decimalの精度は、doubleと同じというMySQL側の仕様の影響だと思われるが、MySQL独特な動作の一つである数値の丸めが発生し、decimal(38,0)では最大値の精度が23桁になってしまっている。これもgeneric connectivity経由での参照、更新対象にはしないほうがよいだろう。

CORYDORAS> select
2 "r_decimal_38_16",
3 "r_decimal_38_16_unsigned"
4 from
5 num_test_mysql4025_mac@oracle10g_win;

r_decimal_38_16 r_decimal_38_16_unsigned
---------------------------------------- ----------------------------------------
NULL NULL
0 0
0 0
NULL NULL

中略

NULL NULL
-9999999999999999999999.9999999999999999 0
10000000000000000000000 9999999999999999999999.9999999999999999
NULL NULL
NULL NULL

25行が選択されました。

4)MySQL4.1.13aのdecimal(38,16)とdecimal(38,16) unsignedを
  Generic Connectivity経由で問い合わせた結果。

3)とほぼ同じ結果であった。

CORYDORAS> list
1 select
2 "r_decimal_38_16",
3 "r_decimal_38_16_unsigned"
4 from
5* num_test_mysql4113a_mac_sv@oracle10g_win
CORYDORAS> /

r_decimal_38_16 r_decimal_38_16_unsigned
---------------------------------------- ----------------------------------------
NULL NULL
0 0
0 0
NULL NULL

中略

NULL NULL
-9999999999999999999999.9999999999999999 0
10000000000000004194304 9999999999999999999999.9999999999999999

27行が選択されました。

CORYDORAS>


==================================
Generic Connectivity経由での数値型の参照、更新のまとめ(MySQL4.0.x、4.1.x編)


利用している MyODBCドライバなどはこちら

数値型マッピング
MySQL4.0.25
MySQL4.1.13a
Oracle10g R1Generic Connectivityでの利用備 考
tinyint型 number型注1)
tinyint unsigned型 × 直接利用するのは避けたほうがよいだろう。参照するだけならば、MySQLの表データをCSVファイル化し外部表で取り込む等、直接参照しないアプローチを考えたほうがよいだろう。注1)
smallint型 注1)
smallint unsigned型 × 直接利用するのは避けたほうがよいだろう。参照するだけならば、MySQLの表データをCSVファイル化し外部表で取り込む等、直接参照しないアプローチを考えたほうがよいだろう。注1)
mediumint型 注1)
mediumint unsigned型 注1)
int型 注1)
int unsigned型 × 直接利用するのは避けたほうがよいだろう。参照するだけならば、MySQLの表データをCSVファイル化し外部表で取り込む等、直接参照しないアプローチを考えたほうがよいだろう。注1)
bigint型 × 直接利用するのは避けたほうがよいだろう。参照するだけならば、MySQLの表データをCSVファイル化し外部表で取り込む等、直接参照しないアプローチを考えたほうがよいだろう。注1)
bigint unsigned型 × 同上
float型 注1)
float unsigned型 注1)
double型 × 直接利用するのは避けたほうがよいだろう。参照するだけならば、MySQLの表データをCSVファイル化し外部表で取り込む等、直接参照しないアプローチを考えたほうがよいだろう。注1)
double unsigned型 × 同上
decimal(38,0)

double型と同じ精度ということなので、結果を見る限りdecimal(16,0)ぐらいまでなら利用できそうであるが、利用するのは避けたほうが無難かもしれない。どうしても利用したい場合には、Generic Connectivity以外のアプローチを考えたほうがよいかもしれない。例えば、参照だけならば、MySQLのデータをCSVファイル化し外部表で取り込む等。注1)

decimal(38,0) unsigned 同上
decimal(38,16) ×

直接利用するのは避けたほうがよいだろう。参照するだけならば、MySQLの表データをCSVファイル化し外部表で取り込む等、直接参照しないアプローチを考えたほうがよいだろう。注1)

decimal(38,16) unsigned × 同上

注1)数値型を扱う際にinsertやupdate文では、値が有効範囲を超えると数値が最大値、最小値に丸められるというMySQLの仕様に要注意。但し、MySQL5.0.2以降であればSQL_MODEの設定でエラーとして扱うこともできるようなので、それがうまく機能すれば回避することは可能かもしれない。(現時点では未確認)

次回、文字型の検証へつづく。

| | | コメント (0) | トラックバック (0)

2006年2月21日 (火)

Mac De Oracle Heterogeneous! #44

数値型のつづき。

Generic Connectivity経由でMySQL4.0.25及び、MySQL4.1.13aの数値型にアクセス 8回目。

Generic Connectivity経由でdouble型と同型の符号なしにアクセスした結果。

PostgreSQL7.4.9の場合と同様にGeneric Connectivity経由での参照、更新は避けたほうがよい。

問合せの結果だけを載せる。(データの登録も行ったが結果は同じであったため省略)

1)MySQL4.0.25をGeneic Connectivity経由で問い合わせた結果。

CORYDORAS> select
2 "r_double",
3 "r_double_unsigned"
4 from
5 num_test_mysql4025_mac@oracle10g_win;

r_double r_double_unsigned
---------- -----------------
NULL NULL
0 0
0 0
NULL NULL

中略

NULL NULL
-˜ 0
˜ 0
0 0
0 ˜
NULL NULL

中略

NULL NULL

25行が選択されました。

CORYDORAS>

2)MySQl4.1.13aをGeneric Connectivity経由で問い合わせた結果。
CORYDORAS> select
2 "r_double",
3 "r_double_unsigned"
4 from
5 num_test_mysql4113a_mac_sv@oracle10g_win;

r_double r_double_unsigned
---------- -----------------
NULL NULL
0 0
0 0
NULL NULL

中略

NULL NULL
-˜ 0
˜ 0
0 0
0 ˜
NULL NULL

中略

NULL NULL

27行が選択されました。

CORYDORAS>


次につづく。

| | | コメント (0) | トラックバック (0)

2006年2月20日 (月)

Mac De Oracle Heterogeneous! #43

数値型のつづき。

Generic Connectivity経由でMySQL4.0.25及び、MySQL4.1.13aの数値型にアクセス 7回目。

Generic Connectivity経由でfloat型と同型の符号なしにアクセスした結果。

MySQL4.0.2.25、 MySQL4.1.13aともにfloat型の利用は問題ないと思われる。


1)MySQL4.0.25をGeneric Connectivity経由で問い合わせた結果。

CORYDORAS> set numwidth 10
CORYDORAS> list
1 select
2 "r_float",
3 "r_float_unsigned"
4 from
5* num_test_mysql4025_mac@oracle10g_win
CORYDORAS> /

r_float r_float_unsigned
---------- ----------------
NULL NULL
0 0
0 0
NULL NULL

中略

NULL NULL
-3.400E+38 0
3.4000E+38 NULL
-1.200E-38 1.2000E-38
1.2000E-38 3.4000E+38
NULL NULL

中略

NULL NULL

25行が選択されました。

2)MySQL4.1.13aをGeneric Connectivity経由で問い合わせた結果。
CORYDORAS> list
1 select
2 "r_float",
3 "r_float_unsigned"
4 from
5* num_test_mysql4113a_mac_sv@oracle10g_win
CORYDORAS> /

r_float r_float_unsigned
---------- ----------------
NULL NULL
0 0
0 0
NULL NULL

中略

NULL NULL
-3.400E+38 0
3.4000E+38 NULL
-1.200E-38 1.2000E-38
1.2000E-38 3.4000E+38
NULL NULL

中略

NULL NULL

27行が選択されました。

CORYDORAS>

3)MySQL4.0.25へ最大値、最小値、アンダーフローする値、オーバーフローする値を登録した結果。

CORYDORAS> insert into num_test_mysql4025_mac@oracle10g_win("r_float","r_float_unsigned")
2 values(-3.4e38,0);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4025_mac@oracle10g_win("r_float","r_float_unsigned")
2 values(3.4e38,null);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4025_mac@oracle10g_win("r_float","r_float_unsigned")
2 values(-1.2e-38,1.2e-38)
3 ;

1行が作成されました。

CORYDORAS> insert into num_test_mysql4025_mac@oracle10g_win("r_float","r_float_unsigned")
2 values(1.2e-38,3.4e38);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4025_mac@oracle10g_win("r_float","r_float_unsigned")

2 values(-3.5e38,-1.0e38);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4025_mac@oracle10g_win("r_float","r_float_unsigned")
2 values(3.5e38,3.5e38);

1行が作成されました。

CORYDORAS> select *
2 from
3 (
4 select
5 rownum as "rownum",
6 a."r_float",
7 a."r_float_unsigned"
8 from
9 num_test_mysql4025_mac@oracle10g_win a
10 )
11 where
12 "rownum" > 25;

rownum r_float r_float_unsigned
---------- ---------- ----------------
26 -3.400E+38 0
27 3.4000E+38 NULL
28 -1.200E-38 1.2000E-38
29 1.2000E-38 3.4000E+38
30 -3.403E+38 0
31 3.4028E+38 3.4028E+38

6行が選択されました。

CORYDORAS> rollback;

ロールバックが完了しました。


4)MySQL4.1.13aへ最大値、最小値、アンダーフローする値、オーバーフローする値を登録した結果。

CORYDORAS> insert into num_test_mysql4113a_mac_sv@oracle10g_win("r_float","r_float_unsigned")
2 values(-3.4e38,0);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4113a_mac_sv@oracle10g_win("r_float","r_float_unsigned")
2 values(3.4e38,null);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4113a_mac_sv@oracle10g 2 _win("r_float","r_float_unsigned")
2 values(-1.2e-38,1.2e-38);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4113a_mac_sv@oracle10g_win("r_float","r_float_unsigned")
2 values(1.2e-38,3.4e38);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4113a_mac_sv@oracle10g_win("r_float","r_float_unsigned")
2 values(-3.5e38,-1.0e38);

CORYDORAS> insert into num_test_mysql4113a_mac_sv@oracle10g_win("r_float","r_float_unsigned")
2 values(3.5e38,3.5e38);

1行が作成されました。

CORYDORAS> select *
2 from
3 (
4 select
5 rownum as "rownum",
6 a."r_float",
7 a."r_float_unsigned"
8 from
9 num_test_mysql4113a_mac_sv@oracle10g_win a
10 )
11 where
12 "rownum" > 27;

rownum r_float r_float_unsigned
---------- ---------- ----------------
28 -3.400E+38 0
29 3.4000E+38 NULL
30 -1.200E-38 1.2000E-38
31 1.2000E-38 3.4000E+38
32 -3.403E+38 0
33 3.4028E+38 3.4028E+38

6行が選択されました。

CORYDORAS> rollback;

ロールバックが完了しました。

CORYDORAS>


次回につづく。

| | | コメント (0) | トラックバック (0)

2006年2月19日 (日)

Mac De Oracle Heterogeneous! #42

数値型のつづき。

Generic Connectivity経由でMySQL4.0.25及び、MySQL4.1.13aの数値型にアクセス 6回目。

Generic Connectivity経由でbigint型と同型の符号なしにアクセスした結果。

MySQL4.0.2.25、 MySQL4.1.13aともにbigint型は Generic Connectivity経由で利用しないほうがよいだろう。

1)MySQL4.0.25をGeneric Connectivity経由で問い合わせた結果。

0のはずが、48と表示される。最大値、最長値とも設定した値とは異なる値が表示されている。

CORYDORAS> select
2 "r_bigint",
3 "r_bigint_unsigned"
4 from
5 num_test_mysql4025_mac@oracle10g_win;

r_bigint r_bigint_unsigned
---------------------------------------- ----------------------------------------
NULL NULL
48 48
48 48
NULL NULL

中略

NULL NULL
15537418697586989 48
14134441877320249 14697404732553265
NULL NULL

中略

NULL NULL

25行が選択されました。

2)MySQL4.1.13aをGeneric Connectivity経由で問い合わせた結果。

1)の場合と同じくNG。

CORYDORAS> 
CORYDORAS> list
1 select
2 "r_bigint",
3 "r_bigint_unsigned"
4 from
5* num_test_mysql4113a_mac_sv@oracle10g_win
CORYDORAS> /

r_bigint r_bigint_unsigned
---------------------------------------- ----------------------------------------
NULL NULL
48 48
48 48
NULL NULL

中略

NULL NULL
15537418697586989 48
14134441877320249 14697404732553265
15537418697586989 14697404732553265
15537418697586989 14697404732553265
NULL NULL

中略

NULL NULL

27行が選択されました。

3)MySQL4.0.25へ最大値、最小値、許容範囲を超える値を登録した結果。

登録した値とは全く異なる値になってしまう。

CORYDORAS> 
CORYDORAS> insert into num_test_mysql4025_mac@oracle10g_win("r_bigint","r_bigint_unsigned")
2 values(-9223372036854775808,0);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4025_mac@oracle10g_win("r_bigint","r_bigint_unsigned")
2 values(9223372036854775807,18446744073709551615);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4025_mac@oracle10g_win("r_bigint","r_bigint_unsigned")
2 values(-9223372036854775809, -1);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4025_mac@oracle10g_win("r_bigint","r_bigint_unsigned")
2 values(9223372036854775808, 18446744073709551616);

1行が作成されました。

CORYDORAS> select *
2 from
3 (
4 select
5 rownum as "rownum",
6 a."r_bigint",
7 a."r_bigint_unsigned"
8 from
9 num_test_mysql4025_mac@oracle10g_win a
10 )
11 where
12 "rownum" > 25;

rownum r_bigint r_bigint_unsigned
---------------------------------------- ---------------------------------------- ----------------------------------------
26 15537418697586989 48
27 14134441877320249 14697404732553265
28 15537418697586989 14697404732553265
29 15537418697586989 14697404732553265

CORYDORAS>
CORYDORAS> rollback;

ロールバックが完了しました。

4)MySQL4.1.13aへ最大値、最小値、許容範囲を超える値を登録。

3)と同じ結果。

CORYDORAS> insert into num_test_mysql4113a_mac_sv@oracle10g_win("r_bigint","r_bigint_unsigned")
2 values(-9223372036854775808,0);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4113a_mac_sv@oracle10g_win("r_bigint","r_bigint_unsigned")
2 values(9223372036854775807,18446744073709551615);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4113a_mac_sv@oracle10g_win("r_bigint","r_bigint_unsigned")
2 values(-9223372036854775809, -1);

1行が作成されました。

CORYDORAS> insert int 2 o num_test_mysql4113a_mac_sv@oracle10g_win("r_bigint","r_bigint_unsigned")
2 values(9223372036854775808, 18446744073709551616);

1行が作成されました。

CORYDORAS> list
1 select *
2 from
3 (
4 select
5 rownum as "rownum",
6 a."r_bigint",
7 a."r_bigint_unsigned"
8 from
9 num_test_mysql4113a_mac_sv@oracle10g_win a
10 )
11 where
12* "rownum" > 27
CORYDORAS> /

rownum r_bigint r_bigint_unsigned
---------------------------------------- ---------------------------------------- ----------------------------------------
28 15537418697586989 48
29 14134441877320249 14697404732553265
30 15537418697586989 14697404732553265
31 15537418697586989 14697404732553265

CORYDORAS> rollback;

ロールバックが完了しました。

CORYDORAS>

次へつづく。

| | | コメント (0) | トラックバック (0)

2006年2月18日 (土)

Mac De Oracle Heterogeneous! #41

数値型のつづき。

Generic Connectivity経由でMySQL4.0.25及び、MySQL4.1.13aの数値型にアクセス 5回目。

Generic Connectivity経由でint型と同型の符号なしにアクセスした結果。

MySQL4.0.2.25、 MySQL4.1.13aともにint型の符号なしは NG。 Generic Connectivity経由で、符号なしint型は利用しないほうがよいだろう。

1)MySQL4.0.25をGeneric Connectivity経由で問い合わせた結果。

CORYDORAS> list
1 select
2 "r_int",
3 "r_int_unsigned"
4 from
5* num_test_mysql4025_mac@oracle10g_win
CORYDORAS> /

r_int r_int_unsigned
---------------------------------------- ----------------------------------------
NULL NULL
0 0
0 0
NULL NULL

中略

NULL NULL
-2147483648 0
2147483647 -1
NULL NULL

中略

NULL NULL

25行が選択されました。

2)MySQL4.1.13aをGeneric Connectivity経由で問い合わせた結果。

CORYDORAS> list
1 select
2 "r_int",
3 "r_int_unsigned"
4 from
5* num_test_mysql4113a_mac_sv@oracle10g_win
CORYDORAS> /

r_int r_int_unsigned
---------------------------------------- ----------------------------------------
NULL NULL
0 0
0 0
NULL NULL

中略

NULL NULL
-2147483648 0
2147483647 -1
NULL NULL

中略

NULL NULL

27行が選択されました。

CORYDORAS>

3)MySQL4.0.25へ最大値、最小値、許容範囲を超える値を登録した結果。

CORYDORAS> insert into num_test_mysql4025_mac@oracle10g_win("r_int", "r_int_unsigned")
2 values(-2147483648,0);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4025_mac@oracle10g_win("r_int", "r_int_unsigned")
2 values(2147483647,4294967295);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4025_mac@oracle10g_win("r_int", "r_int_unsigned")
2 values(-2147483649,-1);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4025_mac@oracle10g_win("r_int", "r_int_unsigned")
2 values(2147483648,4294967296);

1行が作成されました。

CORYDORAS> list
1 select *
2 from
3 (
4 select
5 rownum as "rownum",
6 a."r_int",
7 a."r_int_unsigned"
8 from
9 num_test_mysql4025_mac@oracle10g_win a
10 )
11 where
12* "rownum" > 25
CORYDORAS> /

rownum r_int r_int_unsigned
---------------------------------------- ---------------------------------------- ----------------------------------------
26 -2147483648 0
27 2147483647 -1
28 -2147483648 0
29 2147483647 -1

CORYDORAS> commit;

コミットが完了しました。

CORYDORAS>

4)MySQL4.1.13aへ最大値、最小値、許容範囲を超える値を登録した結果。

CORYDORAS> insert into num_test_mysql4113a_mac_sv@oracle10g_win("r_int", "r_int_unsigned")
2 values(-2147483648,0);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4113a_mac_sv@oracle10g_win("r_int", "r_int_unsigned")
2 values(2147483647,4294967295);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4113a_mac_sv@o 2 racle10g_win("r_int", "r_int_unsigned")
2 values(-2147483649,-1);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4113a_mac_sv@oracle10g_win("r_int", "r_int_unsigned")
2 values(2147483648,4294967296);

1行が作成されました。

CORYDORAS> list
1 select *
2 from
3 (
4 select
5 rownum as "rownum",
6 a."r_int",
7 a."r_int_unsigned"
8 from
9 num_test_mysql4113a_mac_sv@oracle10g_win a
10 )
11 where
12* "rownum" > 27
CORYDORAS> /

rownum r_int r_int_unsigned
---------------------------------------- ---------------------------------------- ----------------------------------------
28 -2147483648 0
29 2147483647 -1
30 -2147483648 0
31 2147483647 -1

CORYDORAS>
CORYDORAS> rollback;

ロールバックが完了しました。

CORYDORAS>

次回につづく。

| | | コメント (0) | トラックバック (0)

2006年2月17日 (金)

Mac De Oracle Heterogeneous! #40

数値型のつづき。

Generic Connectivity経由でMySQL4.0.25及び、MySQL4.1.13aの数値型にアクセス 4回目。

Generic Connectivity経由でmediumint型と同型の符号なしにアクセスした結果。

tinyint,smallint型とは異なり、符号なしでも問題はない。

1)MySQL4.0.25への問合せ。

CORYDORAS> select
2 "r_mediumint",
3 "r_mediumint_unsigned"
4 from
5 num_test_mysql4025_mac@oracle10g_win;

r_mediumint r_mediumint_unsigned
----------- --------------------
NULL NULL
0 0
0 0
NULL NULL

中略

NULL NULL
-8388608 0
8388607 16777215
NULL NULL

中略

NULL NULL

25行が選択されました。

CORYDORAS>

2)MySQL4.0.25への最大値、最小値、及び、許容範囲を超える値の登録。

CORYDORAS> insert into num_test_mysql4025_mac@oracle10g_win("r_mediumint", "r_mediumint_unsigned")
2 values(-8388608,0);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4025_mac@oracle10g_win("r_mediumint", "r_mediumint_unsigned")
2 values(8388607,16777215);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4025_mac@oracle10g_win("r_mediumint", "r_mediumint_unsigned")
2 values(-8388609,-1);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4025_mac@oracle10g_win("r_mediumint", "r_mediumint_unsigned")
2 values(8388608,16777216);

1行が作成されました。


CORYDORAS> list
1 select *
2 from
3 (
4 select
5 rownum as "rownum",
6 a."r_mediumint",
7 a."r_mediumint_unsigned"
8 from
9 num_test_mysql4025_mac@oracle10g_win a
10 )
11 where
12* "rownum" > 25
CORYDORAS> /

rownum r_mediumint r_mediumint_unsigned
---------- ----------- --------------------
26 -8388608 0
27 8388607 16777215
28 -8388608 0
29 8388607 16777215

CORYDORAS> rollback;

ロールバックが完了しました。

3)MySQL4.1.13aへの問合せ。

CORYDORAS> select
2 "r_mediumint",
3 "r_mediumint_unsigned"
4 from
5 num_test_mysql4113a_mac_sv@oracle10g_win;

r_mediumint r_mediumint_unsigned
----------- --------------------
NULL NULL
0 0
0 0
NULL NULL

中略

NULL NULL
-8388608 0
8388607 16777215
NULL NULL

中略

NULL NULL

27行が選択されました。

4)MySQL4.1.13aへの最大値、最小値、及び、許容範囲を超える値の登録。

CORYDORAS> insert into num_test_mysql4113a_mac_sv@oracle10g_win("r_mediumint", "r_mediumint_unsigned")
2 values(-8388608,0);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4113a_mac_sv@oracle10g_win("r_mediumint", "r_mediumint_unsigned")
2 values(8388607,16777215);

1行が作成されました。

CORYDORAS> insert into num_test_mys 2 ql4113a_mac_sv@oracle10g_win("r_mediumint", "r_mediumint_unsigned")
2 values(-8388609,-1);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4113a_mac_sv@oracle10g_win("r_mediumint", "r_mediumint_unsigned")
2 values(8388608,16777216);

1行が作成されました。

CORYDORAS> list
1 select *
2 from
3 (
4 select
5 rownum as "rownum",
6 a."r_mediumint",
7 a."r_mediumint_unsigned"
8 from
9 num_test_mysql4113a_mac_sv@oracle10g_win a
10 )
11 where
12* "rownum" > 27
CORYDORAS> /

rownum r_mediumint r_mediumint_unsigned
---------- ----------- --------------------
28 -8388608 0
29 8388607 16777215
30 -8388608 0
31 8388607 16777215

CORYDORAS> rollback;

ロールバックが完了しました。

CORYDORAS>

次回へつづく。

| | | コメント (0) | トラックバック (0)

2006年2月16日 (木)

Mac De Oracle Heterogeneous! #39

数値型のつづき。

Generic Connectivity経由でMySQL4.0.25及び、MySQL4.1.13aの数値型にアクセス 3回目。

1) smallint型及び、同型の符号なし。

tinyint型の場合と同様に符号なしは、NG。

CORYDORAS> select
2 "r_smallint",
3 "r_smallint_unsigned"
4 from
5 num_test_mysql4025_mac@oracle10g_win;

r_smallint r_smallint_unsigned
---------- -------------------
NULL NULL
0 0
0 0
NULL NULL
NULL NULL
-32768 0
32767 -1
NULL NULL

中略

NULL NULL

25行が選択されました。

CORYDORAS>

1−1)MySQL4.0.25への最大値と最小値、許容範囲を超える値の登録。

これもMySQL側の挙動の通りだが、符号なしは NG。

CORYDORAS> insert into num_test_mysql4025_mac@oracle10g_win("r_smallint", "r_smallint_unsigned")
2 values(-32768,0);

1行が作成されました。

insert into num_test_mysql4025_mac@oracle10g_win("r_smallint", "r_smallint_unsigned")
2 values(32767,65535);

1行が作成されました。

insert into num_test_mysql4025_mac@oracle10g_win("r_smallint", "r_smallint_unsigned")
2 values(-32769,-1);

1行が作成されました。

insert into num_test_mysql4025_mac@oracle10g_win("r_smallint", "r_smallint_unsigned")
2 values(32768,65536);

1行が作成されました。


CORYDORAS> list
1 select *
2 from
3 (
4 select
5 rownum as "rownum",
6 a."r_smallint",
7 a."r_smallint_unsigned"
8 from
9 num_test_mysql4025_mac@oracle10g_win a
10 )
11 where
12* "rownum" > 25
CORYDORAS> /

rownum r_smallint r_smallint_unsigned
---------- ---------- -------------------
26 -32768 0
27 32767 -1
28 -32768 0
29 32767 -1

CORYDORAS>

CORYDORAS> rollback;

ロールバックが完了しました。

1−2)MySQL4.1.13aへの最大値と最小値、許容範囲を超える値の登録。

これもMySQL側の挙動の通りだが、符号なしは NG。

CORYDORAS> insert into num_test_mysql4113a_mac_sv@oracle10g_win("r_smallint", "r_smallint_unsigned")
2 values(-32768,0);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4113a_mac_sv@oracle10g_win("r_smallint", "r_smallint_unsigned")
2 values(32767,65535);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4113a_mac 2 _sv@oracle10g_win("r_smallint", "r_smallint_unsigned")
2 values(-32769,-1);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4113a_mac_sv@oracle10g_win("r_smallint", "r_smallint_unsigned")
2 values(32768,65536);

1行が作成されました。

CORYDORAS> select *
2 from
3 (
4 select
5 rownum as "rownum",
6 a."r_smallint",
7 a."r_smallint_unsigned"
8 from
9 num_test_mysql4113a_mac_sv@oracle10g_win a
10 )
11 where
12 "rownum" > 27;

rownum r_smallint r_smallint_unsigned
---------- ---------- -------------------
28 -32768 0
29 32767 -1
30 -32768 0
31 32767 -1

CORYDORAS> rollback;

ロールバックが完了しました。

CORYDORAS>

次回へつづく。

| | | コメント (0) | トラックバック (0)

2006年2月15日 (水)

Mac De Oracle Heterogeneous! #38

数値型のつづき。
Generic Connectivity経由でMySQL4.0.25及び、MySQL4.1.13aの数値型にアクセス 2回目。 tinyint型と同型の符号なし。

1)MySQLのtinyint型及び、同型の符号なしの検証。

  tinyint型は問題ないのだが、符号なしは NG。

1−1)MySQL4.1.13aにGeneric Connectivity経由で問合せをした結果

CORYDORAS> list
1 select
2 "r_tinyint",
3 "r_tinyint_unsigned"
4 from
5* num_test_mysql4113a_mac_sv@oracle10g_win
CORYDORAS> /

r_tinyint r_tinyint_unsigned
---------- ------------------
NULL NULL
0 0
0 0
-128 0
127 -1
NULL NULL
NULL NULL

中略

NULL NULL

27行が選択されました。

CORYDORAS>

1−2)MySQL4.0.25にGeneric Connectivity経由で問合せをした結果

CORYDORAS> list
1 select
2 "r_tinyint",
3 "r_tinyint_unsigned"
4 from
5* num_test_mysql4025_mac@oracle10g_win
CORYDORAS> /

r_tinyint r_tinyint_unsigned
---------- ------------------
NULL NULL
0 0
0 0
-128 0
127 -1
NULL NULL

中略

NULL NULL

25行が選択されました。

CORYDORAS>

1−3)MySQL4.1.13aへGeneric Connectivity経由でインサート文を発行。
   各型の最小値、最大値、許容範囲を超える値を登録。

MySQL上ではワーニングが返るが、Generic Connectivity経由では正常に処理される。MySQL側では許容範囲を超える数値は丸められ、最小値、最大値に置換される。

CORYDORAS> insert into num_test_mysql4113a_mac_sv@oracle10g_win("r_tinyint", "r_tinyint_unsigned")
2 values(-128,0);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4113a_mac_sv@oracle10g_win("r_tinyint","r_tinyint_unsigned")
2 values(127,255);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4113a_mac_sv@oracle10g_win("r_tinyint","r_tinyint_unsigned")
2 values(-129,-1);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4113a_mac_sv@oracle10g_win("r_tinyint","r_tinyint_unsigned")
2 values(128,256);

1行が作成されました。

CORYDORAS> list
1 select *
2 from
3 (
4 select
5 rownum as "rownum",
6 a."r_tinyint",
7 a."r_tinyint_unsigned"
8 from
9 num_test_mysql4113a_mac_sv@oracle10g_win a
10 )
11 where
12* "rownum" > 27
CORYDORAS> /

rownum r_tinyint r_tinyint_unsigned
---------- ---------- ------------------
28 -128 0
29 127 -1
30 -128 0
31 127 -1

CORYDORAS>

CORYDORAS> rollback;

ロールバックが完了しました。

1−4)MySQL4.0.25へGeneric Connectivity経由でインサート文を発行。
    各型の最小値、最大値、許容範囲を超える値を登録。

結果は、MySQL4.1.13aと同じ。

CORYDORAS> insert into num_test_mysql4025_mac@oracle10g_win("r_tinyint", "r_tinyint_unsigned")
2 values(-128,0);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4025_mac@oracle10g_win("r_tinyint","r_tinyint_unsigned")
2 values(127,255);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4025_mac@oracle10g_win("r_tinyint","r_tinyint_unsigned")
2 values(-129,-1);

1行が作成されました。

CORYDORAS> insert into num_test_mysql4025_mac@oracle10g_win("r_tinyint","r_tinyint_unsigned")
2 values(128,256);

1行が作成されました。

CORYDORAS> list
1 select *
2 from
3 (
4 select
5 rownum as "rownum",
6 a."r_tinyint",
7 a."r_tinyint_unsigned"
8 from
9 num_test_mysql4025_mac@oracle10g_win a
10 )
11 where
12* "rownum" > 25
CORYDORAS> /

rownum r_tinyint r_tinyint_unsigned
---------- ---------- ------------------
26 -128 0
27 127 -1
28 -128 0
29 127 -1

CORYDORAS> rollback;

ロールバックが完了しました。

CORYDORAS> select count(*) from num_test_mysql4025_mac@oracle10g_win;

COUNT(*)
----------
25

CORYDORAS>

次回につづく。

| | | コメント (0) | トラックバック (0)

2006年2月14日 (火)

Mac De Oracle Heterogeneous! #37

数値型のつづき。MySQLでの数値型の癖はある程度見えたので、ここからはGeneric Connectivity経由でMySQL4.0.25及び、MySQL4.1.13aの数値型にアクセスし、その挙動を検証する。

以下のような経路でアクセスしている


gencon_blog_img1

Oracle10g R1(Windows XP Professional)には、num_test_mysql4025_mac(MySQL4.0.25のnum_test表へのシノニム)とnum_test_mysql4113a_mac_sv(MySQL4.1.13aのnum_test表へのシノニム)という2つのシノニムを作成しておく。

CORYDORAS> select synonym_name from user_synonyms@oracle10g_win;

SYNONYM_NAME
------------------------------
NUM_TEST_POSTGRESQL749_MAC
NUM_TEST_MYSQL4113A_MAC_SV
NUM_TEST_MYSQL4025_MAC
DATE_TEST_MYSQL4026_WIN
DATE_TEST_MYSQL4113A_MAC_SV
DATE_TEST_POSTGRESQL749_MAC
EMP_MYSQL4025_MAC
INNO_EMP_MYSQL4025_MAC
EMP_MYSQL4026_WIN
EMP_MYSQL4113A_MAC_SV
EMP_POSTGRESQL749_MAC
ORACLE_EMP_MYSQL4026_WIN

12行が選択されました。

CORYDORAS>

おっと! いきなり問題発生。27行しかないのに count(*)の結果が14130行とは? 問題はMySQL側にあるように思える。MySQL4.0.25では正しい結果が取得できるが、MySQl4.1.13aでは見ての通り。試しに、execute immediate文で試してみたが同じ結果だった。

さて、どうすればいいか? 

ということで、回避策としてrownumの最大値を取得するという方法(なかなかキツいね。)

CORYDORAS> select count(*) from num_test_mysql4113a_mac_sv@oracle10g_win;

COUNT(*)
----------
14130

CORYDORAS> select count(*) from num_test_mysql4025_mac@oracle10g_win;

COUNT(*)
----------
25

CORYDORAS>

CORYDORAS> set serveroutput on;
CORYDORAS> list
1 declare
2 rows pls_integer;
3 begin
4 execute immediate 'select count(*) as ctr from num_test_mysql4113a_mac_sv@oracle10g_win' into rows;
5 dbms_output.put_line(rows);
6* end;
CORYDORAS> /
14130

PL/SQLプロシージャが正常に完了しました。

CORYDORAS> select max(rownum) from num_test_mysql4113a_mac_sv@oracle10g_win;

MAX(ROWNUM)
----------------------------------------
27

CORYDORAS>

さて、最初から凹み気味だが、MySQLの数値型は、Oracleではすべて number型 にマッピングされる。

CORYDORAS> list
1 select
2 dump("r_tinyint") as "tinyint",
3 dump("r_tinyint_unsigned") as "tinyint_unsigned",
4 dump("r_smallint") as "smallint",
5 dump("r_smallint_unsigned") as "smallint_unsigned",
6 dump("r_mediumint") as "mediumint",
7 dump("r_mediumint_unsigned") as "mediumint_unsigned",
8 dump("r_int") as "int",
9 dump("r_int_unsigned") as "int_unsigned"
10 from
11 num_test_mysql4025_mac@oracle10g_win
12 where
13* rownum <= 2
CORYDORAS> /

tinyint tinyint_unsigned smallint smallint_unsigne mediumint mediumint_unsign int int_unsigned
---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ---------------- ----------------
NULL NULL NULL NULL NULL NULL NULL NULL
Typ=2 Len=1: 128 Typ=2 Len=1: 128 Typ=2 Len=1: 128 Typ=2 Len=1: 128 Typ=2 Len=1: 128 Typ=2 Len=1: 128 Typ=2 Len=1: 128 Typ=2 Len=1: 128
CORYDORAS>

次回につづく。

| | | コメント (0) | トラックバック (0)

2006年2月13日 (月)

Mac De Oracle Heterogeneous! #36

数値型の検証のつづき(MySQL編の第4回目)。。decimal型のdecimal(38,0)とdecimal(38,16)、それらの型で符号なし。

1)decimal型

1−1)decimal(38,0)と符号なしdecimal(38,0)

精度はdouble型と同じであるとマニュアルに記載されているので、decimal(38,0)の場合だとOracleのnumber(38,0)より精度が劣るようだ。
decimal型をOracleに取り込むだけなら、精度の範囲内なので利用できそうであるが、OracleからMySQLへ登録したり更新する場合は注意が必要だ。decimal(16,0)くらいなら利用できる可能性はあるが実際に確認してから利用するか否かを決めた方がよさそうである。

mysql> insert into
-> num_test(r_decimal_38, r_decimal_38_unsigned)
-> values(
-> 99999999999999999999999999999999999999,
-> 0
-> );
Query OK, 1 row affected (0.00 sec)

mysql> insert into
-> num_test(r_decimal_38, r_decimal_38_unsigned)
-> values(
-> -99999999999999999999999999999999999999,
-> 99999999999999999999999999999999999999
-> );
Query OK, 1 row affected (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.07 sec)

mysql> insert into
-> num_test(r_decimal_38, r_decimal_38_unsigned)
-> values(100000000000000000000000000000000000000,-1);
Query OK, 1 row affected (0.00 sec)

mysql> insert into
-> num_test(r_decimal_38,r_decimal_38_unsigned)
-> values(-100000000000000000000000000000000000000,100000000000000000000000000000000000000);
Query OK, 1 row affected (0.00 sec)

mysql> select
-> r_decimal_38,
-> r_decimal_38_unsigned
-> from
-> num_test
-> limit
-> 21,-1;
+-----------------------------------------+----------------------------------------+
| r_decimal_38 | r_decimal_38_unsigned |
+-----------------------------------------+----------------------------------------+
| 99999999999999997748809823456034029568 | 0 |
| -99999999999999997748809823456034029568 | 99999999999999997748809823456034029568 |
| 99999999999999997748809823456034029568 | 0 |
| -99999999999999997748809823456034029568 | 99999999999999997748809823456034029568 |
+-----------------------------------------+----------------------------------------+
4 rows in set (0.00 sec)

mysql> rollback;
Query OK, 0 rows affected (0.39 sec)

mysql>

MySQL4.0.25では正常に見えるが実は、丸め処理が行われている。MySQL4.1.13aで同じインサート文を発行すると2件のワーニングが返される。内容は以下の通り out of range。そして、r_decimal_38の精度は38桁なのだが39桁になってしまった。MySQLのバージョン毎に対応を変えるというか、変えられるような作り込みが必要になる可能性もでてきた。
mysql>
mysql> insert into
-> num_test(r_decimal_38, r_decimal_38_unsigned)
-> values(
-> 99999999999999999999999999999999999999,
-> 0
-> );
Query OK, 1 row affected (0.00 sec)

mysql>
mysql> insert into
-> num_test(r_decimal_38, r_decimal_38_unsigned)
-> values(
-> -99999999999999999999999999999999999999,
-> 99999999999999999999999999999999999999
-> );
Query OK, 1 row affected, 2 warnings (0.01 sec)

mysql> show warnings;
+---------+------+--------------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+--------------------------------------------------------------------------+
| Warning | 1264 | Data truncated; out of range for column 'r_decimal_38' at row 1 |
| Warning | 1264 | Data truncated; out of range for column 'r_decimal_38_unsigned' at row 1 |
+---------+------+--------------------------------------------------------------------------+
2 rows in set (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.06 sec)


mysql> edit
-> \¥g
+-----------------------------------------+----------------------------------------+
| r_decimal_38 | r_decimal_38_unsigned |
+-----------------------------------------+----------------------------------------+
| 100000000000000035527741686413195739136 | 0 |
| -99999999999999999999999999999999999999 | 99999999999999999999999999999999999999 |
+-----------------------------------------+----------------------------------------+
2 rows in set (0.00 sec)

mysql>

1−2)decimal(38,16)と符号なしdecimal(38,16)

これは問題無さそうだと思い見逃しそうになったのだが、よくよく結果をみてみると、decimal(38.16)で最小値はよいのだが、最大値がまずい。精度が22桁なのに、最大値が23桁になっている。(これも不具合だろうか?。Generic Connectivity経由ではdecimal型も利用しないほうがよいかもしれない。まだ、テストしていないので使えるか不明だが。。)
以下、MySQL4.0.25での実行結果。

mysql> insert into
-> num_test(r_decimal_38_16, r_decimal_38_16_unsigned)
-> values
-> (-9999999999999999999999.9999999999999999,0),
-> ( 9999999999999999999999.9999999999999999,9999999999999999999999.9999999999999999);
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 2

mysql> commit;
Query OK, 0 rows affected (0.06 sec)

mysql> insert into
-> num_test(r_decimal_38_16, r_decimal_38_16_unsigned)
-> values(-10000000000000000000000.99999999999999995,-1);
Query OK, 1 row affected (0.00 sec)

mysql> insert into
-> num_test(r_decimal_38_16, r_decimal_38_16_unsigned)
-> values(10000000000000000000000.99999999999999994,10000000000000000000000.99999999999999995);
Query OK, 1 row affected (0.00 sec)

mysql> select
-> r_decimal_38_16,
-> r_decimal_38_16_unsigned
-> from
-> num_test
-> limit
-> 23,-1;
+------------------------------------------+-----------------------------------------+
| r_decimal_38_16 | r_decimal_38_16_unsigned |
+------------------------------------------+-----------------------------------------+
| -9999999999999999999999.9999999999999999 | 0.0000000000000000 |
| 10000000000000000000000.0000000000000000 | 9999999999999999999999.9999999999999999 |
| -9999999999999999999999.9999999999999999 | 0.0000000000000000 |
| 10000000000000000000000.0000000000000000 | 9999999999999999999999.9999999999999999 |
+------------------------------------------+-----------------------------------------+
4 rows in set (0.00 sec)

mysql> rollback;
Query OK, 0 rows affected (0.38 sec)

mysql>

以下、MySQL4.1.13aでの実行結果。精度が1桁多くなる現象もあるが値も微妙に違う。
mysql> insert into
-> num_test(r_decimal_38_16, r_decimal_38_16_unsigned)
-> values
-> (-9999999999999999999999.9999999999999999,0),
-> ( 9999999999999999999999.9999999999999999,9999999999999999999999.9999999999999999);
Query OK, 2 rows affected, 2 warnings (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 2

mysql>
mysql> commit;
Query OK, 0 rows affected (0.05 sec)

mysql>
mysql> insert into
-> num_test(r_decimal_38_16, r_decimal_38_16_unsigned)
-> values(-10000000000000000000000.99999999999999995,-1);
Query OK, 1 row affected, 2 warnings (0.00 sec)

mysql>
mysql> insert into
-> num_test(r_decimal_38_16, r_decimal_38_16_unsigned)
-> values(10000000000000000000000.99999999999999994,10000000000000000000000.99999999999999995);
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> select
-> r_decimal_38_16,
-> r_decimal_38_16_unsigned
-> from
-> num_test
-> limit
-> 25,99;
+------------------------------------------+-----------------------------------------+
| r_decimal_38_16 | r_decimal_38_16_unsigned |
+------------------------------------------+-----------------------------------------+
| -9999999999999999999999.9999999999999999 | 0.0000000000000000 |
| 10000000000000004194304.0000000000000000 | 9999999999999999999999.9999999999999999 |
| -9999999999999999999999.9999999999999999 | 0.0000000000000000 |
| 10000000000000002097152.0000000000000000 | 9999999999999999999999.9999999999999999 |
+------------------------------------------+-----------------------------------------+
4 rows in set (0.00 sec)

mysql>

長いので次回につづく。

| | | コメント (0) | トラックバック (0)

2006年2月12日 (日)

Mac De Oracle Heterogeneous! #35

数値型の検証のつづき(MySQL編の第3回目)・・・float型、double型及び、各型の符号なし

1)float型
MySQL4.0.25とMySQL4.1.13aは同じ挙動であった。オーバーフロー、アンダーフローを丸めてしまう点も同じ。

mysql> insert into 
-> num_test(r_float, r_float_unsigned)
-> values(-3.4e38,0),(3.4e38,null),(-1.2e-38,1.2e-38),(1.2e-38,3.4e38);
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into
-> num_test(r_float, r_float_unsigned)
-> values(-3.5e38,-1.0e38);
Query OK, 1 row affected (0.00 sec)

mysql> insert into
-> num_test(r_float, r_float_unsigned)
-> values(3.5e38,3.5e38);
Query OK, 1 row affected (0.00 sec)

mysql> select
-> r_float,
-> r_float_unsigned
-> from
-> num_test
-> limit
-> 13,-1;
+--------------+------------------+
| r_float | r_float_unsigned |
+--------------+------------------+
| -3.4e+38 | 0 |
| 3.4e+38 | NULL |
| -1.2e-38 | 1.2e-38 |
| 1.2e-38 | 3.4e+38 |
| -3.40282e+38 | 0 |
| 3.40282e+38 | 3.40282e+38 |
+--------------+------------------+
6 rows in set (0.00 sec)

mysql> rollback;

ちなみに、MySQl4.1.13aで同じインサート文を実行すると、ワーニングが2件返され、オーバフローした値、及びアンダーフローした値は、それぞれ最大値、最小値に丸めらる。

mysql> insert into
-> num_test(r_float, r_float_unsigned)
-> values(-3.5e38,-1.0e38);
Query OK, 1 row affected, 2 warnings (0.00 sec)

mysql> show warnings;
+---------+------+---------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------------------------------------+
| Warning | 1264 | Data truncated; out of range for column 'r_float' at row 1 |
| Warning | 1264 | Data truncated; out of range for column 'r_float_unsigned' at row 1 |
+---------+------+---------------------------------------------------------------------+
2 rows in set (0.00 sec)

mysql>

2)double型
MySQL4.0.25は特に問題なさそうだが、MySQL4.1.13aではdouble型の値が0と−0となってしまった。(これも不具合だろう)。double unsigned型のアンダーフロー処理が改善された反面、double型のオーバフローとアンダーフローの丸め処理がデグっているように見える。

+------------+-------------------+
| r_double | r_double_unsigned |
+------------+-------------------+
| 2.3e-308 | 2.3e-308 |
| -2.3e-308 | 1.79e+308 |

となっているが、MySQL4.1.13aでは、double型の丸め処理に問題がありそうな結果だ。
+------------+-------------------+
| r_double | r_double_unsigned |
+------------+-------------------+
| 0 | 0 |
| -0 | 1.79e+308 |

以下、MySQL4.0.25でインサート文を実行した結果

mysql> insert into
-> num_test(r_double,r_double_unsigned)
-> values(-1.79e308,0),(1.79e308,0),(2.3e-308,2.3e-308),(-2.3e-308,1.79e308);
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0

mysql> commit;
Query OK, 0 rows affected (0.08 sec)

mysql> select
-> r_double,
-> r_double_unsigned
-> from
-> num_test
-> limit
-> 17,-1;
+------------+-------------------+
| r_double | r_double_unsigned |
+------------+-------------------+
| -1.79e+308 | 0 |
| 1.79e+308 | 0 |
| 2.3e-308 | 2.3e-308 |
| -2.3e-308 | 1.79e+308 |
+------------+-------------------+
4 rows in set (0.00 sec)

mysql>

以下、MySQL4.1.13aでインサート文を実行した結果。MySQL4.0.25と比べ、double unsigned型のアンダーフローの丸め処理は改善されているようだが、double型のアンダーフロー及びオーバーフローの丸め処理は挙動がおかしくなってしまったようだ。
mysql> insert into
-> num_test(r_double,r_double_unsigned)
-> values(-1.79e308,0),(1.79e308,0),(2.3e-308,2.3e-308),(-2.3e-308,1.79e308);
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0

mysql>
mysql> commit;
Query OK, 0 rows affected (0.08 sec)

mysql> select
-> r_double,
-> r_double_unsigned
-> from
-> num_test
-> limit
-> 19,99;
+------------+-------------------+
| r_double | r_double_unsigned |
+------------+-------------------+
| -1.79e+308 | 0 |
| 1.79e+308 | 0 |

| 0 | 0 |
| -0 | 1.79e+308 |
+------------+-------------------+
4 rows in set (0.00 sec)

以下のような結果からみても、おかしな挙動を示す。(取りあえず使う予定はないからよしとしておくか?!)

mysql> insert into num_test(r_double) values(0.5e-307);
Query OK, 1 row affected (0.00 sec)

mysql> select r_double from num_test limit 27,99;
+----------+
| r_double |
+----------+
| 5e-308 |
+----------+
1 row in set (0.00 sec)

mysql> insert into num_test(r_double) values(2.2e-307);
Query OK, 1 row affected (0.00 sec)

mysql> select r_double from num_test limit 27,99;
+----------+
| r_double |
+----------+
| 5e-308 |
| 0 |
+----------+
2 rows in set (0.00 sec)

mysql> insert into num_test(r_double) values(2.2e-306);
Query OK, 1 row affected (0.00 sec)

mysql> select r_double from num_test limit 27,99;
+----------+
| r_double |
+----------+
| 5e-308 |
| 0 |
| 2.2e-306 |
+----------+
3 rows in set (0.00 sec)

mysql>

長いので次回につづく。

| | | コメント (0) | トラックバック (0)

2006年2月11日 (土)

Mac De Oracle Heterogeneous! #34

数値型の検証のつづき(MySQL編の第2回目)。。。tinyint型、smallint型、mediumint型、int型、bigint型及び、各型の符号なし。

MySQL4.0.25での検証。(MySQL4.1.13aではワーニング返される点がことなるが大きな挙動の差はない。但し、不具合と思われる部分がいくつかある。)
MySQLの仕様なのだが数値型で定義した範囲を超える値を設定した場合はワーニング扱になっている、しかも、上限を超えれば最大値、下限を超えれば最小値に置き換えられる。ちなみに私の知っている商用RDBMSでこのような挙動をするものはないので私にとっては嫌な特徴の一つ。Oracleだけをやってきた方は、”ハマ”りそうな点なので注意しておいたほうがいいだろう。(複数行インサート文では精度超過でワーニングがでるが、MySQL4.0.xでは単一行をインサートする場合はワーニングもでないので要注意。)


1)tinyint型と符号なしtinyint型


Generic Connectivityで扱う場合にも問題は無さそうな気がするが、前述した通り、tinyint型及び、符号なしtinyint型で表現できる範囲を超えた値を設定すると最小値及び最大値に置き換えられてしまうので注意したほうがよい。

mysql> insert into
-> num_test(r_tinyint, r_tinyint_unsigned)
-> values(-128,0);
Query OK, 1 row affected (0.00 sec)

mysql> insert into
-> num_test(r_tinyint, r_tinyint_unsigned)
-> values(127,255);
Query OK, 1 row affected (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> select
-> r_tinyint,
-> r_tinyint_unsigned
-> from
-> num_test
-> limit
-> 3,-1;
+-----------+--------------------+
| r_tinyint | r_tinyint_unsigned |
+-----------+--------------------+
| -128 | 0 |
| 127 | 255 |
+-----------+--------------------+
2 rows in set (0.01 sec)

mysql>


MySQL4.0.25でも表現可能な範囲を超えた値を設定した場合には複数行インサート文ではワーニングが返される。
mysql> insert into
-> num_test(r_tinyint, r_tinyint_unsigned)
-> values(-129,-1), (128,256);
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 4

mysql>
mysql> select
-> r_tinyint,
-> r_tinyint_unsigned
-> from
-> num_test
-> limit
-> 3,-1;
+-----------+--------------------+
| r_tinyint | r_tinyint_unsigned |
+-----------+--------------------+
| -128 | 0 |
| 127 | 255 |
| -128 | 0 |
| 127 | 255 |
+-----------+--------------------+
4 rows in set (0.00 sec)

mysql> rollback;
Query OK, 0 rows affected (0.06 sec)

mysql> insert into
-> num_test(r_tinyint, r_tinyint_unsigned)
-> values(-129, -1);
Query OK, 1 row affected (0.00 sec)

mysql> insert into
-> num_test(r_tinyint, r_tinyint_unsigned)
-> values(128,256);
Query OK, 1 row affected (0.00 sec)

mysql> select
-> r_tinyint,
-> r_tinyint_unsigned
-> from
-> num_test
-> limit
-> 3,-1;
+-----------+--------------------+
| r_tinyint | r_tinyint_unsigned |
+-----------+--------------------+
| -128 | 0 |
| 127 | 255 |
| -128 | 0 |
| 127 | 255 |
+-----------+--------------------+
4 rows in set (0.00 sec)

mysql> rollback;
Query OK, 0 rows affected (0.06 sec)

mysql>

2)smallint型と符号なしsmallint型

mysql> insert into
-> num_test(r_smallint, r_smallint_unsigned)
-> values(-32768,0), (32767,65535);
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0

mysql> commit;
Query OK, 0 rows affected (0.00 sec)


以下のインサート文では表現可能な値より大きい又は小さい値を設定している。
mysql> insert into
-> num_test(r_smallint, r_smallint_unsigned)
-> values(-32769,-1);
Query OK, 1 row affected (0.00 sec)

mysql> insert into
-> num_test(r_smallint, r_smallint_unsigned)
-> values(32768,65536);
Query OK, 1 row affected (0.00 sec)

mysql> select
-> r_smallint,
-> r_smallint_unsigned
-> from
-> num_test
-> limit
-> 5,-1;
+------------+---------------------+
| r_smallint | r_smallint_unsigned |
+------------+---------------------+
| -32768 | 0 |
| 32767 | 65535 |
| -32768 | 0 |
| 32767 | 65535 |
+------------+---------------------+
4 rows in set (0.00 sec)

mysql> rollback;
Query OK, 0 rows affected (0.06 sec)

mysql>

3)mediumint型と符号nasimediumint型

mysql> insert into
-> num_test(r_mediumint, r_mediumint_unsigned)
-> values(-8388608,0), (8388607,16777215);
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

以下のインサート文で表現可能な値より大きい又は小さい値を設定している。
mysql> insert into
-> num_test(r_mediumint, r_mediumint_unsigned)
-> values(-8388609,-1);
Query OK, 1 row affected (0.00 sec)

mysql> insert into
-> num_test(r_mediumint, r_mediumint_unsigned)
-> values(8388608,16777216);
Query OK, 1 row affected (0.00 sec)

mysql> select
-> r_mediumint,
-> r_mediumint_unsigned
-> from
-> num_test
-> limit 7,-1;
+-------------+----------------------+
| r_mediumint | r_mediumint_unsigned |
+-------------+----------------------+
| -8388608 | 0 |
| 8388607 | 16777215 |
| -8388608 | 0 |
| 8388607 | 16777215 |
+-------------+----------------------+
4 rows in set (0.00 sec)

mysql> rollback;
Query OK, 0 rows affected (0.38 sec)

mysql>

4)int型と符号なしint型

mysql> insert into
-> num_test(r_int, r_int_unsigned)
-> values(-2147483648,0), (2147483647,4294967295);
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

以下のインサート文では表現可能な値より大きい又は小さい値を設定している。
mysql> insert into
-> num_test(r_int, r_int_unsigned)
-> values(-2147483649,-1);
Query OK, 1 row affected (0.00 sec)

mysql> insert into
-> num_test(r_int, r_int_unsigned)
-> values(2147483648,4294967296);
Query OK, 1 row affected (0.00 sec)

mysql> select
-> r_int,
-> r_int_unsigned
-> from
-> num_test
-> limit
-> 9,-1;
+-------------+----------------+
| r_int | r_int_unsigned |
+-------------+----------------+
| -2147483648 | 0 |
| 2147483647 | 4294967295 |
| -2147483648 | 0 |
| 2147483647 | 4294967295 |
+-------------+----------------+
4 rows in set (0.00 sec)

mysql> rollback;
Query OK, 0 rows affected (0.39 sec)

mysql>

5)bigint型と符号なしbigint型 

3行目のインサート文では、符号なしbigint型に −1 を設定しているが丸められて 0 にはならなず、符号なしbigint型の最大値が設定される。4行目のインサート文では、正の最大値を超える値(9223372036854775808)を設定してるにもかかわらず、負の最大値が設定されている。 (不具合だと思われる。)

mysql> insert into
-> num_test(r_bigint, r_bigint_unsigned)
-> values(-9223372036854775808,0), (9223372036854775807,18446744073709551615);
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

以下のインサート文では表現可能な値より大きい又は小さい値を設定している。
mysql> insert into
-> num_test(r_bigint, r_bigint_unsigned)
-> values(-9223372036854775809, -1);
Query OK, 1 row affected (0.00 sec)

mysql> insert into
-> num_test(r_bigint, r_bigint_unsigned)
-> values(9223372036854775808, 18446744073709551616);
Query OK, 1 row affected (0.00 sec)

mysql> select
-> r_bigint,
-> r_bigint_unsigned
-> from
-> num_test
-> limit
-> 11,-1;
+----------------------+----------------------+
| r_bigint | r_bigint_unsigned |
+----------------------+----------------------+
| -9223372036854775808 | 0 |
| 9223372036854775807 | 18446744073709551615 |
| -9223372036854775808 | 18446744073709551615 |
| -9223372036854775808 | 18446744073709551615 |
+----------------------+----------------------+
4 rows in set (0.00 sec)

mysql>


尚、MySQL4.1.13aでは3行目と4行目のインサート文でワーニングが1件返される。(ワーニングは2件じゃないのかな? これも不具合のようだが・・・。)
5.x以降ではどのようになるかは分からないが、少なくともMySQL4.x台を対象にしたGeneric Connectivityで、bigint型は利用しないほうがよいだろう。(厳密に範囲チェックし精度を超えないようにすればなんとかなるかもしれないが・・・・・所詮そのプログラムも人が作るもの。バグがないとも限らない。)

mysql> insert into
-> num_test(r_bigint, r_bigint_unsigned)
-> values(-9223372036854775808,0), (9223372036854775807,18446744073709551615);
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0

mysql>
mysql> commit;
Query OK, 0 rows affected (0.07 sec)

mysql>
以下のインサート文では表現可能な値より大きい又は小さい値を設定している。
mysql> insert into
-> num_test(r_bigint, r_bigint_unsigned)
-> values(-9223372036854775809, -1);
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql>
mysql> insert into
-> num_test(r_bigint, r_bigint_unsigned)
-> values(9223372036854775808, 18446744073709551616);
Query OK, 1 row affected, 1 warning (0.00 sec)

mysql> select
-> r_bigint,
-> r_bigint_unsigned
-> from
-> num_test
-> limit
-> 11,99;
+----------------------+----------------------+
| r_bigint | r_bigint_unsigned |
+----------------------+----------------------+
| -9223372036854775808 | 0 |
| 9223372036854775807 | 18446744073709551615 |
| -9223372036854775808 | 18446744073709551615 |
| -9223372036854775808 | 18446744073709551615 |
+----------------------+----------------------+
4 rows in set (0.00 sec)

mysql>

次回につづく。

| | | コメント (0) | トラックバック (0)

2006年2月10日 (金)

Mac De Oracle Heterogeneous! #33

つづきです。数値型の検証(MySQL編の第一回目)。。。PostgreSQLとは一味違った癖がありそうな予感。

赤で囲まれたデータベースを利用した。

gencon_blog_img33

MySQL4.0.25で、null、0、そして空文字を設定した。PostgreSQLやOracleとは異なり、空文字を設定すると0が設定されてしまう。PostgreSQLやOracleではエラーなので注意してたポイントだ。コーディング規約で空文字で数値型を初期化したりしないように縛っていたほうがよいかもしれない。
MySQL4.1.13aで同じことを行うと、仕様変更されたようで、空文字についてはワーニングが返される、しかし、エラーではないのでGeneric Connectivity経由ではエラーになることはないと予想される。この手のワーニングをエラー扱いにできれば、PostgreSQLやOracleと同じハンドリングで済むのだが。
マニュアルと読んでいたら、5.0.2以降では、sql_mode=traditionalとするとワーニングではなくエラーが返されるらしい。。今回は4.0と4.1なので使えない。

以下は、MySQL4.0.25で行った結果である。

mysql> insert into num_test
-> values(null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null);
Query OK, 1 row affected (0.07 sec)

mysql> insert into num_test
-> values(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
Query OK, 1 row affected (0.39 sec)

mysql> insert into num_test
-> values('','','','','','','','','','','','','','','','','','');
Query OK, 1 row affected (0.37 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from num_test¥G
*************************** 1. row ***************************
r_tinyint: NULL
r_tinyint_unsigned: NULL
r_smallint: NULL
r_smallint_unsigned: NULL
r_mediumint: NULL
r_mediumint_unsigned: NULL
r_int: NULL
r_int_unsigned: NULL
r_bigint: NULL
r_bigint_unsigned: NULL
r_float: NULL
r_float_unsigned: NULL
r_double: NULL
r_double_unsigned: NULL
r_decimal_38: NULL
r_decimal_38_unsigned: NULL
r_decimal_38_16: NULL
r_decimal_38_16_unsigned: NULL
*************************** 2. row ***************************
r_tinyint: 0
r_tinyint_unsigned: 0
r_smallint: 0
r_smallint_unsigned: 0
r_mediumint: 0
r_mediumint_unsigned: 0
r_int: 0
r_int_unsigned: 0
r_bigint: 0
r_bigint_unsigned: 0
r_float: 0
r_float_unsigned: 0
r_double: 0
r_double_unsigned: 0
r_decimal_38: 0
r_decimal_38_unsigned: 0
r_decimal_38_16: 0.0000000000000000
r_decimal_38_16_unsigned: 0.0000000000000000
*************************** 3. row ***************************
r_tinyint: 0
r_tinyint_unsigned: 0
r_smallint: 0
r_smallint_unsigned: 0
r_mediumint: 0
r_mediumint_unsigned: 0
r_int: 0
r_int_unsigned: 0
r_bigint: 0
r_bigint_unsigned: 0
r_float: 0
r_float_unsigned: 0
r_double: 0
r_double_unsigned: 0
r_decimal_38: 0
r_decimal_38_unsigned: 0
r_decimal_38_16: 0.0000000000000000
r_decimal_38_16_unsigned: 0.0000000000000000
3 rows in set (0.00 sec)

mysql>

以下は、MySQL4.1.13aで行ったもの。空文字をインサートするとワーニングが返されていることがわかるだろうか?

mysql> insert into num_test
-> values(null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null);
Query OK, 1 row affected (0.10 sec)

mysql> insert into num_test
-> values(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
Query OK, 1 row affected (0.07 sec)

mysql> insert into num_test
-> values('','','','','','','','','','','','','','','','','','');
Query OK, 1 row affected, 13 warnings (0.09 sec)

mysql> commit;


次回につづく。

| | | コメント (0) | トラックバック (0)

2006年2月 9日 (木)

Mac De Oracle Heterogeneous! #32

PostgreSQLに引き続き、MySQLで数値型の検証を行った。(一連の検証では、それほど深く検証している訳ではない。Generic ConnectivityでOracleと他のRDBMSを連携させようと思うのなら、さらに詳細な検証を行うことをお勧めする。MySQL4.0、4.1、5.0とかなりの仕様が変更されているので、各バージョンで挙動が異なることが予想されるのもその理由だ。)

PowerBook G4 MacOSX Tiger 10.4.4のMySQL4.0.25 standardと、PowerMac G5 MacOSX Tiger Server 10.4.3のMySQL4.1.13aで検証を行った。
以下のような経路でアクセスするのだが、

gencon_blog_img1


まず最初はMySQL側で数値型の癖を把握しておく。

Powerbook G4 の MySQL4.0.25及び、PowerMac G5の MySQL4.1.13aには以下の表を作成した。

mysql> desc num_test;
+--------------------------+-------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------------------+-------------------------+------+-----+---------+-------+
| r_tinyint | tinyint(4) | YES | | NULL | |
| r_tinyint_unsigned | tinyint(3) unsigned | YES | | NULL | |
| r_smallint | smallint(6) | YES | | NULL | |
| r_smallint_unsigned | smallint(5) unsigned | YES | | NULL | |
| r_mediumint | mediumint(9) | YES | | NULL | |
| r_mediumint_unsigned | mediumint(8) unsigned | YES | | NULL | |
| r_int | int(11) | YES | | NULL | |
| r_int_unsigned | int(10) unsigned | YES | | NULL | |
| r_bigint | bigint(20) | YES | | NULL | |
| r_bigint_unsigned | bigint(20) unsigned | YES | | NULL | |
| r_float | float | YES | | NULL | |
| r_float_unsigned | float unsigned | YES | | NULL | |
| r_double | double | YES | | NULL | |
| r_double_unsigned | double unsigned | YES | | NULL | |
| r_decimal_38 | decimal(38,0) | YES | | NULL | |
| r_decimal_38_unsigned | decimal(38,0) unsigned | YES | | NULL | |
| r_decimal_38_16 | decimal(38,16) | YES | | NULL | |
| r_decimal_38_16_unsigned | decimal(38,16) unsigned | YES | | NULL | |
+--------------------------+-------------------------+------+-----+---------+-------+
18 rows in set (0.00 sec)

mysql>

MySQL4.0.25では問題なかった?!のだが、MySQL4.1.13aで同じDDLを実行するとワーニングがでる。
以下は、MySQL4.1.13aで表を作成したログ。

mysql> create table num_test
-> (
-> r_tinyint tinyint,
-> r_tinyint_unsigned tinyint unsigned,
-> r_smallint smallint,
-> r_smallint_unsigned smallint unsigned,
-> r_mediumint mediumint,
-> r_mediumint_unsigned mediumint unsigned,
-> r_int int,
-> r_int_unsigned int unsigned,
-> r_bigint bigint,
-> r_bigint_unsigned bigint unsigned,
-> r_float float,
-> r_float_unsigned float unsigned,
-> r_double double,
-> r_double_unsigned double unsigned,
-> r_decimal_38 decimal(38,0),
-> r_decimal_38_unsigned decimal(38,0) unsigned,
-> r_decimal_38_16 decimal(38,16),
-> r_decimal_38_16_unsigned decimal(38,16) unsigned
-> ) type=InnoDB;
Query OK, 0 rows affected, 1 warning (0.14 sec)

なんだろう。ワーニングがでるが表は作成されている。

mysql> desc num_test;
+--------------------------+-------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------------------+-------------------------+------+-----+---------+-------+
| r_tinyint | tinyint(4) | YES | | NULL | |
| r_tinyint_unsigned | tinyint(3) unsigned | YES | | NULL | |
| r_smallint | smallint(6) | YES | | NULL | |
| r_smallint_unsigned | smallint(5) unsigned | YES | | NULL | |
| r_mediumint | mediumint(9) | YES | | NULL | |
| r_mediumint_unsigned | mediumint(8) unsigned | YES | | NULL | |
| r_int | int(11) | YES | | NULL | |
| r_int_unsigned | int(10) unsigned | YES | | NULL | |
| r_bigint | bigint(20) | YES | | NULL | |
| r_bigint_unsigned | bigint(20) unsigned | YES | | NULL | |
| r_float | float | YES | | NULL | |
| r_float_unsigned | float unsigned | YES | | NULL | |
| r_double | double | YES | | NULL | |
| r_double_unsigned | double unsigned | YES | | NULL | |
| r_decimal_38 | decimal(38,0) | YES | | NULL | |
| r_decimal_38_unsigned | decimal(38,0) unsigned | YES | | NULL | |
| r_decimal_38_16 | decimal(38,16) | YES | | NULL | |
| r_decimal_38_16_unsigned | decimal(38,16) unsigned | YES | | NULL | |
+--------------------------+-------------------------+------+-----+---------+-------+
18 rows in set (0.00 sec)

MySQL初心者なのでワーニングメッセージを表示させる方法が判らない。ヘルプで見てみると、 show warnings がそれらしいので試してみと
表のデータベースエンジンの指定は、typeではなく、engineを利用しなさいということらしい。とりあえず表は作成されたのでこのまま進めることにした。
(日付型の検証を行ったときにも出ていたのだが・・・・。確認漏れだ)

mysql> show warnings;
+---------+------+--------------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+--------------------------------------------------------------------------+
| Warning | 1287 | 'TYPE=storage_engine' is deprecated; use 'ENGINE=storage_engine' instead |
+---------+------+--------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql>

typeよりengineのほうが分かりやすいと思うが、type= としたらエラーにしちゃえばいいじゃん。ワーニングにしておく意味があるのだろうか。と思うのは私だけか?! 
とMySQLのオンラインマニュアルのcreate table文を確認してみたのだが、これに関連する記述が見当たらない。4.1のマニュアルを見ても、typeはengineのシノニムですという記述だけだったのだ。まぁ、マニュアルのメンテ漏れなのだろうとよい方に解釈して、次から engine=innoDB を使う事にする。
次回につづく。

| | | コメント (0) | トラックバック (0)

2006年2月 8日 (水)

Mac De Oracle Heterogeneous! #31

前回のつづきです。やっと、数値型(PostgreSQL編)の最終回。PostgreSQLの数値型をGeneric Connectivity経由でアクセス。

real型。関わっているシステムではほとんど使っていないのだが、念のために試してみた。なんとか使えそう。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_real") values(3.4e38);

1行が作成されました。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_real") values(-3.4e38);

1行が作成されました。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_real") values(1.2e-38);

1行が作成されました。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_real") values(-1.2e-38);

1行が作成されました。

CORYDORAS> commit;

コミットが完了しました。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_real") values(3.5e38);
insert into num_test_postgresql749_mac@oracle10g_win("r_real") values(3.5e38)
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC]ERROR: type "real" value out of range: overflow (SQL State: S1000; SQL Code: 7)
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_real") values(-3.5e38);
insert into num_test_postgresql749_mac@oracle10g_win("r_real") values(-3.5e38)
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC]ERROR: type "real" value out of range: overflow (SQL State: S1000; SQL Code: 7)
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_real") values(1.1e-38);
insert into num_test_postgresql749_mac@oracle10g_win("r_real") values(1.1e-38)
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC]ERROR: type "real" value out of range: underflow (SQL State: S1000; SQL Code: 7)
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_real") values(-1.1e-38);
insert into num_test_postgresql749_mac@oracle10g_win("r_real") values(-1.1e-38)
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC]ERROR: type "real" value out of range: underflow (SQL State: S1000; SQL Code: 7)
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_real") values(3.4e39);
insert into num_test_postgresql749_mac@oracle10g_win("r_real") values(3.4e39)
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC]ERROR: type "real" value out of range: overflow (SQL State: S1000; SQL Code: 7)
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_real") values(1.2e-39);
insert into num_test_postgresql749_mac@oracle10g_win("r_real") values(1.2e-39)
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC]ERROR: type "real" value out of range: underflow (SQL State: S1000; SQL Code: 7)
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> list
1 select *
2 from
3 (
4 select
5 rownum as "rownum",
6 a.*
7 from
8 num_test_postgresql749_mac@oracle10g_win a
9 )
10 where
11* "rownum" > 47
CORYDORAS> /

rownum r_smallint r_integer r_bigint r_numeric38 r_numeric38_16 r_real r_double
---------- ---------- ------------ ----------------------- --------------------------------------- ---------------------------------------- ---------- ----------
48 NULL NULL NULL NULL NULL 3.4000E+38 NULL
49 NULL NULL NULL NULL NULL -3.400E+38 NULL
50 NULL NULL NULL NULL NULL 1.2000E-38 NULL
51 NULL NULL NULL NULL NULL -1.200E-38 NULL

CORYDORAS>

double precision型。関わっているシステムでは全く利用されていなかったのだが、これまた興味本位で調べてみた。問合せでは、tilde表示されていた 1.79e308と-1.79e308だが insert時にはエラーになる。前述した通り、現時点ではdouble precisionは利用しない方が無難かな。
パススルーさせれば登録できなくもないと思うが。。。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_double") values(1.79e308);
insert into num_test_postgresql749_mac@oracle10g_win("r_double") values(1.79e308)
*
行1でエラーが発生しました。:
ORA-01426: 数値オーバーフローが発生しました


CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_double") values(-1.79e308);
insert into num_test_postgresql749_mac@oracle10g_win("r_double") values(-1.79e308)
*
行1でエラーが発生しました。:
ORA-01426: 数値オーバーフローが発生しました


CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_double") values(2.3e-308);

1行が作成されました。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_double") values(-2.3e-308);

1行が作成されました。

CORYDORAS> commit;

コミットが完了しました。


CORYDORAS> select *
2 from
3 (
4 select
5 rownum as "rownum",
6 a.*
7 from
8 num_test_postgresql749_mac@oracle10g_win a
9 )
10 where
11 "rownum" > 51;

rownum r_smallint r_integer r_bigint r_numeric38 r_numeric38_16 r_real r_double
---------- ---------- ------------ ----------------------- --------------------------------------- ---------------------------------------- ---------- ----------
52 NULL NULL NULL NULL NULL NULL 0
53 NULL NULL NULL NULL NULL NULL 0

CORYDORAS>

========================
数値型のまとめ(PostgreSQL7.4.9編)

利用している psqlODBCドライバなどはこちら

数値型マッピング
PostgreSQL7.4.9Oracle10g R1Generic Connectivityでの利用備 考
smallint型number型
integer型
bigint型
numeric型 Oracle number型の精度と位置取り範囲内であれば問題なし。但し、精度と位置取りを超えていても格納されている値が精度と位置取り範囲内であれば利用できないこともないが、利用する際には十分な事前調査が必要。
real型
double precision型×Oracle number型の精度範囲内であれば利用できないこともないが、利用するのは避けたほうが無難。どうしても利用したいならOracleのbinary double型にマップするようなアプローチ方法を考えたほうがよいと思う。

numeric型の精度には注意が必要だが、double precision型以外はGeneric Connectivity経由でも違和感無く利用できそうだ。

次回は、MySQLで数値型の癖を確認することにする。

| | | コメント (0) | トラックバック (0)

2006年2月 7日 (火)

Mac De Oracle Heterogeneous! #30

前回のつづきです。numeric型について少しだけ掘り下げてみた。

PostgreSQLのnumeric型の精度は無制限となっている。一方Oracleのnumber型はprecisionが38、scaleが−84から127となっている。
当然だが、Oracleのnumber型の精度と位置取りの制限を超える値の場合は問題が発生する。以下は精度を80に設定した場合の例である。
Oracle側では、number(80,0)とはできないのでエラーになってしまう。但し、PostgreSQL型の定義がnumeric(80,0)であっても、格納されている値が制限範囲内であれば問題はない。numeric型や、decimal型がPostgreSQL側で利用されている場合には、定義されているprecisionやscale及び、格納されている値の最小値、最大値も調査しておいたほうがよいだろう。

PostgreSQL側で numeric(80,0)の列を追加して、値を設定しておく。

pb17:˜ postgres$ psql -U scott postgresql749
Password:
Welcome to psql 7.4.9, the PostgreSQL interactive terminal.

Type: ¥copyright for distribution terms
¥h for help with SQL commands
¥? for help on internal slash commands
¥g or terminate with semicolon to execute query
¥q to quit

postgresql749=>
postgresql749=>
postgresql749=>
postgresql749=> ¥d num_test
Table "scott.num_test"
Column | Type | Modifiers
----------------+------------------+-----------
r_smallint | smallint |
r_integer | integer |
r_bigint | bigint |
r_numeric38 | numeric(38,0) |
r_numeric38_16 | numeric(38,16) |
r_real | real |
r_double | double precision |

postgresql749=> alter table num_test add column r_numeric numeric(80,0);
ALTER TABLE
postgresql749=> commit;
COMMIT
postgresql749=> ¥d num_test
Table "scott.num_test"
Column | Type | Modifiers
----------------+------------------+-----------
r_smallint | smallint |
r_integer | integer |
r_bigint | bigint |
r_numeric38 | numeric(38,0) |
r_numeric38_16 | numeric(38,16) |
r_real | real |
r_double | double precision |
r_numeric | numeric(80,0) |

postgresql749=> insert into num_test(r_numeric) values(9e79);
INSERT 25529 1
postgresql749=> commit;
COMMIT
postgresql749=> select r_numeric from num_test where r_numeric is not null;
r_numeric
----------------------------------------------------------------------------------
90000000000000000000000000000000000000000000000000000000000000000000000000000000
(1 row)

postgresql749=>


Oracle側で問い合わせてみると・・・・・・以下のようになる。number型の精度内の値が設定されていれば問題ないが、それを超えているとエラーが発生する。

CORYDORAS>
CORYDORAS> select "r_numeric" from num_test_postgresql749_mac@oracle10g_win where "r_numeric" is not null;
select "r_numeric" from num_test_postgresql749_mac@oracle10g_win where "r_numeric" is not null
*
行1でエラーが発生しました。:
ORA-28528: 異機種間サービス・データ型の変換中にエラーが発生しました。
ORA-02063: 先行のエラー・メッセージを参照してくださいline(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(ORACLE10G_WIN)。

CORYDORAS> delete from num_test_postgresql749_mac@oracle10g_win where "r_numeric" > 0;

1行が削除されました。

CORYDORAS> commit;

コミットが完了しました。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_numeric") values(9e37);

1行が作成されました。

CORYDORAS> commit;

コミットが完了しました。

CORYDORAS> select "r_numeric" from num_test_postgresql749_mac@oracle10g_win where "r_numeric" > 0;

r_numeric
----------
9.0000E+37

CORYDORAS>


次回につづく。

| | | コメント (0) | トラックバック (0)

2006年2月 6日 (月)

Mac De Oracle Heterogeneous! #29

つづきです。PostgreSQLの数値型をGeneric Connectivity経由でアクセス。

numeric型も特に扱いづらいという点は無さそうだ。(小数点以下を指定してしまった場合の扱いもオラクルと同じで四捨五入してくれる)

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38") values(-99999999999999999999999999999999999999);

1行が作成されました。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38") values(99999999999999999999999999999999999999);

1行が作成されました。

CORYDORAS> commit;

コミットが完了しました。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38") values(-100000000000000000000000000000000000000);
insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38") values(-100000000000000000000000000000000000000)
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC]ERROR: numeric field overflow (SQL State: S1000; SQL Code: 7)
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38") values(100000000000000000000000000000000000000);
insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38") values(100000000000000000000000000000000000000)
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC]ERROR: numeric field overflow (SQL State: S1000; SQL Code: 7)
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38") values(-0.4);

1行が作成されました。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38") values(-0.5);

1行が作成されました。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38") values(0.4);

1行が作成されました。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38") values(0.5);

1行が作成されました。

CORYDORAS> commit;

コミットが完了しました。

CORYDORAS> select *
2 from
3 (
4 select
5 rownum as "rownum",
6 a.*
7 from
8 num_test_postgresql749_mac@oracle10g_win a
9 )
10 where
11 "rownum" > 37;

rownum r_smallint r_integer r_bigint r_numeric38 r_numeric38_16 r_real r_double
---------- ---------- ------------ ----------------------- --------------------------------------- ---------------------------------------- ---------- ----------
38 NULL NULL NULL -99999999999999999999999999999999999999 NULL NULL NULL
39 NULL NULL NULL 99999999999999999999999999999999999999 NULL NULL NULL
40 NULL NULL NULL 0 NULL NULL NULL
41 NULL NULL NULL -1 NULL NULL NULL
42 NULL NULL NULL 0 NULL NULL NULL
43 NULL NULL NULL 1 NULL NULL NULL

6行が選択されました。

CORYDORAS>


scaleを16にした例だが、特に気になる点はない。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38_16") values(-9999999999999999999999.9999999999999999);

1行が作成されました。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38_16") values(9999999999999999999999.9999999999999999);

1行が作成されました。

CORYDORAS> commit;

コミットが完了しました。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38_16") values(-9999999999999999999999.99999999999999995);
insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38_16") values(-9999999999999999999999.99999999999999995)
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC][A0C9] Value for column r_numeric38_16 exceeds column's length.
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38_16") values(9999999999999999999999.99999999999999994);

1行が作成されました。

CORYDORAS> rollback;

ロールバックが完了しました。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38_16") values(-9999999999999999999999.99999999999999995);
insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38_16") values(-9999999999999999999999.99999999999999995)
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC][A0C9] Value for column r_numeric38_16 exceeds column's length.
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38_16") values(-9999999999999999999999.99999999999999994);
insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38_16") values(-9999999999999999999999.99999999999999994)
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC][A0C9] Value for column r_numeric38_16 exceeds column's length.
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38_16") values(9999999999999999999999.99999999999999995);
insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38_16") values(9999999999999999999999.99999999999999995)
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC]ERROR: numeric field overflow (SQL State: S1000; SQL Code: 7)
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38_16") values(9999999999999999999999.9999999999999994);

1行が作成されました。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38_16") values(99999999999999999999999.9999999999999999);
insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38_16") values(99999999999999999999999.9999999999999999)
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC]ERROR: numeric field overflow (SQL State: S1000; SQL Code: 7)
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38_16") values(-99999999999999999999999.9999999999999999);
insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38_16") values(-99999999999999999999999.9999999999999999)
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC][A0C9] Value for column r_numeric38_16 exceeds column's length.
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38_16") values(-99999999999999999999999.999999999999999);
insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38_16") values(-99999999999999999999999.999999999999999)
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC]ERROR: numeric field overflow (SQL State: S1000; SQL Code: 7)
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38_16") values(-9999999999999999999999.99999999999999995);
insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38_16") values(-9999999999999999999999.99999999999999995)
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC][A0C9] Value for column r_numeric38_16 exceeds column's length.
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> rollback;

ロールバックが完了しました。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38_16") values(0.99999999999999995);

1行が作成されました。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38_16") values(0.99999999999999994);

1行が作成されました。

CORYDORAS> commit;

コミットが完了しました。

CORYDORAS> select *
2 from
3 (
4 select
5 rownum as "rownum",
6 a.*
7 from
8 num_test_postgresql749_mac@oracle10g_win a
9 )
10 where
11 "rownum" > 43;

rownum r_smallint r_integer r_bigint r_numeric38 r_numeric38_16 r_real r_double
---------- ---------- ------------ ----------------------- --------------------------------------- ---------------------------------------- ---------- ----------
44 NULL NULL NULL NULL -9999999999999999999999.9999999999999999 NULL NULL
45 NULL NULL NULL NULL 9999999999999999999999.9999999999999999 NULL NULL
46 NULL NULL NULL NULL 1.0000000000000000 NULL NULL
47 NULL NULL NULL NULL .9999999999999999 NULL NULL

CORYDORAS>


さて、次回は、real型とdouble precision型。

| | | コメント (0) | トラックバック (0)

2006年2月 5日 (日)

Mac De Oracle Heterogeneous! #28

つづきです。PostgreSQLの数値型をGeneric Connectivity経由でアクセス。

記事の内容とは関係ないけど、実はノベルティグッズ大好きなんです。

ということで昨日getしたノベルティ。しかも2個も!

CIMG8700



最近のOracle紅白まんじゅうなどに触発されてまた、コレクター魂が・・・・。Oracle Master Gold 9iASだったな〜〜昔は・・・今は自動的にSilverですが・・・取得記念の時計。と OOWで128ノードデモ成功記念テディベア3匹+Java TechDay記念のDuke。


CIMG8659CIMG8661

generic connectivity経由でpostgresqlのsmallint型に数値を設定してみた。PostgreSQL上で行った結果と同じである。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_smallint") values(32767);

1行が作成されました。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_smallint") values(-32768);

1行が作成されました。

CORYDORAS> commit;

コミットが完了しました。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_smallint") values(32768);
insert into num_test_postgresql749_mac@oracle10g_win("r_smallint") values(32768)
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC]ERROR: integer out of range (SQL State: S1000; SQL Code: 7)
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_smallint") values(-32769);
insert into num_test_postgresql749_mac@oracle10g_win("r_smallint") values(-32769)
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC]ERROR: integer out of range (SQL State: S1000; SQL Code: 7)
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。

CORYDORAS> list
1 select *
2 from
3 (
4 select
5 rownum as "rownum",
6 a.*
7 from
8 num_test_postgresql749_mac@oracle10g_win a
9 )
10 where
11* "rownum" > 31
CORYDORAS> /

rownum r_smallint r_integer r_bigint r_numeric38 r_numeric38_16 r_real r_double
---------- ---------- ------------ ----------------------- --------------------------------------- ---------------------------------------- ---------- ----------
32 32767 NULL NULL NULL NULL NULL NULL
33 -32768 NULL NULL NULL NULL NULL NULL

CORYDORAS>

integer型へのinsert文も PostgreSQL上で行った場合と変わらない。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_integer") values(-2147483648);

1行が作成されました。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_integer") values(2147483647);

1行が作成されました。

CORYDORAS> commit;

コミットが完了しました。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_integer") values(2147483649);
insert into num_test_postgresql749_mac@oracle10g_win("r_integer") values(2147483649)
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC]ERROR: integer out of range (SQL State: S1000; SQL Code: 7)
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_integer") values(2147483648);
insert into num_test_postgresql749_mac@oracle10g_win("r_integer") values(2147483648)
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC]ERROR: integer out of range (SQL State: S1000; SQL Code: 7)
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> rollback;
CORYDORAS> list
1 select *
2 from
3 (
4 select
5 rownum as "rownum",
6 a.*
7 from
8 num_test_postgresql749_mac@oracle10g_win a
9 )
10 where
11* "rownum" > 33
CORYDORAS> /

rownum r_smallint r_integer r_bigint r_numeric38 r_numeric38_16 r_real r_double
---------- ---------- ------------ ----------------------- --------------------------------------- ---------------------------------------- ---------- ----------
34 NULL -2147483648 NULL NULL NULL NULL NULL
35 NULL 2147483647 NULL NULL NULL NULL NULL

CORYDORAS>

bigint型も特に変わった癖は無い。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_bigint") values(-9223372036854775808);

1行が作成されました。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_bigint") values(9223372036854775807);

1行が作成されました。

CORYDORAS> commit;

コミットが完了しました。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_bigint") values(-9223372036854775809);
insert into num_test_postgresql749_mac@oracle10g_win("r_bigint") values(-9223372036854775809)
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC]ERROR: integer out of range (SQL State: S1000; SQL Code: 7)
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_bigint") values(9223372036854775808);
insert into num_test_postgresql749_mac@oracle10g_win("r_bigint") values(9223372036854775808)
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC]ERROR: integer out of range (SQL State: S1000; SQL Code: 7)
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> rollback;

ロールバックが完了しました。

CORYDORAS> select *
2 from
3 (
4 select
5 rownum as "rownum",
6 a.*
7 from
8 num_test_postgresql749_mac@oracle10g_win a
9 )
10 where
11 "rownum" > 35;

rownum r_smallint r_integer r_bigint r_numeric38 r_numeric38_16 r_real r_double
---------- ---------- ------------ ----------------------- --------------------------------------- ---------------------------------------- ---------- ----------
36 NULL NULL -9223372036854775808 NULL NULL NULL NULL
37 NULL NULL 9223372036854775807 NULL NULL NULL NULL

CORYDORAS>

次回、numeric型につづく。

| | | コメント (0) | トラックバック (0)

2006年2月 4日 (土)

Mac De Oracle Heterogeneous! #27

つづきです。PostgreSQLの数値型をGeneric Connectivity経由でアクセス。

PostgreSQL側で行ったことと同じ操作を行う。まず、0の設定とnullの設定。問題なし。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win
2 values(0,0,0,0,0,0,0);

1行が作成されました。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win
2 values(null,null,null,null,null,null,null);

1行が作成されました。

CORYDORAS> commit;

コミットが完了しました。

CORYDORAS> select * from num_test_postgresql749_mac@oracle10g_win;

r_smallint r_integer r_bigint r_numeric38 r_numeric38_16 r_real r_double
---------- ------------ ----------------------- --------------------------------------- ---------------------------------------- ---------- ----------
0 0 0 0 .0000000000000000 0 0
NULL NULL NULL NULL NULL NULL NULL
NULL NULL NULL NULL NULL 0 NULL
NULL NULL NULL NULL NULL NULL 0
32767 NULL NULL NULL NULL NULL NULL
-32768 NULL NULL NULL NULL NULL NULL
NULL -2147483648 NULL NULL NULL NULL NULL
NULL 2147483647 NULL NULL NULL NULL NULL
NULL NULL -9223372036854775808 NULL NULL NULL NULL
NULL NULL 9223372036854775807 NULL NULL NULL NULL
NULL NULL NULL -99999999999999999999999999999999999999 NULL NULL NULL
NULL NULL NULL 0 NULL NULL NULL
NULL NULL NULL -1 NULL NULL NULL
NULL NULL NULL 0 NULL NULL NULL
NULL NULL NULL 99999999999999999999999999999999999999 NULL NULL NULL
NULL NULL NULL NULL -9999999999999999999999.9999999999999999 NULL NULL
NULL NULL NULL NULL 9999999999999999999999.9999999999999999 NULL NULL
NULL NULL NULL NULL 1.0000000000000000 NULL NULL
NULL NULL NULL NULL .9999999999999999 NULL NULL
NULL NULL NULL NULL NULL 3.4000E+38 NULL
NULL NULL NULL NULL NULL -3.400E+38 NULL
NULL NULL NULL NULL NULL 1.2000E-38 NULL
NULL NULL NULL NULL NULL -1.200E-38 NULL
NULL NULL NULL NULL NULL NULL ˜
NULL NULL NULL NULL NULL NULL -˜
NULL NULL NULL NULL NULL NULL 0
NULL NULL NULL NULL NULL NULL 0
0 0 0 0 .0000000000000000 0 0
NULL NULL NULL NULL NULL NULL NULL

29行が選択されました。

CORYDORAS>


空文字の設定もエラーになり、変わった癖はない。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_smallint") values('');
insert into num_test_postgresql749_mac@oracle10g_win("r_smallint") values('')
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC]ERROR: invalid input syntax for integer: "" (SQL State: S1000; SQL Code: 7)
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_integer") values('');
insert into num_test_postgresql749_mac@oracle10g_win("r_integer") values('')
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC]ERROR: invalid input syntax for integer: "" (SQL State: S1000; SQL Code: 7)
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_bigint") values('');
insert into num_test_postgresql749_mac@oracle10g_win("r_bigint") values('')
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC]ERROR: invalid input syntax for type bigint: "" (SQL State: S1000; SQL Code: 7)
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38") values('');
insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38") values('')
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC]ERROR: invalid input syntax for type numeric: " " (SQL State: S1000; SQL Code: 7)
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38_16") values('');
insert into num_test_postgresql749_mac@oracle10g_win("r_numeric38_16") values('')
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC]ERROR: invalid input syntax for type numeric: " " (SQL State: S1000; SQL Code: 7)
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。


CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_real") values('');

1行が作成されました。

CORYDORAS> insert into num_test_postgresql749_mac@oracle10g_win("r_double") values('');

1行が作成されました。

CORYDORAS> commit;

コミットが完了しました。

CORYDORAS> select * from num_test_postgresql749_mac@oracle10g_win;

r_smallint r_integer r_bigint r_numeric38 r_numeric38_16 r_real r_double
---------- ------------ ----------------------- --------------------------------------- ---------------------------------------- ---------- ----------
0 0 0 0 .0000000000000000 0 0
NULL NULL NULL NULL NULL NULL NULL
NULL NULL NULL NULL NULL 0 NULL
NULL NULL NULL NULL NULL NULL 0
32767 NULL NULL NULL NULL NULL NULL
-32768 NULL NULL NULL NULL NULL NULL
NULL -2147483648 NULL NULL NULL NULL NULL
NULL 2147483647 NULL NULL NULL NULL NULL
NULL NULL -9223372036854775808 NULL NULL NULL NULL
NULL NULL 9223372036854775807 NULL NULL NULL NULL
NULL NULL NULL -99999999999999999999999999999999999999 NULL NULL NULL
NULL NULL NULL 0 NULL NULL NULL
NULL NULL NULL -1 NULL NULL NULL
NULL NULL NULL 0 NULL NULL NULL
NULL NULL NULL 99999999999999999999999999999999999999 NULL NULL NULL
NULL NULL NULL NULL -9999999999999999999999.9999999999999999 NULL NULL
NULL NULL NULL NULL 9999999999999999999999.9999999999999999 NULL NULL
NULL NULL NULL NULL 1.0000000000000000 NULL NULL
NULL NULL NULL NULL .9999999999999999 NULL NULL
NULL NULL NULL NULL NULL 3.4000E+38 NULL
NULL NULL NULL NULL NULL -3.400E+38 NULL
NULL NULL NULL NULL NULL 1.2000E-38 NULL
NULL NULL NULL NULL NULL -1.200E-38 NULL
NULL NULL NULL NULL NULL NULL ˜
NULL NULL NULL NULL NULL NULL -˜
NULL NULL NULL NULL NULL NULL 0
NULL NULL NULL NULL NULL NULL 0
0 0 0 0 .0000000000000000 0 0
NULL NULL NULL NULL NULL NULL NULL
NULL NULL NULL NULL NULL 0 NULL
NULL NULL NULL NULL NULL NULL 0

31行が選択されました。

CORYDORAS>

長いので次回につづく。

| | | コメント (0) | トラックバック (0)

2006年2月 3日 (金)

Mac De Oracle Heterogeneous! #26

前回は、PostgreSQL7.4.9上で数値型の癖を確認した。

今日はPostgreSQLの数値型をGeneric Connectivity経由でアクセスする。

Oracle10g R1 Windowsに num_test_postgresql749_macというシノニムを作成し、以下の経路で
gencon_blog_img02
アクセスしている。

CORYDORAS> select synonym_name from user_synonyms@oracle10g_win;

SYNONYM_NAME
------------------------------
NUM_TEST_POSTGRESQL749_MAC
DATE_TEST_MYSQL4026_WIN
DATE_TEST_MYSQL4113A_MAC_SV
DATE_TEST_POSTGRESQL749_MAC
EMP_MYSQL4025_MAC
INNO_EMP_MYSQL4025_MAC
EMP_MYSQL4026_WIN
EMP_MYSQL4113A_MAC_SV
EMP_POSTGRESQL749_MAC
ORACLE_EMP_MYSQL4026_WIN

10行が選択されました。

CORYDORAS>


登録済みデータを問い合わせてみる。 PostgreSQL7.4.9の double precision型で問題発生。

CORYDORAS> 

r_smallint r_integer r_bigint r_numeric38 r_numeric38_16 r_real r_double
---------- ------------ ----------------------- --------------------------------------- ---------------------------------------- ---------- ----------
0 0 0 0 .0000000000000000 0 0
NULL NULL NULL NULL NULL NULL NULL
NULL NULL NULL NULL NULL 0 NULL
NULL NULL NULL NULL NULL NULL 0
32767 NULL NULL NULL NULL NULL NULL
-32768 NULL NULL NULL NULL NULL NULL
NULL -2147483648 NULL NULL NULL NULL NULL
NULL 2147483647 NULL NULL NULL NULL NULL
NULL NULL -9223372036854775808 NULL NULL NULL NULL
NULL NULL 9223372036854775807 NULL NULL NULL NULL
NULL NULL NULL -99999999999999999999999999999999999999 NULL NULL NULL
NULL NULL NULL 0 NULL NULL NULL
NULL NULL NULL -1 NULL NULL NULL
NULL NULL NULL 0 NULL NULL NULL
NULL NULL NULL 99999999999999999999999999999999999999 NULL NULL NULL
NULL NULL NULL NULL -9999999999999999999999.9999999999999999 NULL NULL
NULL NULL NULL NULL 9999999999999999999999.9999999999999999 NULL NULL
NULL NULL NULL NULL 1.0000000000000000 NULL NULL
NULL NULL NULL NULL .9999999999999999 NULL NULL
NULL NULL NULL NULL NULL 3.4000E+38 NULL
NULL NULL NULL NULL NULL -3.400E+38 NULL
NULL NULL NULL NULL NULL 1.2000E-38 NULL
NULL NULL NULL NULL NULL -1.200E-38 NULL
NULL NULL NULL NULL NULL NULL ˜
NULL NULL NULL NULL NULL NULL -˜
NULL NULL NULL NULL NULL NULL 0
NULL NULL NULL NULL NULL NULL 0

27行が選択されました。

CORYDORAS>

dump()関数で Oracle側の型を確認してみると、double precision型も含めて、全て number型にマッピングされている。
Oracleのnumber型の精度を超えている箇所は TILDEが表示されている。number型の精度を超えていないことが事前に確認できるようならば、double precision型もマッピングできそうではあるが、直接取り込むようなことはしないほうが無難だと思われる。
指数表現でCSVファイルとして出力、それをOracle側で、BINARY_DOUBLE型マッピングした外部表にして取り込むという方法がよさそうに思える(尚、外部表にして取り込む方法は未確認)。

CORYDORAS> list
1 select
2 dump("r_smallint") as "smallint",
3 dump("r_integer") as "integer",
4 dump("r_bigint") as "bigint",
5 dump("r_numeric38") as "numeric38_0",
6 dump("r_numeric38_16") as "numeric38_16",
7 dump("r_real") as "real",
8 dump("r_double") as "double_precision"
9 from
10 num_test_postgresql749_mac@oracle10g_win
11 where
12* rownum = 1
CORYDORAS> /

smallint integer bigint numeric38_0 numeric38_16 real double_precision
-------------------- -------------------- -------------------- -------------------- -------------------- -------------------- --------------------
Typ=2 Len=1: 128 Typ=2 Len=1: 128 Typ=2 Len=1: 128 Typ=2 Len=1: 128 Typ=2 Len=1: 128 Typ=2 Len=1: 128 Typ=2 Len=1: 128

CORYDORAS>

長くなるので、一旦この辺で。

| | | コメント (0) | トラックバック (0)

2006年2月 2日 (木)

Mac De Oracle Heterogeneous! #25

前回までで日付、時間型の癖は把握できた。ここからは数値型について見ていく。まず初めに、PowerBook G4 1Ghz MacOSX Tiger 10.4.4 (アップデータしたので)に作成した PostgreSQL7.4.9から。

以下のような表をPostgreSQl7.4.9に作成した。

pb17:˜ postgres$ psql -U scott postgresql749
Password:
Welcome to psql 7.4.9, the PostgreSQL interactive terminal.

Type: ¥copyright for distribution terms
¥h for help with SQL commands
¥? for help on internal slash commands
¥g or terminate with semicolon to execute query
¥q to quit

postgresql749=>
postgresql749=> ¥d num_test
Table "scott.num_test"
Column | Type | Modifiers
----------------+------------------+-----------
r_smallint | smallint |
r_integer | integer |
r_bigint | bigint |
r_numeric38 | numeric(38,0) |
r_numeric38_16 | numeric(38,16) |
r_real | real |
r_double | double precision |

postgresql749=>

正常の登録できて当然なところから。

postgresql749=> insert into num_test values(0,0,0,0,0,0,0);
INSERT 25454 1
postgresql749=> commit;
COMMIT
postgresql749=> insert into num_test values(null,null,null,null,null,null,null);
INSERT 25455 1
postgresql749=> commit;
COMMIT

さて、空文字はどうか? real型とdouble precision型では空文字を受け入れる。それぞれ 0 が設定される。それ以外の数値型では空文字は許容されない。

postgresql749=> insert into num_test values('',null,null,null,null,null,null);
ERROR: invalid input syntax for integer: ""
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into num_test values(null,'',null,null,null,null,null);
ERROR: invalid input syntax for integer: ""
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into num_test values(null,null,'',null,null,null,null);
ERROR: invalid input syntax for type bigint: ""
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into num_test values(null,null,null,'',null,null,null);
ERROR: invalid input syntax for type numeric: ""
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into num_test values(null,null,null,null,'',null,null);
ERROR: invalid input syntax for type numeric: ""
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into num_test values(null,null,null,null,null,'',null);
INSERT 25456 1
postgresql749=> commit;
COMMIT
postgresql749=> insert into num_test values(null,null,null,null,null,null,'');
INSERT 25457 1
postgresql749=> commit;
COMMIT
postgresql749=> select * from num_test;
r_smallint | r_integer | r_bigint | r_numeric38 | r_numeric38_16 | r_real | r_double
------------+-----------+----------+-------------+--------------------+--------+----------
0 | 0 | 0 | 0 | 0.0000000000000000 | 0 | 0
| | | | | |
| | | | | 0 |
| | | | | | 0
(4 rows)

postgresql749=>

次はsmallint型。変わった癖は無い。

postgresql749=> insert into num_test(r_smallint) values(32767);
INSERT 25458 1
postgresql749=> insert into num_test(r_smallint) values(-32768);
INSERT 25459 1
postgresql749=> commit;
COMMIT
postgresql749=> insert into num_test(r_smallint) values(32768);
ERROR: integer out of range
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into num_test(r_smallint) values(-32769);
ERROR: integer out of range
postgresql749=> rollback;
ROLLBACK
postgresql749=>

integer型。

postgresql749=> insert into num_test(r_integer) values(-2147483648);
INSERT 25460 1
postgresql749=> commit;
COMMIT
postgresql749=> insert into num_test(r_integer) values(-2147483649);
ERROR: integer out of range
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into num_test(r_integer) values(2147483647);
INSERT 25461 1
postgresql749=> commit;
COMMIT
postgresql749=> insert into num_test(r_integer) values(2147483648);
ERROR: integer out of range
postgresql749=> rollback;
ROLLBACK
postgresql749=>


postgresql749=> insert into num_test(r_bigint) values(-9223372036854775808);
INSERT 25462 1
postgresql749=> commit;
COMMIT
postgresql749=> insert into num_test(r_bigint) values(-9223372036854775809);
ERROR: integer out of range
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into num_test(r_bigint) values(9223372036854775807);
INSERT 25463 1
postgresql749=> commit;
COMMIT
postgresql749=> insert into num_test(r_bigint) values(9223372036854775808);
ERROR: integer out of range
postgresql749=> rollback;
ROLLBACK
postgresql749=>

numeric型で 38,0 の精度。Oracleのnumber型のような使い勝手。

postgresql749=> insert into num_test(r_numeric38) values(-99999999999999999999999999999999999999);
INSERT 25464 1
postgresql749=> commit;
COMMIT
postgresql749=> insert into num_test(r_numeric38) values(-999999999999999999999999999999999999991);
ERROR: numeric field overflow
DETAIL: The absolute value is greater than or equal to 10^38 for field with precision 38, scale 0.
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into num_test(r_numeric38) values(-100000000000000000000000000000000000000);
ERROR: numeric field overflow
DETAIL: The absolute value is greater than or equal to 10^38 for field with precision 38, scale 0.
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into num_test(r_numeric38) values(-0.1);
INSERT 25465 1
postgresql749=> insert into num_test(r_numeric38) values(-0.5);
INSERT 25466 1
postgresql749=> insert into num_test(r_numeric38) values(-0.4);
INSERT 25467 1
postgresql749=> commit;
COMMIT
postgresql749=> select * from num_test;
r_smallint | r_integer | r_bigint | r_numeric38 | r_numeric38_16 | r_real | r_double
------------+-------------+----------------------+-----------------------------------------+--------------------+--------+----------
0 | 0 | 0 | 0 | 0.0000000000000000 | 0 | 0
| | | | | |
| | | | | 0 |
| | | | | | 0
32767 | | | | | |
-32768 | | | | | |
| -2147483648 | | | | |
| 2147483647 | | | | |
| | -9223372036854775808 | | | |
| | 9223372036854775807 | | | |
| | | -99999999999999999999999999999999999999 | | |
| | | 0 | | |
| | | -1 | | |
| | | 0 | | |
(14 rows)

精度を変えたnumeric型も変な癖はないようだ。

postgresql749=> insert into num_test(r_numeric38) values(99999999999999999999999999999999999999);
INSERT 25468 1
postgresql749=> commit;
COMMIT
postgresql749=> insert into num_test(r_numeric38) values(100000000000000000000000000000000000000);
ERROR: numeric field overflow
DETAIL: The absolute value is greater than or equal to 10^38 for field with precision 38, scale 0.
postgresql749=> rollback;
ROLLBACK
postgresql749=>
postgresql749=> insert into num_test(r_numeric38_16) values(-9999999999999999999999.9999999999999999);
INSERT 25476 1
postgresql749=> commit;
COMMIT
postgresql749=> insert into num_test(r_numeric38_16) values(-10000000000000000000000.9999999999999999);
ERROR: numeric field overflow
DETAIL: The absolute value is greater than or equal to 10^22 for field with precision 38, scale 16.
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into num_test(r_numeric38_16) values(9999999999999999999999.9999999999999999);
INSERT 25477 1
postgresql749=> commit;
COMMIT
postgresql749=> insert into num_test(r_numeric38_16) values(10000000000000000000000.9999999999999999);
ERROR: numeric field overflow
DETAIL: The absolute value is greater than or equal to 10^22 for field with precision 38, scale 16.
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into num_test(r_numeric38_16) values(-9999999999999999999999.99999999999999995);
ERROR: numeric field overflow
DETAIL: The absolute value is greater than or equal to 10^22 for field with precision 38, scale 16.
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into num_test(r_numeric38_16) values(9999999999999999999999.99999999999999995);
ERROR: numeric field overflow
DETAIL: The absolute value is greater than or equal to 10^22 for field with precision 38, scale 16.
postgresql749=> rollback
postgresql749-> rollback;
ERROR: syntax error at or near "rollback" at character 10
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into num_test (r_numeric38_16) values(0.99999999999999995);
INSERT 25478 1
postgresql749=> insert into num_test (r_numeric38_16) values(0.99999999999999994);
INSERT 25479 1
postgresql749=> commit;
COMMIT
postgresql749=> select * from num_test;
r_smallint | r_integer | r_bigint | r_numeric38 | r_numeric38_16 | r_real | r_double
------------+-------------+----------------------+-----------------------------------------+------------------------------------------+--------+----------
0 | 0 | 0 | 0 | 0.0000000000000000 | 0 | 0
| | | | | |
| | | | | 0 |
| | | | | | 0
32767 | | | | | |
-32768 | | | | | |
| -2147483648 | | | | |
| 2147483647 | | | | |
| | -9223372036854775808 | | | |
| | 9223372036854775807 | | | |
| | | -99999999999999999999999999999999999999 | | |
| | | 0 | | |
| | | -1 | | |
| | | 0 | | |
| | | 99999999999999999999999999999999999999 | | |
| | | | -9999999999999999999999.9999999999999999 | |
| | | | 9999999999999999999999.9999999999999999 | |
| | | | 1.0000000000000000 | |
| | | | 0.9999999999999999 | |
(19 rows)

postgresql749=>


次は、real型。

postgresql749=> 
postgresql749=> insert into num_test(r_real) values(3.4e38);
INSERT 25487 1
postgresql749=> insert into num_test(r_real) values(-3.4e38);
INSERT 25488 1
postgresql749=> commit;
COMMIT
postgresql749=> insert into num_test(r_real) values(1.2e-38);
INSERT 25489 1
postgresql749=> insert into num_test(r_real) values(-1.2e-38);
INSERT 25490 1
postgresql749=> commit;
COMMIT
postgresql749=> insert into num_test(r_real) values(3.4e39);
ERROR: type "real" value out of range: overflow
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into num_test(r_real) values(-3.4e39);
ERROR: type "real" value out of range: overflow
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into num_test(r_real) values(-3.5e38);
ERROR: type "real" value out of range: overflow
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into num_test(r_real) values(-3.41e38);
ERROR: type "real" value out of range: overflow
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into num_test(r_real) values(1.2e-39);
ERROR: type "real" value out of range: underflow
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into num_test(r_real) values(1.1e-38);
ERROR: type "real" value out of range: underflow
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into num_test(r_real) values(-1.1e-38);
ERROR: type "real" value out of range: underflow
postgresql749=> rollback;
ROLLBACK
postgresql749=> select * from num_test;
r_smallint | r_integer | r_bigint | r_numeric38 | r_numeric38_16 | r_real | r_double
------------+-------------+----------------------+-----------------------------------------+------------------------------------------+----------+----------
0 | 0 | 0 | 0 | 0.0000000000000000 | 0 | 0
| | | | | |
| | | | | 0 |
| | | | | | 0
32767 | | | | | |
-32768 | | | | | |
| -2147483648 | | | | |
| 2147483647 | | | | |
| | -9223372036854775808 | | | |
| | 9223372036854775807 | | | |
| | | -99999999999999999999999999999999999999 | | |
| | | 0 | | |
| | | -1 | | |
| | | 0 | | |
| | | 99999999999999999999999999999999999999 | | |
| | | | -9999999999999999999999.9999999999999999 | |
| | | | 9999999999999999999999.9999999999999999 | |
| | | | 1.0000000000000000 | |
| | | | 0.9999999999999999 | |
| | | | | 3.4e+38 |
| | | | | -3.4e+38 |
| | | | | 1.2e-38 |
| | | | | -1.2e-38 |
(23 rows)

postgresql749=>

最後に double precision型。

postgresql749=> insert into num_test(r_double) values(1.79e308);
INSERT 25495 1
postgresql749=> insert into num_test(r_double) values(-1.79e308);
INSERT 25496 1
postgresql749=> insert into num_test(r_double) values(2.3e-308);
INSERT 25497 1
postgresql749=> insert into num_test(r_double) values(-2.3e-308);
INSERT 25498 1
postgresql749=> commit;
COMMIT
postgresql749=> insert into num_test(r_double) values(1.80e308);
ERROR:"180000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000" is out of range for type double precision
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into num_test(r_double) values(-1.80e308);
ERROR:"-18000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000" is out of range for type double precision
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into num_test(r_double) values(1.79e309);
ERROR:"179000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000" is out of range for type double precision
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into num_test(r_double) values(-1.79e309);
ERROR:"-17900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000" is out of range for type double precision
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into num_test(r_double) values(2.2e-308);
ERROR: type "double precision" value out of range: underflow
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into num_test(r_double) values(-2.2e-308);
ERROR: type "double precision" value out of range: underflow
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into num_test(r_double) values(2.3e-309);
ERROR: type "double precision" value out of range: underflow
postgresql749=> rollback;
ROLLBACK
postgresql749=> insert into num_test(r_double) values(-2.3e-309);
ERROR: type "double precision" value out of range: underflow
postgresql749=> rollback;
ROLLBACK
postgresql749=> select * from num_test;
r_smallint | r_integer | r_bigint | r_numeric38 | r_numeric38_16 | r_real | r_double
------------+-------------+----------------------+-----------------------------------------+------------------------------------------+----------+------------
0 | 0 | 0 | 0 | 0.0000000000000000 | 0 | 0
| | | | | |
| | | | | 0 |
| | | | | | 0
32767 | | | | | |
-32768 | | | | | |
| -2147483648 | | | | |
| 2147483647 | | | | |
| | -9223372036854775808 | | | |
| | 9223372036854775807 | | | |
| | | -99999999999999999999999999999999999999 | | |
| | | 0 | | |
| | | -1 | | |
| | | 0 | | |
| | | 99999999999999999999999999999999999999 | | |
| | | | -9999999999999999999999.9999999999999999 | |
| | | | 9999999999999999999999.9999999999999999 | |
| | | | 1.0000000000000000 | |
| | | | 0.9999999999999999 | |
| | | | | 3.4e+38 |
| | | | | -3.4e+38 |
| | | | | 1.2e-38 |
| | | | | -1.2e-38 |
| | | | | | 1.79e+308
| | | | | | -1.79e+308
| | | | | | 2.3e-308
| | | | | | -2.3e-308
(27 rows)

postgresql749=>
postgresql749=> ¥q
pb17:˜ postgres$

日付型とは異なり変わった癖はなさそうな予感。次回はgeneric connectivity経由でOracleからアクセスしてみる。

| | | コメント (0) | トラックバック (0)

2006年1月31日 (火)

Mac De Oracle Heterogeneous! #24

引き続き、Generic Connectivity経由でアクセスした場合、Oracle側では日付、時刻型がどのようにどのように扱われるか確認する。

PostgreSQLの場合と同様に、現在時刻を指定するためにはPL/SQLからexecute immediate文を利用する必要がありそうだ。

CORYDORAS> list
1 insert into date_test_mysql4113a_mac_sv@oracle10g_win
2 values(
3 (select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual),
4 (select to_char(sysdate,'yyyy-mm-dd') from dual),
5 (select to_char(systimestamp, 'yyyy-mm-dd hh24:mi:ss.ff') from dual),
6 (select to_char(sysdate,'hh24:mi:ss') from dual),
7 (select to_char(sysdate,'yyyy') from dual)
8* )
CORYDORAS> /
insert into date_test_mysql4113a_mac_sv@oracle10g_win
*
行1でエラーが発生しました。:
ORA-02070: データベースMYSQL4113A_MAC_SVはこのコンテキストではsubqueriesをサポートしません。
ORA-02063: 先行のエラー・メッセージを参照してくださいline(ORACLE10G_WIN)。


CORYDORAS>
CORYDORAS> list
1 declare
2 v_datetime varchar2(19);
3 v_date varchar2(10);
4 v_timestamp varchar2(30);
5 v_time varchar2(8);
6 v_year varchar2(4);
7 begin
8 v_datetime := to_char(sysdate,'yyyy-mm-dd hh24:mi:ss');
9 v_date := to_char(sysdate, 'yyyy-mm-dd');
10 v_timestamp := to_char(systimestamp , 'yyyy-mm-dd hh24:mi:ss.ff');
11 v_time := to_char(sysdate, 'hh24:mi:ss');
12 v_year := to_char(sysdate, 'yyyy');
13 --
14 insert into date_test_mysql4113a_mac_sv@oracle10g_win
15 values(
16 v_datetime, v_date, v_timestamp, v_time, v_year
17 );
18 commit;
19* end;
CORYDORAS> /
insert into date_test_mysql4113a_mac_sv@oracle10g_win
*
行14でエラーが発生しました。:
ORA-06550: 行14、列3:
PL/SQL: ORA-00980: シノニム変換が無効です。
ORA-06550: 行14、列3:
PL/SQL: SQL Statement ignored


CORYDORAS>
CORYDORAS> list
1 declare
2 v_datetime_string varchar2(19);
3 v_date_string varchar2(10);
4 v_timestamp_string varchar2(30);
5 v_time_string varchar2(8);
6 v_year_string varchar2(4);
7 v_sql varchar2(1000);
8 begin
9 v_datetime_string := to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss');
10 v_date_string := to_char(sysdate, 'yyyy-mm-dd');
11 v_timestamp_string := to_char(systimestamp, 'yyyy-mm-dd hh24:mi:ss');
12 v_time_string := to_char(sysdate, 'hh24:mi:ss');
13 v_year_string := to_char(sysdate, 'yyyy');
14 v_sql :=
15 'insert into date_test_mysql4113a_mac_sv@oracle10g_win values('||
16 '''' || v_datetime_string ||
17 ''',''' || v_date_string ||
18 ''',''' || v_timestamp_string ||
19 ''',''' || v_time_string ||
20 ''',''' || v_year_string || ''')'
21 ;
22 execute immediate v_sql;
23 end;
24*
CORYDORAS> /

PL/SQLプロシージャが正常に完了しました。

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
2006/01/27 01:00:12
0000/00/00 00:00:00 0001/01/01 00:00:00 0
0000/00/00 00:00:00 0001/01/01 00:00:00 0
2006/01/10 00:30:12 2006/02/10 00:00:00 2006/03/04 13:50:12 0001/01/01 12:30:01 2005
2006/01/27 10:13:10
2006/01/27 10:33:34 2006/01/27 00:00:00 0000/00/00 00:00:00 0001/01/01 10:33:34 2006
2006/01/27 10:48:01 2006/01/27 00:00:00 2006/01/27 10:48:01 0001/01/01 10:48:01 2006

23行が選択されました。

CORYDORAS>

DBMS_HS_PASSTHROUGHパッケージが利用できれば、それを利用する手もあるかもしれないが、このように
gencon_blog_img1

特殊な構成ではどうなのだろうか・・・・。

それは別途調べることにして、単純な環境ならば以下のようにして利用できる。
以下は、Windows XP ProfessionalのOracle10g R1 EEから MacOSX Tiger ServerのMySQL4.1.13a対して、DBMS_HS_PASSTHROUGH.EXECUTE_IMMEDIATEプロシージャを利用してMySQL向けSQLをパススルーして実行した例。
尚、dbms_hs_passthroughパッケージは、仮想パッケージとの記載があった。dba_objectsビュ−を覗いても存在していないし、desc dbms_hs_passthrough としても存在しないので驚かないように。
このようにアクセスしている。
gencon_blog_img99

SQL> select * from "date_test"@mysql4113a_mac_sv;

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
2006/01/27 01:00:12
0000/00/00 00:00:00 0001/01/01 00:00:00 0
0000/00/00 00:00:00 0001/01/01 00:00:00 0
2006/01/10 00:30:12 2006/02/10 00:00:00 2006/03/04 13:50:12 0001/01/01 12:30:01 2005
2006/01/27 10:13:10
2006/01/27 10:33:34 2006/01/27 00:00:00 0000/00/00 00:00:00 0001/01/01 10:33:34 2006
2006/01/27 10:44:42 2006/01/27 00:00:00 0000/00/00 00:00:00 0001/01/01 10:44:42 2006
2006/01/27 10:48:01 2006/01/27 00:00:00 2006/01/27 10:48:01 0001/01/01 10:48:01 2006

24行が選択されました。

SQL> DECLARE
2 num_rows PLS_INTEGER;
3 BEGIN
4 num_rows := DBMS_HS_PASSTHROUGH.EXECUTE_IMMEDIATE@mysql4113a_mac_sv
5 (
6 'insert into date_test values(now(), now(), now(), now(), now())'
7 );
8 END;
9 /

PL/SQLプロシージャが正常に完了しました。

SQL> select * from "date_test"@mysql4113a_mac_sv;

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
2006/01/27 01:00:12
0000/00/00 00:00:00 0001/01/01 00:00:00 0
0000/00/00 00:00:00 0001/01/01 00:00:00 0
2006/01/10 00:30:12 2006/02/10 00:00:00 2006/03/04 13:50:12 0001/01/01 12:30:01 2005
2006/01/27 10:13:10
2006/01/27 10:33:34 2006/01/27 00:00:00 0000/00/00 00:00:00 0001/01/01 10:33:34 2006
2006/01/27 10:44:42 2006/01/27 00:00:00 0000/00/00 00:00:00 0001/01/01 10:44:42 2006
2006/01/27 10:48:01 2006/01/27 00:00:00 2006/01/27 10:48:01 0001/01/01 10:48:01 2006
2006/01/28 14:55:38 2006/01/28 00:00:00 2006/01/28 14:55:38 0001/01/01 14:55:38 2006

25行が選択されました。

SQL> commit;

コミットが完了しました。

SQL>

=======================
結構苦戦しそうだが、MySQLの日付型、時刻型を利用する際の注意点をまとめておくと、

利用しているMyODBC Driverは、ここを参照してもらいたい

MySQLOracle
datetime型date型
date型
timestamp型
time型
year型number型
・検索時には、date型ではなく文字列で検索する。 ・MySQL側の型がtimestamp型である場合には、0000年00月00日かをCASE式かDECODE関数を利用してNULLにする必要がる。 ・MySQL側の型がyear型の場合、0ならば、NULLにしておいたほうがよいだろう。 ・逆にOracleからMySQL側に登録する際には、日付や時間の書式チェックを厳重に行うようにしたほうがよい。そうでないと0000年0月0日が設定されてしまう可能性もある。 ・現在日付や時刻を設定する場合には、PL/SQLからexecute immediate文を利用する必要がありそう。
gencon_blog_img1
(このような特殊な構成の場合だけだと思うが。。)  通常の構成ならば、dbms_hs_passthroughパッケージを利用するのもよいだろう。


やっと日付、時間型の確認が終わり、次回は、数値型(多分整数だけ)について、MySQL側の癖から確認してみようと思う。

| | | コメント (0) | トラックバック (0)

2006年1月30日 (月)

Mac De Oracle Heterogeneous! #23

引き続き、Generic Connectivity経由でアクセスした場合、Oracle側では日付、時刻型がどのようにどのように扱われるか確認する。

Oracle側の関数や、逆にMySQL側の関数を利用した場合には、PostgreSQLの場合と同様にエラーとなる。

CORYDORAS> insert into date_test_mysql4113a_mac_sv@oracle10g_win values(sysdate,null,null,null,null);
insert into date_test_mysql4113a_mac_sv@oracle10g_win values(sysdate,null,null,null,null)
*
行1でエラーが発生しました。:
ORA-02070: データベースMYSQL4113A_MAC_SVはこのコンテキストではspecial functionsをサポートしません。
ORA-02063: 先行のエラー・メッセージを参照してくださいline(ORACLE10G_WIN)。


CORYDORAS> insert into date_test_mysql4113a_mac_sv@oracle10g_win values(now(),null,null,null,null);
insert into date_test_mysql4113a_mac_sv@oracle10g_win values(now(),null,null,null,null)
*
行1でエラーが発生しました。:
ORA-00904: "NOW": 無効な識別子です。


CORYDORAS> insert into date_test_mysql4113a_mac_sv@oracle10g_win values(to_char(sysdate,'yyyymmddhh24miss'),null,null,null,null);
insert into date_test_mysql4113a_mac_sv@oracle10g_win values(to_char(sysdate,'yyyymmddhh24miss'),null,null,null,null)
*
行1でエラーが発生しました。:
ORA-02070: データベースMYSQL4113A_MAC_SVはこのコンテキストではTO_CHARをサポートしません。
ORA-02063: 先行のエラー・メッセージを参照してくださいline(ORACLE10G_WIN)。


CORYDORAS> insert into date_test_mysql4113a_mac_sv@oracle10g_win values(to_date('20061212235534','yyyymmddhh24miss'),null,null,null,null);
insert into date_test_mysql4113a_mac_sv@oracle10g_win values(to_date('20061212235534','yyyymmddhh24miss'),null,null,null,null)
*
行1でエラーが発生しました。:
ORA-02070: データベースMYSQL4113A_MAC_SVはこのコンテキストではTO_DATEをサポートしません。
ORA-02063: 先行のエラー・メッセージを参照してくださいline(ORACLE10G_WIN)。


CORYDORAS>

以下のようなリテラル指定ではうまく登録できるようだ。

CORYDORAS> insert into date_test_mysql4113a_mac_sv@oracle10g_win values('2006-01-10 00:30:12','2006-02-10','2006-03-04 13:50:12','12:30:01',2005);

1行が作成されました。

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
2006/01/27 01:00:12
0000/00/00 00:00:00 0001/01/01 00:00:00 0
0000/00/00 00:00:00 0001/01/01 00:00:00 0
2006/01/10 00:30:12 2006/02/10 00:00:00 2006/03/04 13:50:12 0001/01/01 12:30:01 2005

20行が選択されました。

CORYDORAS> commit;

コミットが完了しました。

CORYDORAS>

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 |
| 2006-01-10 00:30:12 | 2006-02-10 | 2006-03-04 13:50:12 | 12:30:01 | 2005 |
+---------------------+------------+---------------------+----------+--------+
20 rows in set (0.00 sec)

mysql>

13月とか40日とか、44時、65分、76秒などもOracle側でエラーにならずに登録できる。但し、MySQL側では0000年00月00日という日付になってしまう。Oracle側で日付を問い合わせるとNULLになる(MyODBCドライバの仕様通り)。

CORYDORAS> insert into date_test_mysql4113a_mac_sv@oracle10g_win values('2006-13-40 44:65:76',null,null,null,null);

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 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
2006/01/27 01:00:12
0000/00/00 00:00:00 0001/01/01 00:00:00 0
0000/00/00 00:00:00 0001/01/01 00:00:00 0
2006/01/10 00:30:12 2006/02/10 00:00:00 2006/03/04 13:50:12 0001/01/01 12:30:01 2005
2006/01/27 10:13:10

21行が選択されました。

CORYDORAS>


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 |
| 2006-01-10 00:30:12 | 2006-02-10 | 2006-03-04 13:50:12 | 12:30:01 | 2005 |
| 0000-00-00 00:00:00 | NULL | 2006-01-27 10:13:10 | NULL | NULL |
+---------------------+------------+---------------------+----------+--------+
21 rows in set (0.00 sec)

mysql>

長いので、また、次回につづく。

| | | コメント (0) | トラックバック (0)

2006年1月29日 (日)

Mac De Oracle Heterogeneous! #22

つづきです。前回は、MySQL側で日付、時刻型がどのように登録され、どのような癖があるのかを確認した。

今回は、Generic Connectivity経由でアクセスした場合、Oracle側ではMySQLの日付、時刻型がどのようにどのように扱われるか確認する。

以下のような経路でアクセスしている。


gencon_blog_img01

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) | トラックバック (0)

2006年1月24日 (火)

Mac De Oracle Heterogeneous! #21

つづきです。

今日は、MySQLの日付、時刻型について、Oracleとの違いを見ていく。

最初は、すべて 0 を設定してみる。
なんと正常に登録できてしまう。
しかもOracleやMySQLでも設定できなかった 0月 0日やOracleではエラーになってしまう 0000年が設定できるのである。generic connectivityでは問題になるかもしれないので注意しておく必要がある。

mysql> insert into date_test values(0,0,0,0,0);
Query OK, 1 row affected (0.09 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

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 |
+---------------------+------------+---------------------+----------+--------+
7 rows in set (0.00 sec)


nullableなのでNULLを設定しても問題ない。ただし、timestamp型はnullにならず必ずタイムスタンプが設定される。この辺りはOracleでも問題なることはないだろう。

mysql> insert into date_test values(null,null,null,null,null);
Query OK, 1 row affected (0.09 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

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 |
+---------------------+------------+---------------------+----------+--------+
8 rows in set (0.00 sec)

mysql>


現在時刻、日付の設定も特に問題になるようなことはなさそうに感じる。ただ warningが出ているが、気にせずcommitすると登録できてしまうので、プログラムミスでwarningを拾わず、rollbackしなかったらおかしな日付が登録される危険性がある。
ちなみに、MySQL4.1.13aでは 1 warningとでているが、MySQL4.0.26-ntでは warining表示すら表示されていなかった。

mysql> insert into date_test values(now(), now(), now(), now(), now());
Query OK, 1 row affected, 1 warning (0.09 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

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 |
+---------------------+------------+---------------------+----------+--------+
9 rows in set (0.00 sec)

mysql>

さて、お次は問題。MySQLでは、PostgreSQLでも設定できなかった空文字が warningはでるがコミットはできてしまう。前述したがwarningを拾わずにcommitしてしまうようなプログラムがあれば日付としておかしな値が設定されてしまう危険性がある。

mysql> insert into date_test values('','','','','');
Query OK, 1 row affected, 5 warnings (0.07 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

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 |
+---------------------+------------+---------------------+----------+--------+
10 rows in set (0.00 sec)

mysql>

さすがに、13月や35日、26時間、 70分、70秒などは warningとして警告がでるが、やはり commitが行える。内容を見てみると、0000年0月0日 0時0分0秒となる。注意しなければ。。。

mysql> insert into date_test values('2006-13-35 26:70:70',null,null,null,null);
Query OK, 1 row affected, 1 warning (0.06 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

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 |
+---------------------+------------+---------------------+----------+--------+
11 rows in set (0.00 sec)

mysql> insert into date_test values('99999999',null,null,null,null);
Query OK, 1 row affected, 1 warning (0.04 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

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 |
+---------------------+------------+---------------------+----------+--------+
12 rows in set (0.00 sec)

mysql>

これもあぶない。0月、0日がワーニングもなく登録できるのである。

mysql> insert into date_test values('2006-00-00 00:00:00',null,null,null,null);
Query OK, 1 row affected (0.06 sec)

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 |
+---------------------+------------+---------------------+----------+--------+
13 rows in set (0.00 sec)

mysql>

ざっと確認してみたところ、ポイントは

0000年
0月
0日

それぞれを許容してしまうあたりだろうか。。


次回は、Generic Connectivityを経由してMySQLにアクセスしてみる。Oracle側ではどの型にマッピングされ、どのような癖があるのかを確認する。

| | | コメント (0) | トラックバック (0)

2006年1月23日 (月)

Mac De Oracle Heterogeneous! #20

前回は、PostgreSQL上で日付や時間型がどのように扱われるか確認してみた。今日はGenneric Connectivity経由でPostgreSQLに日付や時間を登録してみる。

いつものように、date型とtimestamp型の書式を設定しておく

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';

セッションが変更されました。

Oracle10g R1 (MacOSX Server : PowerMac G5) --> oracle10g_win(データベースリンク) --> Oracle10g R1 (Windows XP Professional)のdate_test_postgresql749_mac(シノニム)--> generic connectivity agent --> MyODBCドライバ --> PostgreSQL7.4.9 の date_test表(MacOSX : PowerBook G4)という経路で問い合わせている。

PostgreSQL7.4.9の date型、time型、timestamp型すべてが、Oracleのdate型にマップされているため以下のような点に注意。

PostgreSQLのtime型は時間だけだが、Oracle側ではdate型になるため、0001/01/01+時間となる。
PostgreSQLのdate型は日付だけだが、Oracle型ではdate型なので 時間が00:00:00になる。
PostgreSQLのtimestamp型は、Oracleのdate型にマップされてしまうため、秒の少数部が欠落する。

ということになる。
以下は、generic connectivity経由でOracleから問い合わせた結果である。dump()関数を利用してデータタイプも確認してある。

CORYDORAS> select * from date_test_postgresql749_mac@oracle10g_win;

r_date r_timestamp r_time
------------------- ------------------- -------------------
1900/01/01 00:00:00
2006/01/20 00:00:00
1981/01/01 00:00:00
1990/12/01 00:00:00
0001/01/01 00:00:00
2007/03/07 00:00:00
0001/01/01 00:00:00
2007/09/11 00:00:00
2006/01/01 00:00:00
0001/01/01 23:59:59
2006/01/02 00:00:00
2006/01/02 03:01:00
2006/01/22 00:00:00 2006/01/22 21:57:25 0001/01/01 21:57:25
2008/11/07 04:50:03

14行が選択されました。

CORYDORAS>
CORYDORAS> list
1 select
2 dump("r_date") as r_date,
3 dump("r_timestamp") as r_timestamp,
4 dump("r_time") as r_time
5 from
6* date_test_postgresql749_mac@oracle10g_win
CORYDORAS> /

R_DATE R_TIMESTAMP R_TIME
---------------------------------------- ---------------------------------------- ----------------------------------------
Typ=12 Len=7: 119,100,1,1,1,1,1 NULL NULL
Typ=12 Len=7: 120,106,1,20,1,1,1 NULL NULL
NULL Typ=12 Len=7: 119,181,1,1,1,1,1 NULL
NULL Typ=12 Len=7: 119,190,12,1,1,1,1 NULL
Typ=12 Len=7: 100,101,1,1,1,1,1 NULL NULL
Typ=12 Len=7: 120,107,3,7,1,1,1 NULL NULL
NULL Typ=12 Len=7: 100,101,1,1,1,1,1 NULL
NULL Typ=12 Len=7: 120,107,9,11,1,1,1 NULL
NULL Typ=12 Len=7: 120,106,1,1,1,1,1 NULL
NULL NULL Typ=12 Len=7: 100,101,1,1,24,60,60
NULL Typ=12 Len=7: 120,106,1,2,1,1,1 NULL
NULL Typ=12 Len=7: 120,106,1,2,4,2,1 NULL
Typ=12 Len=7: 120,106,1,22,1,1,1 Typ=12 Len=7: 120,106,1,22,22,58,26 Typ=12 Len=7: 100,101,1,1,22,58,26
NULL Typ=12 Len=7: 120,108,11,7,5,51,4 NULL

14行が選択されました。

CORYDORAS>

次に、日付、時間型データを登録してみた。
パススルーされているのだろうか、to_date()関数は利用できない。(HS_CALL_NAME初期化パラメータでPostgreSQLのto_date関数が利用できるかは未確認。)

CORYDORAS> insert into date_test_postgresql749_mac@oracle10g_win
2 values(to_date('00000000','yyyymmdd'),null,null);
insert into date_test_postgresql749_mac@oracle10g_win
*
行1でエラーが発生しました。:
ORA-02070: データベースPOSTGRESQL749_MACはこのコンテキストではTO_DATEをサポートしません。
ORA-02063: 先行のエラー・メッセージを参照してくださいline(ORACLE10G_WIN)。

PostgreSQL上でもエラーになったINSERT文を実行してみると、これはPostgreSQLまで届いているようだ。PostgreSQL上で実行した時と同じエラーが返ってくる。

CORYDORAS> insert into date_test_postgresql749_mac@oracle10g_win
2 values('00000000',null,null);
insert into date_test_postgresql749_mac@oracle10g_win
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC]ERROR: date/time field value out of range: "00000000" (SQL State: S1000; SQL Code: 7)
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。

Oracleのsysdate,systimestampを利用してみる。これは予想通りエラーとなる。

CORYDORAS> 
CORYDORAS> insert into date_test_postgresql749_mac@oracle10g_win
2 values(sysdate,systimestamp,sysdate);
insert into date_test_postgresql749_mac@oracle10g_win
*
行1でエラーが発生しました。:
ORA-02070: データベースPOSTGRESQL749_MACはこのコンテキストではspecial functionsをサポートしません。
ORA-02063: 先行のエラー・メッセージを参照してくださいline(ORACLE10G_WIN)。

to_char()関数を利用してみたが、これはto_date()関数と同じで利用できない。

CORYDORAS> insert into date_test_postgresql749_mac@oracle10g_win
2 values(to_char(sysdate,'yyyymmdd'), to_char(systimestamp,'yyyymmddhh24miss.ff'), to_char(sysdate,'hh24miss'));
insert into date_test_postgresql749_mac@oracle10g_win
*
行1でエラーが発生しました。:
ORA-02070: データベースPOSTGRESQL749_MACはこのコンテキストではTO_CHARをサポートしません。
ORA-02063: 先行のエラー・メッセージを参照してくださいline(ORACLE10G_WIN)。

では、暗黙型変換に任せて、単純に日付や時間を文字列指定した場合はどうか? 
やっと、登録できた。(よかった、よかった。と安心ばかりはしていられない。。。)


CORYDORAS> insert into date_test_postgresql749_mac@oracle10g_win
2  values('20061231','20060101 125959','235959');

1行が作成されました。

CORYDORAS> select * from date_test_postgresql749_mac@oracle10g_win;

r_date r_timestamp r_time
---------------------------------------- ---------------------------------------- ----------------------------------------
1900/01/01 00:00:00
2006/01/20 00:00:00
1981/01/01 00:00:00
1990/12/01 00:00:00
0001/01/01 00:00:00
2007/03/07 00:00:00
0001/01/01 00:00:00
2007/09/11 00:00:00
2006/01/01 00:00:00
0001/01/01 23:59:59
2006/01/02 00:00:00
2006/01/02 03:01:00
2006/01/22 00:00:00 2006/01/22 21:57:25 0001/01/01 21:57:25
2008/11/07 04:50:03
2006/12/31 00:00:00 2006/01/01 12:59:59 0001/01/01 23:59:59

15行が選択されました。

各列はnullableなのでNULLを設定することも問題ない。

CORYDORAS> 
CORYDORAS> insert into date_test_postgresql749_mac@oracle10g_win
2 values(null,null,null);

1行が作成されました。

Oracleでは、今のところ、空文字=NULLなのでNULLが登録されると予想していたがDML文がパススルーされているようで、PostgreSQL上で実行した場合と同様の結果(エラー)になる。(尚、本来は、空文字とNULLは別もの。オラクルのマニュアルにも記載があり空文字=NULLという扱いにはなっているが将来は変わる可能性があるというようなニュアンスのコメントが記載されている)

CORYDORAS> insert into date_test_postgresql749_mac@oracle10g_win
2 values('',null,null);
insert into date_test_postgresql749_mac@oracle10g_win
*
行1でエラーが発生しました。:
ORA-28500: OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Generic Connectivity Using ODBC]ERROR: invalid input syntax for type date: "" (SQL State: S1000; SQL Code: 7)
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(POSTGRESQL749_MAC)。
ORA-02063: 先行のエラー・メッセージを参照してください3 lines(ORACLE10G_WIN)。

しかし、リテラルでしか登録できないとなると、現在時間や日付を設定したい場合には非常に都合が悪い。スカラー副問合せを利用してみたがこれもエラーとなった。これは困った。

CORYDORAS> 
CORYDORAS> list
1 insert into date_test_postgresql749_mac@oracle10g_win
2 values(
3 (select to_char(sysdate,'yyyymmdd') from dual),
4 (select to_char(systimestamp,'yyyymmdd hh24miss.ff') from dual),
5 (select to_char(sysdate,'hh24miss') from dual)
6* )
CORYDORAS> /
insert into date_test_postgresql749_mac@oracle10g_win
*
行1でエラーが発生しました。:
ORA-02070: データベースPOSTGRESQL749_MACはこのコンテキストではsubqueriesをサポートしません。
ORA-02063: 先行のエラー・メッセージを参照してくださいline(ORACLE10G_WIN)。

PL/SQLからなら、なんとかなるかとも知れないと以下のようにしてみたが、今度はシノニム変換で問題が発生した。

CORYDORAS> 
CORYDORAS> declare
2 v_datetime_string varchar2(25);
3 v_date_string varchar2(8);
4 v_time_string varchar2(6);
5 begin
6 v_date_string := to_char(sysdate,'yyyymmdd');
7 v_datetime_string := to_char(systimestamp, 'yyyymmdd hh24miss.ff');
8 v_time_string := to_char(sysdate,'hh24miss');
9 --
10 insert into date_test_postgresql749_mac@oracle10g_win
11 values(v_date_string, v_datetime_string, v_time_string);
12 commit;
13 end;
14 /
insert into date_test_postgresql749_mac@oracle10g_win
*
行10でエラーが発生しました。:
ORA-06550: 行10、列3:
PL/SQL: ORA-00980: シノニム変換が無効です。
ORA-06550: 行10、列3:
PL/SQL: SQL Statement ignored

CORYDORAS>

WindowsのOracle10g R1を踏み台にしている関係なのか、無理矢理構築したOracle10g R1 for MacOSX Serverだからなのか確かなことは言えないが、以下のような流れではシノニムの解決ができないようである。

もちろん、Oracle10g for MacOSX Serverで Oracle Heterogeneous ServiceのGeneric connectivityが正式にサポートされればこのような構成

gencon_blog_img1

にする必要はない。。。。趣味というか興味だけでやっていることなので、こんな”おもしろい”(変わっているとも言う)構成してあるのでご注意を。

ちなみにMacOSX Serverの先にあるOracle10g R1 for Windowsからだと上記PL/SQLブロックで実行可能であった。やはり踏み台方式もしくは無理矢理構築したOracle10g for MacOSX Server側の問題のような気がする。。

SQL> declare
2 v_datetime_string varchar2(25);
3 v_date_string varchar2(8);
4 v_time_string varchar2(6);
5 begin
6 v_date_string := to_char(sysdate,'yyyymmdd');
7 v_datetime_string := to_char(systimestamp, 'yyyymmdd hh24miss.ff');
8 v_time_string := to_char(sysdate,'hh24miss');
9 --
10 insert into date_test_postgresql749_mac
11 values(v_date_string, v_datetime_string, v_time_string);
12 commit;
13 end;
14 /

PL/SQLプロシージャが正常に完了しました。

そして最後の悪あがき! 
insert文をexecute immediate文で実行してみた。おお〜〜っ!、Oracle10g for MacOSX ServerからPL/SQLブロックが実行できた瞬間だった。(爆!)

CORYDORAS> list
1 declare
2 v_timestamp_string varchar2(25);
3 v_date_string varchar2(8);
4 v_time_string varchar2(6);
5 v_sql varchar2(1000);
6 begin
7 v_date_string := to_char(sysdate,'yyyymmdd');
8 v_timestamp_string := to_char(systimestamp,'yyyymmdd hh24miss.ff');
9 v_time_string := to_char(sysdate,'hh24miss');
10 v_sql :=
11 'insert into date_test_postgresql749_mac@oracle10g_win values('||
12 '''' || v_date_string ||
13 ''',''' || v_timestamp_string ||
14 ''',''' || v_time_string || ''')'
15 ;
16 execute immediate v_sql;
17 commit;
18* end;
CORYDORAS> /

PL/SQLプロシージャが正常に完了しました。

CORYDORAS> select * from date_test_postgresql749_mac@oracle10g_win;

r_date r_timestamp r_time
------------------- ------------------- -------------------
1900/01/01 00:00:00
2006/01/20 00:00:00
1981/01/01 00:00:00
1990/12/01 00:00:00
0001/01/01 00:00:00
2007/03/07 00:00:00
0001/01/01 00:00:00
2007/09/11 00:00:00
2006/01/01 00:00:00
0001/01/01 23:59:59
2006/01/02 00:00:00
2006/01/02 03:01:00
2006/01/22 00:00:00 2006/01/22 21:57:25 0001/01/01 21:57:25
2008/11/07 04:50:03
2006/12/12 00:00:00
2006/12/12 12:01:01
0001/01/01 23:59:59
2006/01/23 00:00:00 2006/01/23 23:38:56 0001/01/01 23:38:56
2006/01/23 00:00:00 2006/01/23 23:50:34 0001/01/01 23:50:34

19行が選択されました。

CORYDORAS>


今日はここまで。

======
Generic Connectivity
日付、時間型のまとめ(PostgresSQL7.4.9編)

参照時のポイント
・PostgreSQL7.4.9の date型、time型、timestamp型すべてが、Oracleのdate型にマップされる。
・PostgreSQLのtime型は時間だけだが、Oracle側ではdate型になるため、0001/01/01+時間となる。
・PostgreSQLのdate型は日付だけだが、Oracle型ではdate型なので 時間が00:00:00になる。
・PostgreSQLのtimestamp型は、Oracleのdate型にマップされてしまうため、秒の少数部が欠落する。

検索時のポイント
・to_date()を利用してdate型で検索することも、日付、時間を文字列として検索することも可能(Oracleの動きに類似している)

登録時のポイント
・日付、時間を文字列(リテラル)として指定ことしかできない。
・現在時間や、日付を設定する場合は、PL/SQLからINSERT文や、UPDATE文を実行する。
 (但し、このテストで利用しているような特殊構成ではPL/SQLから実行するDMLは、execute immediate文を利用したダイナミックSQLにしたほうがよいかも。この環境では、たまたま動作しただけかもしれないのでご注意を。)

次回はMySQLで同様の確認を行う予定。

| | | コメント (0) | トラックバック (0)

2006年1月22日 (日)

Mac De Oracle Heterogeneous! #19

続きです。

日付、時間型がOracle側にはどのようにマッピングされるのか、どのような注意点があるのか検証してみる。

今日はPostgreSQL7.4.9の日付型、時間型について確認してみることにする

まず、PostgreSQL7.4.9のdate型、timestamp型、time型が、Oracleのdate型やtimestamp型とどのような違いがあるのかPostgreSQL上で確認してみることにする。

Oracleだとdate型とtimestamp型だけでなのでdate型が年月日だけ、time型が時間だけを格納するという点は覚えておくと良さそう。
timestamp型はOracleのtimestamp型と同じようなので特に注意する点はなさそうである。

重要なのは、Oracleのdate型やtimestamp型は日付や時間の妥当性チェックが厳しいというか、しっかりしているので日付として妥当でない文字列を受け入れることはないのだが、PostgreSQL7.4.9では、それを”調整して”受け入れてしまう点である。PostgreSQLに慣れている方なら驚くことではないと思うが、Oracleには慣れているが、PostgreSQLは初心者ということになると、かなり戸惑うことになる。(前回利用したdate_test表にtime型の列を追加した表を利用した。)

Last login: Fri Jan 20 22:41:46 on ttyp1
Welcome to Darwin!
pb17:˜ stargrass$ su - postgres
Password:
pb17:˜ postgres$ postmaster -S
pb17:˜ postgres$
pb17:˜ postgres$ psql -U scott postgresql749
Password:
Welcome to psql 7.4.9, the PostgreSQL interactive terminal.

Type: ¥copyright for distribution terms
¥h for help with SQL commands
¥? for help on internal slash commands
¥g or terminate with semicolon to execute query
¥q to quit

postgresql749=> alter table date_test add column r_time time;
ALTER TABLE
postgresql749=> commit;
COMMIT
postgresql749=> ¥d date_test;
Table "scott.date_test"
Column | Type | Modifiers
-------------+-----------------------------+-----------
r_date | date |
r_timestamp | timestamp without time zone |
r_time | time without time zone |

postgresql749=> select * from date_test;
r_date | r_timestamp | r_time
------------+---------------------+--------
1900-01-01 | |
2006-01-20 | |
| 1981-01-01 00:00:00 |
| 1990-12-01 00:00:00 |
(4 rows)

※Oracleならエラーになる。
postgresql749=> insert into date_test values(to_date('00000000','yyyymmdd'),null,null);
INSERT 25433 1

※Oracleならエラーになる。
postgresql749=> insert into date_test values(to_date('20061435','yyyymmdd'),null,null);
INSERT 25434 1

※Oracleならエラーになる。
postgresql749=> insert into date_test values(null,to_date('00000000','yyyymmdd'),null);
INSERT 25435 1

※Oracleならエラーになる。
postgresql749=> insert into date_test values(null,to_date('20062040','yyyymmdd'),null);
INSERT 25436 1

※Oracleならエラーになる。
postgresql749=> insert into date_test values(null,to_date('20060101479999','yyyymmddhh24miss'),null);
INSERT 25437 1

postgresql749=> insert into date_test values(null,null,'235959');
INSERT 25438 1

※Oracleならエラーになる。
postgresql749=> insert into date_test values(null,'2006-01-01 240000',null);
INSERT 25439 1

※Oracleならエラーになる。
postgresql749=> insert into date_test values(null,'2006-01-01 266060',null);
INSERT 25440 1


postgresql749=> insert into date_test values(current_date, current_timestamp, current_time);
INSERT 25441 1

※Oracleならエラーになる。
postgresql749=> insert into date_test values(null,to_timestamp('20063433284963','yyyymmddhh24miss'),null);
INSERT 25442 1
postgresql749=> commit;
COMMIT
postgresql749=> select * from date_test;
r_date | r_timestamp | r_time
---------------+----------------------------+-----------------
1900-01-01 | |
2006-01-20 | |
| 1981-01-01 00:00:00 |
| 1990-12-01 00:00:00 |
0001-01-01 BC | |
2007-03-07 | |
| 0001-01-01 00:00:00 BC |
| 2007-09-11 00:00:00 |
| 2006-01-01 00:00:00 |
| | 23:59:59
| 2006-01-02 00:00:00 |
| 2006-01-02 03:01:00 |
2006-01-22 | 2006-01-22 21:57:25.372923 | 21:57:25.372923
| 2008-11-07 04:50:03 |
(14 rows)

postgresql749=>
postgresql749=>

※空文字は指定できないようだ。(Oracleでは、空文字もNULLとして扱っているので Genneric Connectivity経由だとエラーにはならないかもしれない)
postgresql749=> insert into date_test values('',null,null);
ERROR: invalid input syntax for type date: ""
postgresql749=> rollback;
ROLLBACK

見ての通り、Oracleではエラーになるケースが含まれているのだがPostgreSQLではすべて正常に登録できてしまう。(しかも日付は調整された形で登録されてしまう。)
Oracleに慣れていると日付や時間に設定する文字列が日付や時間として妥当であるか厳密にチェックされているという事に慣れすぎているのでかなり驚く。
14月とか20月、63秒なんて存在しないからエラーにするという考え方のOracleと、14月と指定すれば1年と2ヶ月として”勝手に”日付を調整してくれるPostgreSQL、戸惑わないほうがおかしい。


上記は、to_date()や、to_timestamp()という関数の動きなのだが、以下のようにto_date()やto_timestamp()関数を利用しないで暗黙型変換?を利用すると挙動が異なるのでさらに戸惑う。
文字列のままで暗黙型変換だと、ちゃんと文字列が日付や時間として妥当な文字列かチェックしてくれるのである。いや〜結構ハマりそうだ。

postgresql749=> insert into date_test values('00000000',null,null);
ERROR: date/time field value out of range: "00000000"
HINT: Perhaps you need a different "datestyle" setting.
postgresql749=> insert into date_test values('20060101',null,null);
ERROR: current transaction is aborted, commands ignored until end of transaction block
postgresql749=> rollback;
ROLLBACK

postgresql749=> insert into date_test values('20060101',null,null);
INSERT 25443 1

postgresql749=> insert into date_test values('20061349',null,null);
ERROR: date/time field value out of range: "20061349"
HINT: Perhaps you need a different "datestyle" setting.
postgresql749=> insert into date_test values('2006-13-49',null,null);
ERROR: current transaction is aborted, commands ignored until end of transaction block
postgresql749=> select * from date_test;
ERROR: current transaction is aborted, commands ignored until end of transaction block
postgresql749=> rollback;
ROLLBACK

postgresql749=> insert into date_test values('2006-13-49',null,null);
ERROR: date/time field value out of range: "2006-13-49"
HINT: Perhaps you need a different "datestyle" setting.
postgresql749=> rollback;
ROLLBACK

postgresql749=>

ということで今日はここまで。
次回は、Genneric Connectivity経由でPostgreSQLに日付や時間を登録してみる。(どのようになるか楽しみである。)

---
都心では9センチの積雪とか言っていたけど、車にはもっと積もっているような気がする。

| | | コメント (0) | トラックバック (0)

2006年1月21日 (土)

Mac De Oracle Heterogeneous! #18

前回からのつづきです。

Generic Connectivity経由でMySQLにアクセスする際、日付型ではうまく検索できないというものだった。


データ型のマッピンングについて確認していこうと思うが、その前に、日付を条件に指定した検索ができないという問題を回避する方法を探してみることにした。

対象データを日付で絞り込もうとして where句に指定してみると正しく検索できない。

CORYDORAS> list
1 select
2 *
3 from
4 oracle_emp_mysql4026_win@oracle10g_win
5 where
6* "hiredate" >= to_date('19870101','yyyymmdd')
CORYDORAS> /

empno ename job mgr hiredate sal comm deptno
---------- -------------------- ------------------ ---------- -------- ---------- ---------- ----------
7369 SMITH CLERK 7902 80-12-17 800 20
7499 ALLEN SALESMAN 7698 81-02-20 1600 300 30
7521 WARD SALESMAN 7698 81-02-22 1250 500
7566 JONES MANAGER 7839 81-04-02 2975 20
7654 MARTIN SALESMAN 7698 81-09-28 1250 1400 30
7698 BLAKE MANAGER 7839 81-05-01 2850
7782 CLARK MANAGER 7839 81-06-09 2450 10
7788 SCOTT ANALYST 7566 87-04-19 3000 20
7839 KING PRESIDENT 81-11-17 5000 10
7844 TURNER SALESMAN 7698 81-09-08 1500 0 30
7876 ADAMS CLERK 7788 87-05-23 1100 20
7900 JAMES CLERK 7698 81-12-03 950 30
7902 FORD ANALYST 7566 81-12-03 3000 20
7934 MILLER CLERK 7782 82-01-23 1300 10

14行が選択されました。

経過: 00:00:00.10
CORYDORAS>

上記は、Windows XP Professionalに構築したMySQL4.0.26-nt.

その他のPlatformに構築したMySQLそれにPostgreSQLでも確認してみることにした。

PowerMac G5 Dual 2.7Ghz MacOSX Tiger Serverに構築した MySQL4.1.13a及び、PowerBookに構築した PostgreSQL7.4.9の日付型について試してみた。

今回は以下のような経路でアクセスした。

gencon_blog_img1


dump()関数で型を確認するのもいいがDATEかTIMESTAMPのいずれかなので以下のようなフォーマットを設定して区別しやすくしておく。
どちらの形式で表示されるかでマッピングされているのがdate型かtimestamp型なのかが判る。

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>

まずは、PowerMac G5 Dual 2.7Ghz MacOSX Tiger ServerのMySQL4.1.13aで検証した。以下のようなデータを用意。
r_datetime:datetime型、
r_date:date型、
r_timestamp:timestamp型
としてある。
マニュアルによればOracle側ではdate型にマップされることになっているようだ。(実際にはODBCドライバの実装に影響されるようだが。今回 Generic Connectivityで利用しているODBCドライバについてはこちらを参照してほしい。
全データを問い合わせてみると、全てNLS_DATE_FORMATに指定した書式で表示されているのでDATE型にマッピングされているのが判る。

CORYDORAS> 
CORYDORAS> select * from date_test_mysql4113a_mac_sv@oracle10g_win;

r_datetime r_date r_timestamp
------------------- ------------------- -------------------
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

6行が選択されました。

では、早速、MySQLのデータを日付を条件として検索してみる。DATE型にマッピングされているようなので、to_date()関数を利用してDATE型同士で検索してみるが1件もヒットしない。
CORYDORAS> select *
2 from
3 date_test_mysql4113a_mac_sv@oracle10g_win
4 where
5 "r_datetime" <= to_date('19910101','yyyymmdd');

レコードが選択されませんでした。

文字列として比較させると該当するデータが返される。どうやらDATE型ではうまく検索できないようである。
CORYDORAS> select * 
2 from
3 date_test_mysql4113a_mac_sv@oracle10g_win
4 where
5 "r_datetime" = '19900101';

r_datetime r_date r_timestamp
------------------- ------------------- -------------------
1990/01/01 00:00:00 2006/01/20 23:04:22

1行が選択されました。

暗黙型変換ではなく、to_char()により明示的に文字列に変換して比較してみると、やはり、正しい結果が得られた。
CORYDORAS> list
1 select *
2 from
3 date_test_mysql4113a_mac_sv@oracle10g_win
4 where
5* to_char("r_datetime",'yyyymmdd') >= '19900201'
CORYDORAS> /

r_datetime r_date r_timestamp
------------------- ------------------- -------------------
2000/12/01 00:00:00 2006/01/20 23:04:35

1行が選択されました。

MySQLのdate型、及び、timestamp型についても同様の結果だった。
CORYDORAS> select *
2 from
3 date_test_mysql4113a_mac_sv@oracle10g_win
4 where
5 "r_date" <= to_date('18100101','yyyymmdd');

レコードが選択されませんでした。

CORYDORAS> select *
2 from
3 date_test_mysql4113a_mac_sv@oracle10g_win
4 where
5 "r_date" <= '18100101';

r_datetime r_date r_timestamp
------------------- ------------------- -------------------
1800/01/01 00:00:00 2006/01/20 23:04:51

1行が選択されました。

CORYDORAS> select *
2 from
3 date_test_mysql4113a_mac_sv@oracle10g_win
4 where
5 "r_timestamp" <= to_date('20040101','yyyymmdd');

レコードが選択されませんでした。

CORYDORAS> list
1 select *
2 from
3 date_test_mysql4113a_mac_sv@oracle10g_win
4 where
5* "r_timestamp" <= '20040101'
CORYDORAS> /

r_datetime r_date r_timestamp
------------------- ------------------- -------------------
2002/12/01 00:00:00

1行が選択されました。

CORYDORAS>


MySQLでは、date型の検索に多少難ありという結果だったが、PostgreSQL7.4.9ではどうなるかも検証してみた。
PostgreSQL7.4.9では、r_dateをdate型、r_timestampをtimestamp型として定義した。問い合わせると、NLS_DATE_FORMATに指定した書式で表示されるので、これらの型もOracle側ではdate型にマッピングされていることが判る。

CORYDORAS> 
CORYDORAS> select * from date_test_postgresql749_mac@oracle10g_win;

r_date r_timestamp
------------------- -------------------
1900/01/01 00:00:00
2006/01/20 00:00:00
1981/01/01 00:00:00
1990/12/01 00:00:00

4行が選択されました。

MySQLの時と同様に、to_date()関数によるdate型での検索、文字列(暗黙型変換)、to_char()関数による明示型変換それぞれについて検証してみた。結果は、どの方法でも正しく検索できた。
Genneric Connectivity経由のアクセスでは、(Oracleデータベースに慣れている方なら)違和感無く利用できる可能性が高いPostgreSQLのほうが楽だと感じる場面が多いかもしれない。(私感)
CORYDORAS> select *
2 from
3 date_test_postgresql749_mac@oracle10g_win
4 where
5 "r_date" <= to_date('19900101','yyyymmdd');

r_date r_timestamp
------------------- -------------------
1900/01/01 00:00:00

1行が選択されました。

CORYDORAS> select *
2 from
3 date_test_postgresql749_mac@oracle10g_win
4 where
5 to_char("r_date",'yyyymmdd') <= '19900101';

r_date r_timestamp
------------------- -------------------
1900/01/01 00:00:00

1行が選択されました。

CORYDORAS> select *
2 from
3 date_test_postgresql749_mac@oracle10g_win
4 where
5 "r_date" <= '19900101';

r_date r_timestamp
------------------- -------------------
1900/01/01 00:00:00

1行が選択されました。

CORYDORAS> select *
2 from
3 date_test_postgresql749_mac@oracle10g_win
4 where
5 "r_timestamp" <= to_date('19820101');

r_date r_timestamp
------------------- -------------------
1981/01/01 00:00:00

1行が選択されました。

CORYDORAS> select *
2 from
3 date_test_postgresql749_mac@oracle10g_win
4 where
5 to_char("r_timestamp",'yyyymmdd') <= '19820101';

r_date r_timestamp
------------------- -------------------
1981/01/01 00:00:00

1行が選択されました。

CORYDORAS> select *
2 from
3 date_test_postgresql749_mac@oracle10g_win
4 where
5 "r_timestamp" <= '19810101';

r_date r_timestamp
------------------- -------------------
1981/01/01 00:00:00

1行が選択されました。

CORYDORAS>

まとめ。
日付型に関して、Generic Connectivity経由(ODBCドライバ経由)の検索では以下のような点に注意する必要がある。
(各ODBCドライバがアップデートされると挙動が異なる可能性が高いので、実際に利用する際には事前に実機調査されることをお勧めする)

MySQLの日付型をGeneric Connectivity経由で検索する場合には、文字型に変換して検索する。
PostgreSQLの日付型をGenneric Connecvitity経由で検索する場合には、日付型でも文字型でも検索できるので特に注意する点はない。(但し、パフォーマンス面を考えると日付型で検索したほうがよいのではないか?。未検証なので想像ですが。)

次回は、Generic Connectivity経由でリンクされているMySQL4.0.x,4.1.x及びPostgreSQL7.4.9の時間型などについて、Oracle側ではどの型にマッピングされ、どのような”癖”があるのか見てみることにする。

| | | コメント (0) | トラックバック (0)

2006年1月20日 (金)

Mac De Oracle Heterogeneous! #17

つづきです。今日は分析用関数編(すべてではないですが、幾つか試してみました。簡単なところだけですが。。)

gencon_blog_img1

以下のような emp表がMySQL上にあります。おなじみの表です。

CORYDORAS> select * from oracle_emp_mysql4026_win@oracle10g_win;

empno ename job mgr hiredate sal comm deptno
---------- -------------------- ------------------ ---------- -------- ---------- ---------- ----------
7369 SMITH CLERK 7902 80-12-17 800 20
7499 ALLEN SALESMAN 7698 81-02-20 1600 300 30
7521 WARD SALESMAN 7698 81-02-22 1250 500 30
7566 JONES MANAGER 7839 81-04-02 2975 20
7654 MARTIN SALESMAN 7698 81-09-28 1250 1400 30
7698 BLAKE MANAGER 7839 81-05-01 2850 30
7782 CLARK MANAGER 7839 81-06-09 2450 10
7788 SCOTT ANALYST 7566 87-04-19 3000 20
7839 KING PRESIDENT 81-11-17 5000 10
7844 TURNER SALESMAN 7698 81-09-08 1500 0 30
7876 ADAMS CLERK 7788 87-05-23 1100 20
7900 JAMES CLERK 7698 81-12-03 950 30
7902 FORD ANALYST 7566 81-12-03 3000 20
7934 MILLER CLERK 7782 82-01-23 1300 10

14行が選択されました。

CORYDORAS>

ランキング関数 RANK() 。 

CORYDORAS> 
CORYDORAS> list
1 select
2 rank() over (order by "sal") as rank,
3 "empno",
4 "ename",
5 "sal"
6 from
7* oracle_emp_mysql4026_win@oracle10g_win
CORYDORAS> /

RANK empno ename sal
---------- ---------- -------------------- ----------
1 7369 SMITH 800
2 7900 JAMES 950
3 7876 ADAMS 1100
4 7521 WARD 1250
4 7654 MARTIN 1250
6 7934 MILLER 1300
7 7844 TURNER 1500
8 7499 ALLEN 1600
9 7782 CLARK 2450
10 7698 BLAKE 2850
11 7566 JONES 2975
12 7788 SCOTT 3000
12 7902 FORD 3000
14 7839 KING 5000

14行が選択されました。

CORYDORAS>

同じくランキング関数 ROW_NUMBER()。

CORYDORAS> list
1 select
2 row_number() over (order by "empno") as row_number,
3 "empno",
4 "ename"
5 from
6* oracle_emp_mysql4026_win@oracle10g_win
CORYDORAS> /

ROW_NUMBER empno ename
---------- ---------- --------------------
1 7369 SMITH
2 7499 ALLEN
3 7521 WARD
4 7566 JONES
5 7654 MARTIN
6 7698 BLAKE
7 7782 CLARK
8 7788 SCOTT
9 7839 KING
10 7844 TURNER
11 7876 ADAMS
12 7900 JAMES
13 7902 FORD
14 7934 MILLER

14行が選択されました。

経過: 00:00:00.03
CORYDORAS>

集計ウィンドウ関数 FIRST_VALUE() 及び、LAST_VALUE()。

CORYDORAS> break on deptno on first_empno on last_empno skip page
CORYDORAS> list
1 select
2 first_value("empno")
3 over
4 (
5 partition by "deptno"
6 ) as first_empno,
7 last_value("empno")
8 over
9 (
10 partition by "deptno"
11 ) as last_empno,
12 "deptno",
13 "empno",
14 "ename"
15 from
16 oracle_emp_mysql4026_win@oracle10g_win
17 order by
18 "deptno",
19* "empno"
CORYDORAS> /

FIRST_EMPNO LAST_EMPNO deptno empno ename
----------- ---------- ---------- ---------- --------------------
7782 7934 10 7782 CLARK
7839 KING
7934 MILLER

FIRST_EMPNO LAST_EMPNO deptno empno ename
----------- ---------- ---------- ---------- --------------------
7369 7902 20 7369 SMITH
7566 JONES
7788 SCOTT
7876 ADAMS
7902 FORD

FIRST_EMPNO LAST_EMPNO deptno empno ename
----------- ---------- ---------- ---------- --------------------
7499 7900 30 7499 ALLEN
7521 WARD
7654 MARTIN
7698 BLAKE
7844 TURNER
7900 JAMES

14行が選択されました。

経過: 00:00:00.05
CORYDORAS>

ここまでは、分析用関数を簡単な構文で試していたのだが、その過程でちょっと気になることがあった。
Generic ConnectivityでリンクしているMySQLの日付型である。ODBC経由では MySQL側のDatetime型は、OracleのDATE型にマップされるようなのだが。。。

CORYDORAS> list
1 select
2 "ename",
3 to_char("hiredate", 'yyyy/mm/dd') as hiredate
4 from
5* oracle_emp_mysql4026_win@oracle10g_win
CORYDORAS> /

ename HIREDATE
-------------------- ----------
SMITH 1980/12/17
ALLEN 1981/02/20
WARD 1981/02/22
JONES 1981/04/02
MARTIN 1981/09/28
BLAKE 1981/05/01
CLARK 1981/06/09
SCOTT 1987/04/19
KING 1981/11/17
TURNER 1981/09/08
ADAMS 1987/05/23
JAMES 1981/12/03
FORD 1981/12/03
MILLER 1982/01/23

14行が選択されました。

経過: 00:00:00.05

対象データを日付で絞り込もうとして where句に指定してみると以下のようになってしまう。

CORYDORAS> list
1 select
2 *
3 from
4 oracle_emp_mysql4026_win@oracle10g_win
5 where
6* "hiredate" >= to_date('19870101','yyyymmdd')
CORYDORAS> /

empno ename job mgr hiredate sal comm deptno
---------- -------------------- ------------------ ---------- -------- ---------- ---------- ----------
7369 SMITH CLERK 7902 80-12-17 800 20
7499 ALLEN SALESMAN 7698 81-02-20 1600 300 30
7521 WARD SALESMAN 7698 81-02-22 1250 500
7566 JONES MANAGER 7839 81-04-02 2975 20
7654 MARTIN SALESMAN 7698 81-09-28 1250 1400 30
7698 BLAKE MANAGER 7839 81-05-01 2850
7782 CLARK MANAGER 7839 81-06-09 2450 10
7788 SCOTT ANALYST 7566 87-04-19 3000 20
7839 KING PRESIDENT 81-11-17 5000 10
7844 TURNER SALESMAN 7698 81-09-08 1500 0 30
7876 ADAMS CLERK 7788 87-05-23 1100 20
7900 JAMES CLERK 7698 81-12-03 950 30
7902 FORD ANALYST 7566 81-12-03 3000 20
7934 MILLER CLERK 7782 82-01-23 1300 10

14行が選択されました。

経過: 00:00:00.10
CORYDORAS>

あれ? 条件に合わないデータまで取得できちゃうの? なんで?
ということで、次回からは異機種データベースとのデータ型の相性というか、データ型マッピングについて確認してみようと思う。
Generic Connectivityの場合、間にあるODBCドライバの影響も受けるはずなのでどのようなことになりますか。。。

ちなみに、oracle10g R1 for MacOSX Server -> oracle10g R1 for Windows間で同じことをやってみると予想通り正しい結果が返る。

CORYDORAS> list
1* select * from emp@oracle10g_win
CORYDORAS> /

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
7788 SCOTT ANALYST 7566 87-07-13 3000 20
7369 SMITH CLERK 7902 80-12-17 800 20
7499 ALLEN SALESMAN 7698 81-02-20 1600 300 30
7521 WARD SALESMAN 7698 81-02-22 1250 500 30
7566 JONES MANAGER 7839 81-04-02 2975 20
7654 MARTIN SALESMAN 7698 81-09-28 1250 1400 30
7698 BLAKE MANAGER 7839 81-05-01 2850 30
7782 CLARK MANAGER 7839 81-06-09 2450 10
7839 KING PRESIDENT 81-11-17 5000 10
7844 TURNER SALESMAN 7698 81-09-08 1500 0 30
7900 JAMES CLERK 7698 81-12-03 950 30
7902 FORD ANALYST 7566 81-12-03 3000 20
7934 MILLER CLERK 7782 82-01-23 1300 10
7876 ADAMS CLERK 7788 87-07-13 1100 20

14行が選択されました。

CORYDORAS> select *
2 from
3 emp@oracle10g_win
4 where
5 hiredate >= to_date('19870101','yyyymmdd');

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- -------- ---------- ---------- ----------
7788 SCOTT ANALYST 7566 87-07-13 3000 20
7876 ADAMS CLERK 7788 87-07-13 1100 20

CORYDORAS>

次回につづく。

| | | コメント (0) | トラックバック (0)

2006年1月19日 (木)

Mac De Oracle Heterogeneous! #16

さて、Generic Connectivityネタはまだ続きます。

今日はMySQLに Oracleではおなじみの scott.emp表を作り、階層問合せをやってみよう!

できるのか不安だが。。

Last login: Tue Jan 17 20:51:04 on console
Welcome to Darwin!
G5Server:˜ discus$ su - oracle
Password:
G5Server:˜ oracle$ sqlplus /nolog

SQL*Plus: Release 10.1.0.3.0 - Production on 火 1月 17 23:08:28 2006

Copyright (c) 1982, 2004, Oracle. All rights reserved.

> conn / as sysdba
アイドル・インスタンスに接続しました。
SYS> startup
ORACLEインスタンスが起動しました。

Total System Global Area 293601280 bytes
Fixed Size 778888 bytes
Variable Size 99360120 bytes
Database Buffers 192937984 bytes
Redo Buffers 524288 bytes
データベースがマウントされました。
データベースがオープンされました。
SYS>
SYS> conn corydoras
パスワードを入力してください:
接続されました。
CORYDORAS>
CORYDORAS>
CORYDORAS>
CORYDORAS>

Oracleではおなじみの、scottユーザにある emp表をMySQL4.0.26 Windowsに作成し、ORACLE_EMP_MYSQL4026_WIN というシノニムを Windows の Oracle10g R1に作成した。

アクセス経路は以下のようなイメージになる。
gencon_blog_img1


CORYDORAS> select synonym_name from user_synonyms@oracle10g_win;

SYNONYM_NAME
------------------------------
EMP_MYSQL4025_MAC
INNO_EMP_MYSQL4025_MAC
EMP_MYSQL4026_WIN
EMP_MYSQL4113A_MAC_SV
EMP_POSTGRESQL749_MAC
ORACLE_EMP_MYSQL4026_WIN

6行が選択されました。

CORYDORAS> select * from oracle_emp_mysql4026_win@oracle10g_win;

empno ename job mgr hiredate sal comm deptno
---------- -------------------- ------------------ ---------- -------- ---------- ---------- ----------
7369 SMITH CLERK 7902 80-12-17 800 20
7499 ALLEN SALESMAN 7698 81-02-20 1600 300 30
7521 WARD SALESMAN 7698 81-02-22 1250 500 30
7566 JONES MANAGER 7839 81-04-02 2975 20
7654 MARTIN SALESMAN 7698 81-09-28 1250 1400 30
7698 BLAKE MANAGER 7839 81-05-01 2850 30
7782 CLARK MANAGER 7839 81-06-09 2450 10
7788 SCOTT ANALYST 7566 87-04-19 3000 20
7839 KING PRESIDENT 81-11-17 5000 10
7844 TURNER SALESMAN 7698 81-09-08 1500 0 30
7876 ADAMS CLERK 7788 87-05-23 1100 20
7900 JAMES CLERK 7698 81-12-03 950 30
7902 FORD ANALYST 7566 81-12-03 3000 20
7934 MILLER CLERK 7782 82-01-23 1300 10

14行が選択されました。

CORYDORAS>

階層問合せを実行してみると・・・・。
CORYDORAS> list
1 select
2 level,
3 "empno",
4 "ename",
5 "mgr"
6 from
7 oracle_emp_mysql4026_win@oracle10g_win
8 start with
9 "mgr" is null
10 connect by
11* prior "empno" = "mgr"
CORYDORAS> /
select
*
行1でエラーが発生しました。:
ORA-02070: データベースMYSQL4026_WINはこのコンテキストではa connect by clauseをサポートしません。
ORA-02063: 先行のエラー・メッセージを参照してくださいline(ORACLE10G_WIN)。

できないかな〜。
しばし考え込む、MySQL側で階層問い合わせができないのは当然なのだが、階層問い合せ自体ががスルーされないようにできないか。。。
お! ダミー表を用意して外部結合すれば・・・・・早速試してみる。
CORYDORAS> 
CORYDORAS> list
1 select
2 lpad(' ',(level-1)*2,' ')||"empno" as empno,
3 "ename",
4 "mgr",
5 connect_by_isleaf as "Is leaf?"
6 from
7 oracle_emp_mysql4026_win@oracle10g_win remote left outer join
8 (select -1 as dummy from dual) dummy
9 on remote."empno" = dummy.dummy
10 start with
11 "mgr" is null
12 connect by
13* prior "empno" = "mgr"
CORYDORAS> /

EMPNO ename mgr Is leaf?
-------------------- -------------------- ---------- ----------
7839 KING 0
7566 JONES 7839 0
7788 SCOTT 7566 0
7876 ADAMS 7788 1
7902 FORD 7566 0
7369 SMITH 7902 1
7698 BLAKE 7839 0
7499 ALLEN 7698 1
7521 WARD 7698 1
7654 MARTIN 7698 1
7844 TURNER 7698 1
7900 JAMES 7698 1
7782 CLARK 7839 0
7934 MILLER 7782 1

14行が選択されました。

経過: 00:00:00.11
CORYDORAS>
CORYDORAS>

ということで階層問い合せを実行することができた。
ついでに実行計画を取ってみると。
CORYDORAS> set autot trace
CORYDORAS> /

14行が選択されました。


実行計画
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=55 Card=2000 Bytes=80000)
1 0 CONNECT BY (WITH FILTERING)
2 1 FILTER
3 2 COUNT
4 3 HASH JOIN (RIGHT OUTER) (Cost=55 Card=2000 Bytes=80000)
5 4 TABLE ACCESS (FULL) OF 'DUAL' (TABLE) (Cost=2 Card=1 Bytes=2)
6 4 REMOTE* (Cost=52 Card=2000 Bytes=76000) ORACLE10G_WIN
7 1 HASH JOIN
8 7 CONNECT BY PUMP
9 7 COUNT
10 9 HASH JOIN (RIGHT OUTER) (Cost=55 Card=2000 Bytes=80000)
11 10 TABLE ACCESS (FULL) OF 'DUAL' (TABLE) (Cost=2 Card=1 Bytes=2)
12 10 REMOTE* (Cost=52 Card=2000 Bytes=76000) ORACLE10G_WIN
13 1 COUNT
14 13 HASH JOIN (RIGHT OUTER) (Cost=55 Card=2000 Bytes=80000)
15 14 TABLE ACCESS (FULL) OF 'DUAL' (TABLE) (Cost=2 Card=1 Bytes=2)
16 14 REMOTE* (Cost=52 Card=2000 Bytes=76000) ORACLE10G_WIN


6 SERIAL_FROM_REMOTE SELECT "empno","ename","mgr" FROM "ORACLE_EMP_MYSQL4026_WIN" "REMOTE"
12 SERIAL_FROM_REMOTE SELECT "empno","ename","mgr" FROM "ORACLE_EMP_MYSQL4026_WIN" "REMOTE"
16 SERIAL_FROM_REMOTE SELECT "empno","ename","mgr" FROM "ORACLE_EMP_MYSQL4026_WIN" "REMOTE"


統計
----------------------------------------------------------
0 recursive calls
0 db block gets
15 consistent gets
0 physical reads
0 redo size
917 bytes sent via SQL*Net to client
512 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
5 sorts (memory)
0 sorts (disk)
14 rows processed

CORYDORAS>

巨大な表で重くなることも覚悟の上であればこの手法を用いればいろいろとできそうではある。

| | | コメント (0) | トラックバック (0)

2006年1月18日 (水)

Mac De Oracle Heterogeneous! #15

Generic Connectivityの続き。

前回はリモートトランザクションと分散トランザクションについて確認したが、分散クエリーはどうなのか? 念のため確認しておこう。

unionを利用してSQL1文で行ってみた。尚、表及びデータベースリンクはシノニムにしてあるので必要ないのだが、列名は引用識別子にする必要があるのでお忘れなく。

CORYDORAS> 
CORYDORAS> break on table_name skip page
CORYDORAS> select
2 'mysql4025_mac.emp' as table_name,
3 "empno",
4 "ename"
5 from
6 emp_mysql4025_mac@oracle10g_win
7 union all
8 select
9 'mysql4025_mac.inno_emp' as table_name,
10 "empno",
11 "ename"
12 from
13 inno_emp_mysql4025_mac@oracle10g_win
14 union all
15 select
16 'mysql4026_win.emp' as table_name,
17 "empno",
18 "ename"
19 from
20 emp_mysql4026_win@oracle10g_win
21 union all
22 select
23 'mysql4113a_mac_sv.emp' as table_name,
24 "empno",
25 "ename"
26 from
27 emp_mysql4113a_mac_sv@oracle10g_win
28 union all
29 select
30 'postgresql749_mac.emp' as table_name,
31 "empno",
32 "ename"
33 from
34 emp_postgresql749_mac@oracle10g_win
35 order by
36 1,2;

TABLE_NAME empno ename
------------------------------ ---------- ------------------------------
mysql4025_mac.emp 1 おらおら
2 ほげ
3 化けないよねー〜
4 can't rollback

TABLE_NAME empno ename
------------------------------ ---------- ------------------------------
mysql4025_mac.inno_emp 1 おらおら
2 ほげ
3 化けないよねー〜
4 -ー−〜˜

TABLE_NAME empno ename
------------------------------ ---------- ------------------------------
mysql4026_win.emp 1 おらおら
2 ほげ
3 化けないよな〜−
4 -ー−〜˜

TABLE_NAME empno ename
------------------------------ ---------- ------------------------------
mysql4113a_mac_sv.emp 1 ほげほげ
2 ほげ
3 化けないよな〜−
4 -ー−〜˜

TABLE_NAME empno ename
------------------------------ ---------- ------------------------------
postgresql749_mac.emp 1 ほげほげ
2 ほげ
3 化けないよね〜ー
4 -ー−〜˜

20行が選択されました。

経過: 00:00:00.63
CORYDORAS>

問題なくできそうだ。

| | | コメント (0) | トラックバック (0)

2006年1月17日 (火)

Mac De Oracle Heterogeneous! #14

前回にひきつづき、Generic Connectivityでのトランザクションに関連する挙動を見てみた。

Generic Connectivityでは分散トランザクションは行えない。
分散トランザクションを行おうとした場合、どのようなエラーが発生するか見てみることにする。

CORYDORAS> 
CORYDORAS> -- ここまでは、リモートトランザクションなので問題なく実行できる。
CORYDORAS> insert into emp_mysql4026_win@oracle10g_win values(5,'remote transaction');

1行が作成されました。

経過: 00:00:00.03
CORYDORAS>
CORYDORAS> -- 異なるデータベースを更新しようとしているのでここで分散トランザクションになる。
CORYDORAS> insert into emp_mysql4113a_mac_sv@oracle10g_win values(5,'distributed transaction');
insert into emp_mysql4113a_mac_sv@oracle10g_win values(5,'distributed transaction')
*
行1でエラーが発生しました。:
ORA-02047: 動作中の分散トランザクションは結合できません。
ORA-02063: 先行のエラー・メッセージを参照してくださいline(ORACLE10G_WIN)。


経過: 00:00:00.05
CORYDORAS> rollback;

ロールバックが完了しました。

経過: 00:00:00.05
CORYDORAS>

簡単なテストでトランザクションに関する挙動を見てきたが、リモートトランザクションとして実行するようにすれば特に面倒なことはなさそうである。
MySQLを利用する場合には、非トランザクションセーフなエンジンが表に利用されていないか確認しておいたほうがよい。

| | | コメント (0) | トラックバック (0)

2006年1月16日 (月)

Mac De Oracle Heterogeneous! #13

前回からのつづきです。

Generic Connectivityを利用し、異機種データベースのデータを更新するリモートトランザクションの挙動を確認する。


(Oracle Generic Connectivityではトランザクションに関する制限があり分散トランザクションは行えない。リモートトランザクションとローカルトランザクションだけが行えるということになる。)

PowerBook G4 MacOSX Tiger 10.4.3に構築したMySQL4.0.25のemp表は、エンジンにMyISAMを利用している。MyISAMは非トランザクションセーフである。つまり、トランザクションという概念が存在しない。commit文、rollback文がその意味をなさないのである。したがって、INSERT文、UPDATE文、DELETE文を発行すると即座に反映され、rollbackすることはできない。MySQLをリモートデータベースにしている場合にはアクセスする表がトランザクションセーフなエンジンを利用しているかを事前に確認しておいたほうがよいだろう。

CORYDORAS> 
CORYDORAS> insert into emp_mysql4025_mac@oracle10g_win values(4,'can''t rollback');

1行が作成されました。

経過: 00:00:00.68
CORYDORAS> select * from emp_mysql4025_mac@oracle10g_win;

empno ename
---------- ------------------------------
1 おらおら
2 ほげ
3 化けないよねー〜
4 can't rollback

経過: 00:00:00.03
CORYDORAS> rollback;

ロールバックが完了しました。

経過: 00:00:00.05
CORYDORAS> select * from emp_mysql4025_mac@oracle10g_win;

empno ename
---------- ------------------------------
1 おらおら
2 ほげ
3 化けないよねー〜
4 can't rollback

経過: 00:00:00.05
CORYDORAS>

さて、同じデータベースにInnoDBをエンジンとして作成した表はトランザクションセーフなのでrollbackすることができる。

CORYDORAS> 
CORYDORAS> insert into inno_emp_mysql4025_mac@oracle10g_win values(5,'rollback test');

1行が作成されました。

経過: 00:00:00.03
CORYDORAS> select * from inno_emp_mysql4025_mac@oracle10g_win;

empno ename
---------- ------------------------------
1 おらおら
2 ほげ
3 化けないよねー〜
4 -ー−〜˜
5 rollback test

経過: 00:00:00.43
CORYDORAS> rollback;

ロールバックが完了しました。

経過: 00:00:00.15
CORYDORAS> select * from inno_emp_mysql4025_mac@oracle10g_win;

empno ename
---------- ------------------------------
1 おらおら
2 ほげ
3 化けないよねー〜
4 -ー−〜˜

経過: 00:00:00.06
CORYDORAS>

PostgreSQLもトランザクションセーフなのでrollbackすることができる。

CORYDORAS> 
CORYDORAS> insert into emp_postgresql749_mac@oracle10g_win values(5,'rollback test');

1行が作成されました。

経過: 00:00:00.03
CORYDORAS> select * from emp_postgresql749_mac@oracle10g_win;

empno ename
---------- ------------------------------
1 ほげほげ
2 ほげ
3 化けないよね〜ー
4 -ー−〜˜
5 rollback test

経過: 00:00:00.03
CORYDORAS> rollback;

ロールバックが完了しました。

経過: 00:00:00.01
CORYDORAS> select * from emp_postgresql749_mac@oracle10g_win;

empno ename
---------- ------------------------------
1 ほげほげ
2 ほげ
3 化けないよね〜ー
4 -ー−〜˜

経過: 00:00:00.06
CORYDORAS>

次回は分散トランザクションを行おうとするとどのようなエラーが返されるか確認してみることにする。

| | | コメント (0) | トラックバック (0)

2006年1月15日 (日)

Mac De Oracle Heterogeneous! #12

使用しているフォントによっては判りにくいかもしれないが



半角ダッシュ  :"-"

カタカナ長音符号:"ー"

全角ダッシュ  :"−"

全角波線    :"〜"

チルダ(半角):"˜"



を 



Oracle10g R1 (MacOSX Tiger Server) ---database link + synonym --->

---> Oracle10g R1 (Windows) ---> database link + generic connectivity + odbc--->

---> MySQL or PostgreSQLの表



という流れで Oracle10g R1 (MacOSX Tiger Server)からデータを登録し、



Oracle10g R1 (MacOSX Tiger Server) <---

<--- database link + synonym <--- Oracle10g R1 (windows) <---

<--- database link + generic connectivity + odbc <--- MySQL or PostgreSQLの表



という流れで Oracle10g R1 (MacOSX Tiger Server)より問合せ、文字化けしないか確認してみた。

イメージはこんな感じ

gencon_blog_img1

CORYDORAS> insert into inno_emp_mysql4025_mac@oracle10g_win values(4,'-ー−〜˜');

1行が作成されました。

経過: 00:00:01.51
CORYDORAS> commit;

コミットが完了しました。

経過: 00:00:00.18
CORYDORAS> insert into emp_mysql4026_win@oracle10g_win values(4,'-ー−〜˜');

1行が作成されました。

経過: 00:00:00.05
CORYDORAS> commit;

コミットが完了しました。

経過: 00:00:00.05
CORYDORAS> insert into emp_mysql4113a_mac_sv@oracle10g_win values(4,'-ー−〜˜');

1行が作成されました。

経過: 00:00:00.10
CORYDORAS> commit;

コミットが完了しました。

経過: 00:00:00.16
CORYDORAS> insert into emp_postgresql749_mac@oracle10g_win values(4,'-ー−〜˜');

1行が作成されました。

経過: 00:00:00.05
CORYDORAS> commit;

コミットが完了しました。

経過: 00:00:00.63
CORYDORAS>
CORYDORAS> select * from inno_emp_mysql4025_mac@oracle10g_win;

empno ename
---------- ------------------------------
1 おらおら
2 ほげ
3 化けないよねー〜
4 -ー−〜˜

経過: 00:00:00.08
CORYDORAS> select * from emp_mysql4026_win@oracle10g_win;

empno ename
---------- ------------------------------
1 おらおら
2 ほげ
3 化けないよな〜−
4 -ー−〜˜

経過: 00:00:00.05
CORYDORAS> select * from emp_mysql4113a_mac_sv@oracle10g_win;

empno ename
---------- ------------------------------
1 ほげほげ
2 ほげ
3 化けないよな〜−
4 -ー−〜˜

経過: 00:00:00.06
CORYDORAS> select * from emp_postgresql749_mac@oracle10g_win;

empno ename
---------- ------------------------------
1 ほげほげ
2 ほげ
3 化けないよね〜ー
4 -ー−〜˜

経過: 00:00:00.05
CORYDORAS>

これらに関しては特に問題はでていないようである。
次回はこの環境でトランザクションはどうなるのか?  簡単に確認してみることにする。

| | | コメント (0) | トラックバック (0)

2006年1月14日 (土)

Mac De Oracle Heterogeneous! #11

前回からのつづきです。

やっと準備が完了といいますか、Windowsに作成したOracle10g R1 10.1.0.3.0からMySQLやPostgreSQLにアクセスできることまでは確認した。

さて、問題になるのは、どうやってPowerMac G5 Dual2.7Ghz Oracle10g R1 10.1.0.3.0 for MacOSX ServerからWindows版 Oracle10g R1の向うにあるMySQLやPostgreSQLにアクセスするのかという点である。

データベースリンクのネストなんて文法上許されてない訳だし。。。で思いついたのが。。。。

シノニムを利用するということだった。

では早速、Windows XP Professionalに作成したOracle10g R1 10.1.0.3.0に作ったデータベースリンクを利用して、各データベースに作成した emp表向けシノニムを作成する。

まずは作成済みデータベースリンクを確認しておく。

SQL*Plus: Release 10.1.0.2.0 - Production on 土 1月 14 17:22:34 2006

Copyright (c) 1982, 2004, Oracle. All rights reserved.
SQL> conn / as sysdba
接続されました。
SQL> select * from v$version;

BANNER
---------------------------------------------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.1.0.3.0 - Prod
PL/SQL Release 10.1.0.3.0 - Production
CORE 10.1.0.3.0 Production
TNS for 32-bit Windows: Version 10.1.0.3.0 - Production
NLSRTL Version 10.1.0.3.0 - Production

SQL>
SQL> conn discus
パスワードを入力してください: ************
接続されました。
SQL> select db_link from user_db_links;

DB_LINK
--------------------------------------------------------------------------------
MYSQL4025_MAC
MYSQL4026_WIN
MYSQL4113A_MAC_SV
POSTGRESQL749_MAC

この例では、プライベート・シノニムを作成した。シノニムは各データベースのemp表毎に作成した。
尚、MySQL4.0.25 に作成した emp表は MyISAM 、inno_emp表は、InnoDBその他のMySQLでは、emp表はInnoDBをエンジンとしている。

SQL> set linesize 132
SQL> col ename for a30
SQL>
SQL> -- PowerMac G4 MacOSX Tiger 10.4.3 MySQL4.0.25
SQL> create synonym emp_mysql4025_mac for "emp"@mysql4025_mac;

シノニムが作成されました。

SQL> -- PowerMac G4 MacOSX Tiger 10.4.3 MySQL4.0.25
SQL> create synonym inno_emp_mysql4025_mac for "inno_emp"@mysql4025_mac;

シノニムが作成されました。

SQL> -- AMD AthronMP Dual 2800+ Windows XP Professional
SQL> create synonym emp_mysql4026_win for "emp"@mysql4026_win;

シノニムが作成されました。

SQL> -- PowerMac G5 Dual 2.7Ghz MacOSX Tiger 10.4.3 Server MySQL4.1.13a
SQL> create synonym emp_mysql4113a_mac_sv for "emp"@mysql4113a_mac_sv;

シノニムが作成されました。

SQL> -- PowerMac G4 MacOSX Tiger 10.4.3 PostgreSQL7.4.9
SQL> create synonym emp_postgresql749_mac for "emp"@postgresql749_mac;

シノニムが作成されました。


SQL> select synonym_name from user_synonyms;

SYNONYM_NAME
----------------------------------------------------------
EMP_MYSQL4025_MAC
INNO_EMP_MYSQL4025_MAC
EMP_MYSQL4026_WIN
EMP_MYSQL4113A_MAC_SV
EMP_POSTGRESQL749_MAC

シノニムの確認も兼ねて各表に登録されているデータを確認しておく。

SQL> -- PowerMac G4 MacOSX Tiger 10.4.3 MySQL4.0.25
SQL> select * from emp_mysql4025_mac;

empno ename
---------- ------------------------------
1 おらおら
2 ほげ
3 化けないよねー〜

SQL> -- PowerMac G4 MacOSX Tiger 10.4.3 MySQL4.0.25
SQL> select * from inno_emp_mysql4025_mac;

empno ename
---------- ------------------------------
1 おらおら
2 ほげ
3 化けないよねー〜

SQL> -- AMD AthronMP Dual 2800+ Windows XP Professional
SQL> select * from emp_mysql4026_win;

empno ename
---------- ------------------------------
1 おらおら
2 ほげ
3 化けないよな〜−

SQL> -- PowerMac G5 Dual 2.7Ghz MacOSX Tiger 10.4.3 Server MySQL4.1.13a
SQL> select * from emp_mysql4113a_mac_sv;

empno ename
---------- ------------------------------
1 ほげほげ
2 ほげ
3 化けないよな〜−

SQL> -- PowerMac G4 MacOSX Tiger 10.4.3 PostgreSQL7.4.9
SQL> select * from emp_postgresql749_mac;

empno ename
---------- ------------------------------
1 ほげほげ
2 ほげ
3 化けないよね〜ー

SQL>

となっている。

今回の目的である Windows XP ProfessionalのOracle10g R1を踏み台にして、generic connectivityが組み込まれていない MacOSX版 Oracle10g R1からMySQLやPostgreSQLにアクセスするための準備はもう少しある。
それは、MacOSX Tiger 10.4.3 Serverに構築したOracle10g R1 10.1.0.3.0から Windows XP Professionalに構築したOracle10g R1 10.1.0.3.0にデータベースリンクを作成し、前述したシノニムにアクセスできるようにすることである。
以下は、MacOSX Tiger 10.4.3 ServerのOracle10g R1での作業である。まず tnsnames.oraを編集し、Windows XP Professionalに構築したOracle10g R1に接続できるようにする。接続文字列 CATFISHがそれである。

Last login: Sat Jan 14 16:36:47 on console
Welcome to Darwin!
G5Server:˜ discus$ su - oracle
Password:
G5Server:˜ oracle$ cat $ORACLE_HOME/network/admin/tnsnames.ora
# tnsnames.ora Network Configuration File: /Volumes/Discus/4oracle/oracle/u01/app/oracle/product/10.1.0/tigerx/network/admin/tnsnames.ora
# Generated by Oracle configuration tools.

XTIGER =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.19)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = xtiger)
)
)

CATFISH =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.2)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = catfish)
)
)

次に CATFISH にアクセスするためのデータベースリンクを作成する。
テスト用にユーザ(corydoras)を新たに作成してプライベートデータベースリンク(oracle10g_win)を作成した。

G5Server:˜ oracle$ 
G5Server:˜ oracle$
G5Server:˜ oracle$ sqlplus /nolog

SQL*Plus: Release 10.1.0.3.0 - Production on 土 1月 14 16:48:04 2006

Copyright (c) 1982, 2004, Oracle. All rights reserved.

> conn / as sysdba
アイドル・インスタンスに接続しました。
SYS> startup
ORACLEインスタンスが起動しました。

Total System Global Area 293601280 bytes
Fixed Size 778888 bytes
Variable Size 99360120 bytes
Database Buffers 192937984 bytes
Redo Buffers 524288 bytes
データベースがマウントされました。
データベースがオープンされました。
SYS>
SYS> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.1.0.3.0 - Prod
PL/SQL Release 10.1.0.3.0 - Production
CORE 10.1.0.3.0 Production
TNS for MacOS X Server: Version 10.1.0.3.0 - Production
NLSRTL Version 10.1.0.3.0 - Production

SYS>
SYS>
SYS>
SYS> create user corydoras identified by xxxxx
2 default tablespace users
3 temporary tablespace temp
4 quota unlimited on users;

ユーザーが作成されました。

SYS> grant
2 connect,
3 create synonym,
4 create database link,
5 create table
6 to
7 corydoras;

権限付与が成功しました。

SYS> conn corydoras
パスワードを入力してください:
接続されました。
CORYDORAS>
CORYDORAS> create database link oracle10g_win
2 connect to discus identified by xxxxx using 'catfish';

データベース・リンクが作成されました。

作成したデータベースリンクでアクセスできるか確認を兼ねて、Windows XP Professional の Oracle10gにある discusユーザの user_db_linksビュー及び user_synonymsビューを問い合わせてみる。

CORYDORAS> select db_link from user_db_links@oracle10g_win;

DB_LINK
--------------------------------------------------------------------------------
MYSQL4025_MAC
MYSQL4026_WIN
MYSQL4113A_MAC_SV
POSTGRESQL749_MAC

CORYDORAS>
CORYDORAS> set linesize 132
CORYDORAS> col db_link for a40
CORYDORAS> select
2 synonym_name,
3 table_name,
4 db_link
5 from user_synonyms@oracle10g_win;

SYNONYM_NAME TABLE_NAME DB_LINK
------------------------------ ------------------------------ ----------------------------------------
EMP_MYSQL4025_MAC emp MYSQL4025_MAC
INNO_EMP_MYSQL4025_MAC inno_emp MYSQL4025_MAC
EMP_MYSQL4026_WIN emp MYSQL4026_WIN
EMP_MYSQL4113A_MAC_SV emp MYSQL4113A_MAC_SV
EMP_POSTGRESQL749_MAC emp POSTGRESQL749_MAC

CORYDORAS>

さて、いよいよ Windows XP Professional に構築した Oracle10g R1 の generic connectivityを経由して、generic connetivityのない MacOSX Server版 Oracle10g R1 から MySQLやPostgreSQLの表を問い合わせてみる! どうなるか。。。。

CORYDORAS> set timi on
CORYDORAS> col ename for a30
CORYDORAS>
CORYDORAS> select * from emp_mysql4025_mac@oracle10g_win;

empno ename
---------- ------------------------------
1 おらおら
2 ほげ
3 化けないよねー〜

経過: 00:00:09.48
CORYDORAS> select * from inno_emp_mysql4025_mac@oracle10g_win;

empno ename
---------- ------------------------------
1 おらおら
2 ほげ
3 化けないよねー〜

経過: 00:00:01.28
CORYDORAS> select * from emp_mysql4026_win@oracle10g_win;

empno ename
---------- ------------------------------
1 おらおら
2 ほげ
3 化けないよな〜−

経過: 00:00:00.70
CORYDORAS> select * from emp_mysql4113a_mac_sv@oracle10g_win;

empno ename
---------- ------------------------------
1 ほげほげ
2 ほげ
3 化けないよな〜−

経過: 00:00:01.11
CORYDORAS> select * from emp_postgresql749_mac@oracle10g_win;

empno ename
---------- ------------------------------
1 ほげほげ
2 ほげ
3 化けないよね〜ー

経過: 00:00:08.45
CORYDORAS>

やりました〜〜〜〜〜!。 ふ〜。ひとまず、狙い通りの結果がで、よかったよかった。これでこのネタで、もう少し引っ張れそうな気が。。しかし、Oracle10g R2のPreview Releaseがされたら、すぐにそちらで遊びだすかもしれない。噂通り早めにIntel版 Macもリリースされたことだし。

| | | コメント (0) | トラックバック (0)

2006年1月13日 (金)

Mac De Oracle Heterogeneous! #10

前回まででWindowsに作成したOracle10g R1をMySQL及び、PostgreSQLをアクセスするHUBにするための構成は完了した。

リスナーの構成を反映させるためリスナーの再起動を行った。まずは再起動したリスナーの状態を確認。
各サービスのインスタンスがリストされているのが判るだろうか?

C:¥Documents and Settings¥Administrator>
C:¥Documents and Settings¥Administrator>lsnrctl status

LSNRCTL for 32-bit Windows: Version 10.1.0.2.0 - Production on 09-1月 -2006 15:02:20

Copyright (c) 1991, 2004, Oracle. All rights reserved.

(DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC)))に接続中
リスナーのステータス
------------------------
別名 LISTENER
バージョン TNSLSNR for 32-bit Windows: Version 10.1.0.2.0 - Production
開始日 09-1月 -2006 15:01:33
稼働時間 0 日 0 時間 0 分 51 秒
トレース・レベル off
セキュリティ ON: Local OS Authentication
SNMP OFF
パラメータ・ファイル E:¥oracle¥product¥10.1.0¥catfish¥network¥admin¥listener.ora
ログ・ファイル E:¥oracle¥product¥10.1.0¥catfish¥network¥log¥listener.log
リスニング・エンドポイントのサマリー...
(DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(PIPENAME=¥¥.¥pipe¥EXTPROCipc)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.1.2)(PORT=1521)))
サービスのサマリー...
サービス"PLSExtProc"には、1件のインスタンスがあります。
インスタンス"PLSExtProc"、状態UNKNOWNには、このサービスに対する1件のハンドラがあります...
サービス"PostgreSQL749"には、1件のインスタンスがあります。
インスタンス"PostgreSQL749"、状態UNKNOWNには、このサービスに対する1件のハンドラがあります...
サービス"mysql4025_MacOSX"には、1件のインスタンスがあります。
インスタンス"mysql4025_MacOSX"、状態UNKNOWNには、このサービスに対する1件のハンドラがあります...
サービス"mysqldb4026_windows"には、1件のインスタンスがあります。
インスタンス"mysqldb4026_windows"、状態UNKNOWNには、このサービスに対する1件のハンドラがあります...
サービス"mysqldb4113a_MacOSX_Server"には、1件のインスタンスがあります。
インスタンス"mysqldb4113a_MacOSX_Server"、状態UNKNOWNには、このサービスに対する1件のハンドラがあります...
コマンドは正常に終了しました。

C:¥Documents and Settings¥Administrator>




データベースリンクを作成してリモートデータベースにアクセスするのだが、今回はプライベートデータベースリンクを作成することにし、新たにユーザを作成した。
SQL> conn / as sysdba
SQL> create user discus identified by xxxxxxxx
2 default tablespace users
3 temporary tablespace temp
4 quota unlimited on users;

ユーザーが作成されました。

SQL> grant
2 connect,
3 create synonym,
4 create database link,
5 create table
6 to
7 discus;

権限付与が成功しました。




データベースリンクを作成する前に確認しておくことが1点ある。global_names=falseであることを確認しておくことである。
SQL> conn / as sysdba
SQL> show parameter global_names

NAME TYPE VALUE
------------ -------------- ---------------
global_names boolean FALSE
SQL>

もし、trueならば、falseに変更しておく。動的パラメータなので
SQL> alter system set global_names = false scope=both;

システムが変更されました。

SQL>
で変更可能である。
尚、これはspfile の利用を前提に記述している。pfileを利用している場合には、init_<SID>.oraファイルを変更し、再起動が必要である。(ただし、scope=memoryとしてalter system文を発行し、後日再起動しても同じである。)

さていよいよ、プライベートデータベースリンクを作成し、MySQL及び、PostgreSQLにアク