2016年3月19日 (土)

Relational Database Index Design and the Optimizers [Kindle版]とUSE THE INDEX, LUKE

時代は繰り返すw のか? という感じで何周目かのIndex only scanとかのネタを元にした資料とか作ることが多くて。。。

索引の設計って、基本的に、機械的だと思っているのですが、皆さんはどう思っているのか気になる今日この頃。
初心者ならともかく、そうでもない感じの方が、腕組みして、眉間にしわ寄せてるのをみるとちょっと心配になっちゃったり。


と昨日のtwで見かけたやつとかも含めて参考になりそうな書籍を載せておきますね。

最初は私のお気に入りの一冊(ハードカバー本でしたが、最近kindle版がでてました。そして私が買った時より高いw
この書籍は2011 db tech showcaseでTom Kyteさんが紹介していたもので、速攻でポチった記憶があります。
そしてその頃は、8,000円台でしたw(円高だったからねぇ)

この書籍ではCovering Index → FAT Index / Semi Covering Index → Semi FAT Indexと記載されています。

Web上でも読めるんですが、書籍化されPDF版もでてます。
SQLパフォーマンス詳解(原文タイトルSQL Performance Explained)


USE THE INDEX, LUKE - 開発者のためのSQLパフォーマンスの全て

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

2016年3月17日 (木)

こんなのでいいのかなぁ。ズンドコキヨシ  ObjectScript / MUMPS


2016/3/18追記#3

よ〜く見てたら、ズン!は4回だったw 結局この83文字のパターンマッチング版でよかったのか〜〜w (おしまい)

S l="",w(0)="ズン!",w(1)="ドコ!" F  S l=l_w($R(2)) I l ?.E4"ズン!"1"ドコ!" W !,l,"キ・ヨ・シ!" Q

USER>S l="",w(0)="ズン!",w(1)="ドコ!" F  S l=l_w($R(2)) I l ?.E4"ズン!"1"ドコ!" W !,l,"キ・ヨ・シ!" Q

ズン!ズン!ドコ!ズン!ドコ!ドコ!ズン!ズン!ドコ!ズン!ズン!ドコ!ドコ!ズン!ドコ!ドコ!ドコ!ズン!ドコ!ズン!ドコ!ズン!ドコ!ドコ!ズン!ズン!ズン!ズン!ドコ!キ・ヨ・シ!


2016/3/18追記#2

旧構文のFORとIFを使えば82文字まで短縮できた。

S l="",w(0)="ズン!",w(1)="ドコ!" F  S l=l_w($R(2)) I l["ズン!ズン!ズン!ドコ!" W !,l,"キ・ヨ・シ!" Q

USER>S l="",w(0)="ズン!",w(1)="ドコ!" F  S l=l_w($R(2)) I l["ズン!ズン!ズン!ドコ!" W !,l,"キ・ヨ・シ!" Q

ドコ!ズン!ズン!ドコ!ドコ!ズン!ドコ!ズン!ズン!ズン!ズン!ズン!ドコ!キ・ヨ・シ!


調子に乗ってパターンマッチに書き換えたら1文字増えて83文字w orz

S l="",w(0)="ズン!",w(1)="ドコ!" F  S l=l_w($R(2)) I l ?.E3"ズン!"1"ドコ!" W !,l,"キ・ヨ・シ!" Q

USER>S l="",w(0)="ズン!",w(1)="ドコ!" F  S l=l_w($R(2)) I l ?.E3"ズン!"1"ドコ!" W !,l,"キ・ヨ・シ!" Q

ズン!ズン!ドコ!ドコ!ズン!ズン!ドコ!ズン!ズン!ズン!ドコ!キ・ヨ・シ!



2016/3/18追記

85文字までに縮めたw もうむりか?

S l="",w(0)="ズン!",w(1)="ドコ!" F {S l=l_w($R(2)) I l["ズン!ズン!ズン!ドコ!" {W !,l,"キ・ヨ・シ!" Q}}

USER>S l="",w(0)="ズン!",w(1)="ドコ!" F {S l=l_w($R(2)) I l["ズン!ズン!ズン!ドコ!" {W !,l,"キ・ヨ・シ!" Q}}

ズン!ズン!ドコ!ドコ!ズン!ズン!ドコ!ズン!ズン!ドコ!ズン!ドコ!ドコ!ズン!ズン!ズン!ドコ!キ・ヨ・シ!

こんなのでいいのかなぁ。ズンドコキヨシ

もっといいのが浮かびそうだっただけど、眠気で頭まわらなくなってきたので、一旦これでw

ズンドコキヨシまとめ


M言語というか、MUMPSというか、Caché ObjectScriptでやっつけてみた

S s=0 F {S r=$R(2) W !,$CASE(r,0:"ズン!",1:"ドコ!") S s=$CASE(r,0:$CASE(s,0:1,1:2,2:3,:3),1:$CASE(s,3:4,:0)) W:s=4 !,"キ・ヨ・シ!" Q:s=4}
USER>S s=0 F {S r=$R(2) W !,$CASE(r,0:"ズン!",1:"ドコ!") S s=$CASE(r,0:$CASE(s,0:1,1:2,2:3,:3),1:$CASE(s,3:4,:0)) W:s=4 !,"キ・ヨ・シ!" Q:s=4}

ズン!
ズン!
ドコ!
ドコ!
ドコ!
ズン!
ドコ!
ズン!
ズン!
ドコ!
ズン!
ドコ!
ドコ!
ズン!
ズン!
ドコ!
ズン!
ズン!
ズン!
ズン!
ズン!
ズン!
ズン!
ドコ!
キ・ヨ・シ!

USER>halt
[oracle@pleco ˜]$

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

2015年5月17日 (日)

ClubDB2 200回記念に参加してきた :)

ミックさんの出版記念というか、200回記念に、37回目以来、7年ぶりにClubDB2 200回 「SQLにおける手続き型の復権」に参加してきた。

ClubDB2なのに、Oracleを使ってデモをしていたのは、ヒントが使えるからですよね。(ここ重要)
ヒントを使って実行計画を変えたとき、駆動表や、索引使用の有無でどのような結果になるのか追いやすいんですよ == 勉強しやすいといったほうがよいかもしれませんね。

おっと、 本題から外れすぎた w m(_ _)m

Clubdb2_200

1年振りにミックさんにお会いして、久々にミック節を聞かせてもらいました。 楽しかったです!
(1年振り以上ですよ! とミックさんから言われたんだけど、そうだっけ?w)

そして、37回目にもご一緒だった、木村明治さん!。
ミックさんと共著された書籍が発売されてますよね :)。


ClubDB2といいながら、MySQL系の方や、PostgreSQL系の方もちらほら参加している点も面白いですよね。

最後は予想通り、ミックさんのサイン会でした:)


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

2014年6月28日 (土)

InterSystems Symposia 2014に行ってきた

db tech showcase 2014 Osakaより先だったのだけど...
InterSystems Symposia 2014に行ってきた。という話。

CachéはSQLでアクセスする必要はないのだけど、RDBMSからの乗り換え組でSQLから乗り換えコストの低減目的で導入されたインターフェースだというのは間違いなし、
昔からM言語をやってきた人達からすれば、SQLアクセスだと! はぁ〜? 的な感じも無くはないし、おまけ的なイメージは強いんだろうな。
その分のオーバーヘッドもあるしな〜。 と思ってたのですが....

最近の動きを見ているとSQLアクセスにも本気なのかな。と思わせる様子があるんだよね。

Caché SQL 最新情報の資料P3部分でダイレクトアクセス(元からあるNoSQLな部分)とSQLアクセスのメリット、デメリットの解説やビットマップインデックスのメンテナンス機能。

20140628_124018
Caché SQL 最新情報のセッション資料は上のリンクからダウンロードできますよ!


そして、 Push Subquery Conditions into UNION LegsなどのSQL実行計画最適化、OracleのUSE_CONCAT相当など多数のヒント、パラレルクエリなど"おまけのインターフェース"とは思えなくなってきた感がある。


ちなみに、Caché自体はスパース多次元配列なので行指向、列指向のようなことはないんだけど、列指向的な加工もできちゃうわけで、それはそれで面白いかなと、勝ってに妄想してみたりw

たまには、右脳を活性化しないとね、イメージ力大事 :)

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

2014年6月21日 (土)

db tech showcase 2014 Osaka に行ってきた

I love your data(どこかのパクリw) な人たちが、いろいろなDBMSを見聞きし、それぞれの思いで、何年か先の未来に、それぞれの思いを馳せる

そんな、集まりが、 db tech showcase 2014 Osaka 

(ん....俺っぽくない出だしを書いててワロタ....)


に臨時休業(自分ではこれも仕事のうちなんだがw 仕事って思ってないだけw)して参加した。
https://www.facebook.com/db.tech.showcase

Slideshare : セッション資料はここ


話を聞いていたら、オレオレレプリケーションできそうな気になるから不思議 :) .
オレオレ、ゴルゲやオレオレ、attunityとか、自分で作って試してみると、面倒くさいポイントとか見えていいかもね。
Attunity Replicateの画面を初めてみたけど、シンプルで好きなデザイン。
B31 : LogMinerってレプリケーションソフトで使われてるけどどうなってる? / 森田俊哉(インサイトテクノロジー)


Oracle以外の話も聴きたくてNoSQL系などをチョイス。 割り切った実装で特定用途でその力を発揮する。割り切り大事。
D32 : Amazon Redshift Deep Dive / 大久保順(アマゾンデータサービスジャパン)


B33 : Riak: 本物の高可用性を実現する仕組みとは? / 佐藤 貴彦 (Bashoジャパン)


D34 : データウェアハウス・エンジンTeradataのご紹介とビッグデータ統合アーキテクチャー / 山本 泰史(日本テラデータ)


The Machine!にも関連するのだろうけど、Memristorの話題も!
D35 : インメモリーデータベース徹底比較 / 小森博之(日本HP)


そしてスペシャルセッション、遠い未来じゃないはなし
A36 : ウエアラブルとO2Oが切り拓くICTの新地平 / 村上憲郎

vessylもそんな”もの”の一つかもしれない。飲みものの分析ができるんだからトイレにも応用できるんじゃないか的な :)
日本のトイレがそうなるかは分からないけど、先にやってくれたら面白いかもね。
毎日が健康診断、データはかかりつけの医師に共有されていて、気になるデータが見つかると、洗面台のミラー風マルチタッチデバイスに情報がプッシュされ...必要なら、その場で通院予約、その後待たされることなく診察なんて時間の無駄がなくていいな〜と、ぼーっと妄想していたり。

楽しいやね。 :)

そういえばそんなシーンのある映画で思い出したのがこれ



T-シャツ、ありがとうございました。
Bqilsptcyaae4vjjpglarge

東京から大阪への新幹線で日帰りだと電池切れ感が半端ないので一泊することをおすすめしますw


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

2012年10月21日 (日)

Unconference at db tech showcase 2012の資料公開 :)

db tech showcase 2012
Unconference at db tech showcase 2012

db tech showcaseの一角をJPOUGが占拠してUnconferenceを開催しました。 db tech showcase関係者の皆様、このような機会を与えて頂き大変感謝します。
そして、お疲れさまでした。



Index Only Access 3部作の最終回?! として 「Index Only Accessが実装されるたった一つの理由」と題したセッションを行いました。
実行計画を取得するために操作したデータベースの中には人生二度目のデータベース複数もあり、かなりの時間を裂いて調べた割にはセッション時間が少々短めになってしまいました。m(_ _)m

なぜ、このテーマを選んだか.

PostgreSQLがリリースされてから9.1まで実装されなかったIndex Only Accessでしたが、9.2でついに実装されました。

そして..db tech showcase 2012は...

SQL> select dbms_name from all_dbms where dbms_category like "%";

DBMS_NAME
------------------
Oracle
DB2
MySQL
PostgreSQL
SQL Server
Vecterwise
MongoDB
Symfoware
Clustrix
InfiniDB
.
.
.
.

的な雰囲気となっていることもあり、Index Only Accessの魚拓をあつめて比較、Index Only Accessが実装される理由について今一度、考えてみたいな..と。
タイトル見ただけで理由が想像できた方は、資料見なくても大丈夫だと思いますよ。:) 
 

H/Wの性能が急速に伸びてきている影響もあるように感じますが、無駄に広範囲な検索や、無駄にビッグなデータとなっていること気にしていないのではないか? というケースが多くなっていると感じています。
DBMSはアクセスするデータをより少なくするための工夫をしているのに...エンジニアがそれをうまく使っていない、使えていない、設計できてない...そんな"感じ"がするんです。

セッション資料を公開しました。
S1a


じゃ、like "%てない" 状況をどうすればいいか....答えは、小田さんのセッションの中にあった。。。。:)


#不慣れなDBMSもあり、こんなメトリックみたほうが分かりやすいよ〜、などのツッコミ歓迎します.


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

2012年9月 2日 (日)

Index Only Accessネタのおまけのおまけ

Caché de Index Only Access できるのか?

CachéってSQLもサポートしてるので、Index Only Accessサポートしてるのかな〜と素朴な疑問から調べてみたもののマニュアルには記載されていない。
書かれていなきゃどうなるか、試すのが手っ取り早いですね。
(ダウンロードするにはフォームからリクエストする必要があります。1セッション限定の試用ライセンスのようです。他の制限は該当ページ読んでくださいな。)


OracleのIndex Only Accessは以下のエントリを参考にしてください。
いん!、イン!、Index どっぷり Inde Only Access生活w - Oracle OpenWorld Unconference presented by JPOUG
JPOUG SET EVENTS 20120721 - 「(続)いん!、イン!、Index 大人の事情縛りのSQLチューニング」資料公開

MySQL/PostgreSQLのIndex Only Accessは以下のエントリを参考にしてください。
Index Only Accessネタのおまけ


いつもはMacBook Air使うんですが、今回は都合により母艦のVirtualBoxを使いました (^^;;

MacPro Mid 2012 12Core/24GB (OS X Mountain Lion Server)
VirtualBox4.1.20 for MacOS X
GuestOS:CentOS5.8 x86_64 (CPU数とメモリサイズはMacBook Airのx86環境と同じ)

Caché 2012.1 for Linux x86_64


まず、ターミナルで接続して表、索引、データ登録、他のデータベースで言う統計情報取得から。

[oracle@pleco ˜]$ csession cache -U samples

ノード: pleco.macdeoracle.jp インスタンス: CACHE

SAMPLES>

SAMPLES>d $System.SQL.Shell()
SQL Command Line Shell
----------------------------------------------------

The command prefix is currently set to: <<nothing>>.
Enter q to quit, ? for help.
SAMPLES>>
SAMPLES>>create table tab3(unique_id numeric(10) not null, item_code char(15) not null, data varchar(500), is_delete numeric(1), status_code char(2))
1. create table tab3(unique_id numeric(10) not null, item_code char(15) not null, data varchar(500), is_delete numeric(1), status_code char(2))

0 Rows Affected
statement prepare time: 0.0118s, elapsed execute time: 0.2405s.
---------------------------------------------------------------------------
SAMPLES>>
SAMPLES>>alter table tab3 add constraint tab3_pk primary key(unique_id)
3. alter table tab3 add constraint tab3_pk primary key(unique_id)

0 Rows Affected
statement prepare time: 0.0092s, elapsed execute time: 4.9465s.
---------------------------------------------------------------------------
SAMPLES>>
SAMPLES>>create table tab311 (unique_id numeric(10) not null,sub_item_code char(10),data varchar(500),is_delete numeric(1))
4. create table tab311 (unique_id numeric(10) not null,sub_item_code char(10),data varchar(500),is_delete numeric(1))

0 Rows Affected
statement prepare time: 0.0115s, elapsed execute time: 0.1953s.
---------------------------------------------------------------------------
SAMPLES>>create table tab31 (item_code char(15) not null,sub_item_code char(10),data varchar(500),is_delete numeric(1))
5. create table tab31 (item_code char(15) not null,sub_item_code char(10),data varchar(500),is_delete numeric(1))

0 Rows Affected
statement prepare time: 0.0133s, elapsed execute time: 0.1985s.
---------------------------------------------------------------------------
SAMPLES>>
SAMPLES>>alter table tab31 add constraint tab31_pk primary key(item_code)
7. alter table tab31 add constraint tab31_pk primary key(item_code)

0 Rows Affected
statement prepare time: 0.0102s, elapsed execute time: 0.2589s.
---------------------------------------------------------------------------
SAMPLES>>alter table tab311 add constraint tab311_pk primary key(unique_id)
8. alter table tab311 add constraint tab311_pk primary key(unique_id)

0 Rows Affected
statement prepare time: 0.0116s, elapsed execute time: 0.2627s.
---------------------------------------------------------------------------
SAMPLES>>create index tab311_ix on tab311(sub_item_code)
9. create index tab311_ix on tab311(sub_item_code)

0 Rows Affected
statement prepare time: 0.0111s, elapsed execute time: 0.2870s.
---------------------------------------------------------------------------
SAMPLES>>q

確認は管理ポータルで!(どこみればよいか分からなかったので楽な方法で..)

Desc_tab3

Tab3_indexes_no_index_only

Desc_tab31

Tab31_indexes_no_index_only

Desc_tab311

Tab311_indexes_no_index_only_scan

Oracleなら統計情報取得、他のRDBMSならアナライズ(昔はオラクルもアナライズだったんですけどね)、Cachéの世界では「テーブルチューニング」というそうな。
(管理ポータルから実行しています)
Table_analyze

Tab31_analyze

Tab311_analyze

表と索引ができたのでデータ登録。
これまたOracleとは勝っても違うし、DSMの時代(DIGITAL STANDARD MUMPS)から大きく拡張されてるのでかなり辛いな〜MUMPS思い出すというより別物に近い感じw。あの当時はSQL使えねーしというより必要ねーし、だったしね (^^;;;

以下、データ作成中のログ..
グルグル回しているのは気にしないでねw

[oracle@pleco ˜]$ csession cache -U samples

ノード: pleco.macdeoracle.JP インスタンス: CACHE

SAMPLES>
SAMPLES>
SAMPLES>s rs=##class(%SQL.Statement).%ExecDirect(,"start transaction")
TL1:SAMPLES>s sql="insert into SQLUser.tab3 values(?,to_char((?#500000)+1,'FM099999999999999'),repeat('*',250-length(to_char(?)))||to_char(?),0,'00')"
TL1:SAMPLES>s stmt=##class(%SQL.Statement).%New() s stat=stmt.%Prepare(sql)
TL1:SAMPLES>f i=1:1:1000000 {s rs=stmt.%Execute(i,i,i,i)}
TL1:SAMPLES>s rs=##class(%SQL.Statement).%ExecDirect(,"commit")
SAMPLES>d $System.SQL.Shell()

SQL Command Line Shell
----------------------------------------------------

The command prefix is currently set to: <<nothing>>.
Enter q to quit, ? for help.
SAMPLES>>select count(1) from tab3
7. select count(1) from tab3

Aggregate_1
1000000

1 Rows(s) Affected
statement prepare time: 0.0009s, elapsed execute time: 2.6558s.
---------------------------------------------------------------------------
SAMPLES>>select min(unique_id) as "min", max(unique_id) as "max" from tab3
8. select min(unique_id) as "min", max(unique_id) as "max" from tab3

min max
1 1000000

1 Rows(s) Affected
statement prepare time: 0.1423s, elapsed execute time: 0.0006s.
---------------------------------------------------------------------------
SAMPLES>>select min(item_code) "min",max(item_code) "max" from tab3
9. select min(item_code) "min",max(item_code) "max" from tab3

min max
000000000000001 000000000500000

1 Rows(s) Affected
statement prepare time: 0.1324s, elapsed execute time: 3.4683s.
---------------------------------------------------------------------------
SAMPLES>>
SAMPLES>>q

SAMPLES>halt
[oracle@pleco ˜]$

SAMPLES>d $System.SQL.SetAutoCommit(2)
SAMPLES>s rs=##class(%SQL.Statement).%ExecDirect(,"start transaction")
TL1:SAMPLES>s sql="insert into SQLUser.tab31 values(to_char(?,'FM099999999999999'),to_char((?#500000)+1,'FM0999999999'),repeat('*',250-length(to_char(?)))||to_char(?),0)"
TL1:SAMPLES>s stmt=##class(%SQL.Statement).%New() s stat=stmt.%Prepare(sql)
TL1:SAMPLES>f i=1:1:2000000 {s rs=stmt.%Execute(i,i,i,i)}
TL1:SAMPLES>s rs=##class(%SQL.Statement).%ExecDirect(,"commit")

SAMPLES>d $System.SQL.Shell()
SQL Command Line Shell
----------------------------------------------------

The command prefix is currently set to: <<nothing>>.
Enter q to quit, ? for help.
SAMPLES>>select count(1) from tab31
2. select count(1) from tab31

Aggregate_1
2000000

1 Rows(s) Affected
statement prepare time: 0.1349s, elapsed execute time: 6.0684s.
---------------------------------------------------------------------------
SAMPLES>>select min(item_code) "item_code(MIN)",max(item_code) "item_code(MAX)" from tab31
3. select min(item_code) "item_code(MIN)",max(item_code) "item_code(MAX)" from tab31

item_code(MIN) item_code(MAX)
000000000000001 000000002000000

1 Rows(s) Affected
statement prepare time: 0.1361s, elapsed execute time: 0.0010s.
---------------------------------------------------------------------------
SAMPLES>>select min(sub_item_code) "sub_item_code(MIN)",max(sub_item_code) "sub_item_code(MAX)" from tab31
4. select min(sub_item_code) "sub_item_code(MIN)",max(sub_item_code) "sub_item_code(MAX)" from tab31

sub_item_code(MIN) sub_item_code(MAX)
0000000001 0000500000

1 Rows(s) Affected
statement prepare time: 0.1391s, elapsed execute time: 6.7417s.
---------------------------------------------------------------------------
SAMPLES>>q
SAMPLES>

SAMPLES>d $System.SQL.SetAutoCommit(2)
SAMPLES>s rs=##class(%SQL.Statement).%ExecDirect(,"start transaction")
TL1:SAMPLES>s sql="insert into SQLUser.tab311 values(?,to_char((?#500000)+1,'FM0999999999'),repeat('*',250-length(to_char(?)))||to_char(?),0)"
TL1:SAMPLES>s stmt=##class(%SQL.Statement).%New() s stat=stmt.%Prepare(sql)
TL1:SAMPLES>f i=1:1:2000000 {s rs=stmt.%Execute(i,i,i,i)}
TL1:SAMPLES>s rs=##class(%SQL.Statement).%ExecDirect(,"commit")

SAMPLES>d $System.SQL.Shell()

SQL Command Line Shell
----------------------------------------------------

The command prefix is currently set to: <<nothing>>.
Enter q to quit, ? for help.
SAMPLES>>select count(1) from tab311
5. select count(1) from tab311

Aggregate_1
2000000

1 Rows(s) Affected
statement prepare time: 0.0009s, elapsed execute time: 3.7845s.
---------------------------------------------------------------------------
SAMPLES>>select min(sub_item_code) "sub_item_code(MIN)", max(sub_item_code) "sub_item_code(MAX)" from tab311
6. select min(sub_item_code) "sub_item_code(MIN)", max(sub_item_code) "sub_item_code(MAX)" from tab311

sub_item_code(MIN) sub_item_code(MAX)
0000000001 0000500000

1 Rows(s) Affected
statement prepare time: 0.1558s, elapsed execute time: 0.0004s.
---------------------------------------------------------------------------
SAMPLES>>q


本題からはずれるのですが... SQL使ってるとはいっても、ベースはMUMPSというかM言語だからね〜というお話を。。

tab3表及び主キー制約で作成された索引に対応するglobals。索引を見るとSparse Multidimensional Arrayをうまく利用しているのがよくわかる :)
Cachéの表や索引の実態はSparse Multidimensional Arrayなんだお。

1:      ^User.tab3D    =     1512812
2: ^User.tab3D(512813) = $lb("",1,"000000000000002","***************** ...中略... *******************************1",0,"00")
3: ^User.tab3D(512814) = $lb("",2,"000000000000003","***************** ...中略... *******************************2",0,"00")
4: ^User.tab3D(512815) = $lb("",3,"000000000000004","***************** ...中略... *******************************3",0,"00")
...以下略...

tab3表の主キー索引

1:      ^User.tab3I("tab3pk",1,512813)    =     ""
2: ^User.tab3I("tab3pk",2,512814) = ""
3: ^User.tab3I("tab3pk",3,512815) = ""
...以下略...

次は、tab31表と主キー索引

1:      ^User.tab31D    =     2000000
2: ^User.tab31D(1) = $lb("","000000000000001","0000000002","***************** ...中略... *************************1",0)
3: ^User.tab31D(2) = $lb("","000000000000002","0000000003","***************** ...中略... *************************2",0)
4: ^User.tab31D(3) = $lb("","000000000000003","0000000004","***************** ...中略... *************************3",0)
...以下略...


1:      ^User.tab31I("tab31pk"," 000000000000001",1)    =     ""
2: ^User.tab31I("tab31pk"," 000000000000002",2) = ""
3: ^User.tab31I("tab31pk"," 000000000000003",3) = ""
...以下略...


最後に、tab311表と主キー索引及び、非ユニーク索引に対応したSparse Multidimensional Arrayの内容

1:      ^User.tab311D    =     2000000
2: ^User.tab311D(1) = $lb("",1,"0000000002","********************************* ...中略... ************************1",0)
3: ^User.tab311D(2) = $lb("",2,"0000000003","********************************* ...中略... ************************2",0)
4: ^User.tab311D(3) = $lb("",3,"0000000004","********************************* ...中略... ************************3",0)
...以下略...

1:      ^User.tab311I("tab311ix"," 0000000001",500000)    =     ""
2: ^User.tab311I("tab311ix"," 0000000001",1000000) = ""
3: ^User.tab311I("tab311ix"," 0000000001",1500000) = ""
4: ^User.tab311I("tab311ix"," 0000000001",2000000) = ""
5: ^User.tab311I("tab311ix"," 0000000002",1) = ""
6: ^User.tab311I("tab311ix"," 0000000002",500001) = ""
7: ^User.tab311I("tab311ix"," 0000000002",1000001) = ""
8: ^User.tab311I("tab311ix"," 0000000002",1500001) = ""
9: ^User.tab311I("tab311ix"," 0000000003",2) = ""
10: ^User.tab311I("tab311ix"," 0000000003",500002) = ""
11: ^User.tab311I("tab311ix"," 0000000003",1000002) = ""
12: ^User.tab311I("tab311ix"," 0000000003",1500002) = ""
13: ^User.tab311I("tab311ix"," 0000000004",3) = ""
14: ^User.tab311I("tab311ix"," 0000000004",500003) = ""
15: ^User.tab311I("tab311ix"," 0000000004",1000003) = ""
16: ^User.tab311I("tab311ix"," 0000000004",1500003) = ""
...以下略...


実行するクエリはOracle/MySQL/PostgreSQLで実行したものと同じです。

select
t1.unique_id,
t1.item_code,
(
select
max(t3.unique_id)
from
tab31 t2 join tab311 t3
on
t2.sub_item_code = t3.sub_item_code
and t3.is_delete = 0
where
t2.item_code = t1.item_code
and t2.is_delete = 0
) current_sub_item
from
tab3 t1
where
t1.unique_id between 1 and 10000
and t1.is_delete = 0
and t1.status_code = '00'


以下、管理ポータルのSQL実行プラン表示で取得した実行計画とコスト。
Index Only AccessではないのでCacheのSQLの世界で表アクセスを意味するオペレーションである、Read Master mapがスカラー問合せ部分に現れている。
ちなみに、索引アクセスを意味するオペレーションは、Read index mapのようだ。

実行プランが以下に表示されます:
クエリ文字列

SELECT t1 . unique_id , t1 . item_code , ( SELECT MAX ( t3 . unique_id ) FROM tab31 t2 JOIN tab311 t3 ON t2 . sub_item_code = t3 . sub_item_code AND t3 .
is_delete = ? WHERE t2 . item_code = t1 . item_code AND t2 . is_delete = ? ) current_sub_item FROM tab3 t1 WHERE t1 . unique_id BETWEEN ? AND ? AND t1 .
is_delete = ? AND t1 . status_code = ?

クエリプラン
相対コスト = 74082

Call module B, which populates bitmap temp-file A.
Read bitmap temp-file A, looping on ID.
For each row:
Read master map SQLUser.tab3.IDKEY, using the given idkey value.
Output the row.

module B
Read index map SQLUser.tab3.tab3_pk, looping on unique_id (with a range condition) and ID.
For each row:
Add ID bit to bitmap temp-file A.

subquery
Call module E.
Determine subquery result.

module E
Read index map SQLUser.tab31.tab31_pk, using the given %SQLUPPER(item_code), and looping on ID.
For each row:
Read master map SQLUser.tab31.IDKEY, using the given idkey value.
Read index map SQLUser.tab311.tab311_ix, using the given %SQLUPPER(sub_item_code), and looping on ID.
For each row:
Read master map SQLUser.tab311.IDKEY, using the given idkey value.
Accumulate the max(unique_id).


では、Index Only Accessによるチューニング。 Covering Indexを2つ作成します。(Oracle/MySQL/PostgreSQLで作成した索引と同じ名称にしてあります)

[oracle@pleco ˜]$ csession cache -U samples

ノード: pleco.macdeoracle.JP インスタンス: CACHE

SAMPLES>d $System.SQL.Shell()
SQL Command Line Shell
----------------------------------------------------

The command prefix is currently set to: <<nothing>>.
Enter q to quit, ? for help.
SAMPLES>>create index tab31_demo_ix on tab31(item_code, is_delete, sub_item_code)
1. create index tab31_demo_ix on tab31(item_code, is_delete, sub_item_code)

0 Rows Affected
statement prepare time: 4.8277s, elapsed execute time: 9.6483s.
---------------------------------------------------------------------------
SAMPLES>>create index tab311_demo_ix on tab311(sub_item_code, is_delete, unique_id)
2. create index tab311_demo_ix on tab311(sub_item_code, is_delete, unique_id)

0 Rows Affected
statement prepare time: 0.0130s, elapsed execute time: 8.6777s.
---------------------------------------------------------------------------
SAMPLES>>

索引は正しく作成されています。(管理ポータルから確認した結果)
Tab31_indexes_index_only

Tab311_indexes_inde_only

お〜〜〜〜〜っ!。 CacheのSQLワールドでもIndex Only Accessになってる〜〜〜。 (ヒントのような仕組みはないようなのですが、狙い通りの索引が利用されていますね)
スカラー副問合せの実行計画から Read Master Map(表に対応するSparse Multidimensional Array)をアクセスする操作が消え、Read index Map(索引に対応するSparse Multidimensional Array)をアクセスする操作だけになっていることが確認できた。 :)

以下、管理ポータルの「SQL実行」>「実行計画」で取得した実行計画

クエリプラン
相対コスト = 74082

Call module B, which populates bitmap temp-file A.
Read bitmap temp-file A, looping on ID.
For each row:
Read master map SQLUser.tab3.IDKEY, using the given idkey value.
Output the row.

module B
Read index map SQLUser.tab3.tab3_pk, looping on unique_id (with a range condition) and ID.
For each row:
Add ID bit to bitmap temp-file A.

subquery
Call module E.
Determine subquery result.

module E
Read index map SQLUser.tab31.tab31_demo_ix, using the given %SQLUPPER(item_code) and is_delete, and looping on %SQLUPPER(sub_item_code) and ID.
For each row:
Read index map SQLUser.tab311.tab311_demo_ix, using the given %SQLUPPER(sub_item_code) and is_delete, and looping on unique_id and ID.
For each row:
Accumulate the max(unique_id).

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

2012年8月21日 (火)

Index Only Accessネタのおまけ

2012/10/13追記
MySQL(InnoDB)の主キーはClustered Indexなので主キーアクセスである場合はCovering indexは不要ですね。(^^;; 
PostgreSQL9.2のIndex-only scanですが、vacuumさえしっかりやっていればcovering indexを利用するようになることを確認。

前述の2点を後日追加予定です。



随分間があいてしまいました、m(_ _)m

Oracle以外でも多数の商用/OSS RDBMSでIndex Only Accessできるんですよね。
ということで、MySQL/PostgreSQLの実行計画ではどのように表示されるのか、Oracleのように索引だけ作れば勝ってにIndex Only Accessやってくれるのか?、などなど簡単に確かめてみました。(備忘録)

OracleのIndex Only Accessは以下のエントリを参考にしてください。
いん!、イン!、Index どっぷり Inde Only Access生活w - Oracle OpenWorld Unconference presented by JPOUG
JPOUG SET EVENTS 20120721 - 「(続)いん!、イン!、Index 大人の事情縛りのSQLチューニング」資料公開

今回使ったのは、MySQL 5.5.27/PostgreSQL 9.1.4そしてBeta阪ですが9.2 Beta4です。
環境はOracleが乗ってる環境と同じです。

MacBook Air late 2010 13inch 2GB (MacOS X Lion)
VirtualBox4.1.18 for MacOS X
GuestOS:CentOS5.8 x86

ちなみに、データ作りに時間を割けなかったので、クラスタリングファクターはどちらのも低めとなっています。実行計画上どのように見えるのか知りたかっただけなので. (^^;;;

MySQL 5.5.27

Oracleのデモでも使っていたスカラー副問合せで試してみました。最初は、Index Rancge Scanをグルグル。
この場合は索引、表をそれぞれアクセスします。

mysql> explain 
-> select
-> t1.unique_id,
-> t1.item_code,
-> (
-> select
-> max(t3.unique_id)
-> from
-> tab31 t2 join tab311 t3
-> on
-> t2.sub_item_code = t3.sub_item_code
-> and t3.is_delete = 0
-> where
-> t2.item_code = t1.item_code
-> and t2.is_delete = 0
-> ) current_sub_item
-> from
-> tab3 t1
-> where
-> t1.unique_id between 1 and 10000
-> and t1.is_delete = 0
-> and t1.status_code = '00'
-> ;
+----+--------------------+-------+--------+---------------+-----------+---------+------------------------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-------+--------+---------------+-----------+---------+------------------------+-------+-------------+
| 1 | PRIMARY | t1 | range | PRIMARY | PRIMARY | 5 | NULL | 20108 | Using where |
| 2 | DEPENDENT SUBQUERY | t2 | eq_ref | PRIMARY | PRIMARY | 45 | scott.t1.item_code | 1 | Using where |
| 2 | DEPENDENT SUBQUERY | t3 | ref | tab311_ix | tab311_ix | 31 | scott.t2.sub_item_code | 1 | Using where |
+----+--------------------+-------+--------+---------------+-----------+---------+------------------------+-------+-------------+
3 rows in set (0.00 sec)

mysql>


Index Only Accessさせた場合の実行計画です。
Extra列に Using indexと出ていればIndex Only Accessになっています。
ちなみに、Oracleとちがって勝ってにCovering Indexを使ってくれなかったのでSQLヒントを使っています。Oracleのヒントと随分書き方違うので戸惑うよ(^^;;;

mysql> explain
-> select
-> t1.unique_id,
-> t1.item_code,
-> (
-> select
-> max(t3.unique_id)
-> from
-> tab31 t2 ignore index(primary) join tab311 t3 ignore index(tab311_ix)
-> on
-> t2.sub_item_code = t3.sub_item_code
-> and t3.is_delete = 0
-> where
-> t2.item_code = t1.item_code
-> and t2.is_delete = 0
-> ) current_sub_item
-> from
-> tab3 t1
-> where
-> t1.unique_id between 1 and 10000
-> and t1.is_delete = 0
-> and t1.status_code = '00'
-> ;
+----+--------------------+-------+-------+----------------+----------------+---------+------------------------------+-------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-------+-------+----------------+----------------+---------+------------------------------+-------+--------------------------+
| 1 | PRIMARY | t1 | range | PRIMARY | PRIMARY | 5 | NULL | 20108 | Using where |
| 2 | DEPENDENT SUBQUERY | t2 | ref | tab31_demo_ix | tab31_demo_ix | 47 | scott.t1.item_code,const | 10000 | Using where; Using index |
| 2 | DEPENDENT SUBQUERY | t3 | ref | tab311_demo_ix | tab311_demo_ix | 33 | scott.t2.sub_item_code,const | 10000 | Using where; Using index |
+----+--------------------+-------+-------+----------------+----------------+---------+------------------------------+-------+--------------------------+
3 rows in set (0.00 sec)

mysql>


PostgreSQL 9.1

PostgreSQL9.1まではIndex Only Accessが実装されていないとのこと。(実は今年になってはじめて知ったことなのですが、その時は、「え?! そうなの?」って感じでした)

※実行時間のバラツキがあるため実行統計情報から表や索引ブロックアクセス状況を確認しています。

scott=> select * from pg_statio_user_tables where relname in ('tab31','tab311');
relid | schemaname | relname | heap_blks_read | heap_blks_hit | idx_blks_read | idx_blks_hit | toast_blks_read | toast_blks_hit | tidx_blks_read | tidx_blks_hit
-------+------------+---------+----------------+---------------+---------------+--------------+-----------------+----------------+----------------+---------------
16401 | public | tab311 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
16395 | public | tab31 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0

scott=> select * from pg_statio_user_indexes where relname in ('tab31','tab311');
relid | indexrelid | schemaname | relname | indexrelname | idx_blks_read | idx_blks_hit
-------+------------+------------+---------+----------------+---------------+--------------
16401 | 16411 | public | tab311 | tab311_pk | 0 | 0
16395 | 16454 | public | tab31 | tab31_demo_ix | 0 | 0
16401 | 16455 | public | tab311 | tab311_demo_ix | 0 | 0

scott=> explain analyze verbose
scott-> select
scott-> t1.unique_id,
scott-> t1.item_code,
scott-> (
scott(> select
scott(> max(t3.unique_id)
scott(> from
scott(> tab31 t2 join tab311 t3
scott(> on
scott(> t2.sub_item_code = t3.sub_item_code
scott(> and t3.is_delete = 0
scott(> where
scott(> t2.item_code = t1.item_code
scott(> and t2.is_delete = 0
scott(> ) current_sub_item
scott-> from
scott-> tab3 t1
scott-> where
scott-> t1.unique_id between 1 and 10000
scott-> and t1.is_delete = 0
scott-> and t1.status_code = '00'
scott-> ;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------------------
Index Scan using tab3_pk on public.tab3 t1 (cost=0.00..2050286.39 rows=10326 width=22) (actual time=45.613..6560.751 rows=10000 loops=1)
Output: t1.unique_id, t1.item_code, (SubPlan 1)
Index Cond: ((t1.unique_id >= 1::numeric) AND (t1.unique_id <= 10000::numeric))
Filter: ((t1.is_delete = 0::numeric) AND (t1.status_code = '00'::bpchar))
SubPlan 1
-> Aggregate (cost=198.47..198.48 rows=1 width=6) (actual time=0.650..0.651 rows=1 loops=10000)
Output: max(t3.unique_id)
-> Nested Loop (cost=0.00..198.46 rows=4 width=6) (actual time=0.143..0.621 rows=40 loops=10000)
Output: t3.unique_id
-> Index Scan using tab31_pk on public.tab31 t2 (cost=0.00..8.58 rows=1 width=11) (actual time=0.010..0.011 rows=1 loops=10000)
Output: t2.item_code, t2.sub_item_code, t2.data, t2.is_delete
Index Cond: (t2.item_code = t1.item_code)
Filter: (t2.is_delete = 0::numeric)
-> Index Scan using tab311_ix on public.tab311 t3 (cost=0.00..189.27 rows=49 width=17) (actual time=0.130..0.565 rows=40 loops=10000)
Output: t3.unique_id, t3.sub_item_code, t3.data, t3.is_delete
Index Cond: (t3.sub_item_code = t2.sub_item_code)
Filter: (t3.is_delete = 0::numeric)
Total runtime: 6566.636 ms
(18 行)

時間: 6618.795 ms
scott=>

適切な索引を利用しているのでIndex Unique/Range Scanとテーブルブロックへのアクセスが確認できます。(当然といえば当然ですよね)

scott=> select * from pg_statio_user_tables where relname in ('tab31','tab311');
relid | schemaname | relname | heap_blks_read | heap_blks_hit | idx_blks_read | idx_blks_hit | toast_blks_read | toast_blks_hit | tidx_blks_read | tidx_blks_hit
-------+------------+---------+----------------+---------------+---------------+--------------+-----------------+----------------+----------------+---------------
16401 | public | tab311 | 15389 | 36920 | 1983 | 30033 | 0 | 0 | 0 | 0
16395 | public | tab31 | 401 | 9599 | 64 | 30057 | 0 | 0 | 0 | 0

scott=> select * from pg_statio_user_indexes where relname in ('tab31','tab311');
relid | indexrelid | schemaname | relname | indexrelname | idx_blks_read | idx_blks_hit
-------+------------+------------+---------+----------------+---------------+--------------
16401 | 16411 | public | tab311 | tab311_pk | 0 | 0
16395 | 16454 | public | tab31 | tab31_demo_ix | 64 | 30057
16401 | 16455 | public | tab311 | tab311_demo_ix | 1983 | 30033

Index Only AccessさせるためのCovering Index(FAT index)を作ってみましたが、Index Range/Unique Scanのままですね。
ちなみに、PostgreSQLってOracleやMySQLのようなSQLヒントがありません。(あったらごめんなさい。調べきれてないだけです。m(_ _)m
Covering Indexだけを残して邪魔な索引を削除することでCovering indexをアクセスさせています。

scott=> select * from pg_statio_user_tables where relname in ('tab31','tab311');
relid | schemaname | relname | heap_blks_read | heap_blks_hit | idx_blks_read | idx_blks_hit | toast_blks_read | toast_blks_hit | tidx_blks_read | tidx_blks_hit
-------+------------+---------+----------------+---------------+---------------+--------------+-----------------+----------------+----------------+---------------
16401 | public | tab311 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
16395 | public | tab31 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0

scott=> select * from pg_statio_user_indexes where relname in ('tab31','tab311');
relid | indexrelid | schemaname | relname | indexrelname | idx_blks_read | idx_blks_hit
-------+------------+------------+---------+----------------+---------------+--------------
16401 | 16411 | public | tab311 | tab311_pk | 0 | 0
16395 | 16454 | public | tab31 | tab31_demo_ix | 0 | 0
16401 | 16455 | public | tab311 | tab311_demo_ix | 0 | 0


scott=> explain analyze verbose
scott-> select
scott-> t1.unique_id,
scott-> t1.item_code,
scott-> (
scott(> select
scott(> max(t3.unique_id)
scott(> from
scott(> tab31 t2 join tab311 t3
scott(> on
scott(> t2.sub_item_code = t3.sub_item_code
scott(> and t3.is_delete = 0
scott(> where
scott(> t2.item_code = t1.item_code
scott(> and t2.is_delete = 0
scott(> ) current_sub_item
scott-> from
scott-> tab3 t1
scott-> where
scott-> t1.unique_id between 1 and 10000
scott-> and t1.is_delete = 0
scott-> and t1.status_code = '00'
scott-> ;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------------
Index Scan using tab3_pk on public.tab3 t1 (cost=0.00..2109597.62 rows=10326 width=22) (actual time=0.677..1808.056 rows=10000 loops=1)
Output: t1.unique_id, t1.item_code, (SubPlan 1)
Index Cond: ((t1.unique_id >= 1::numeric) AND (t1.unique_id <= 10000::numeric))
Filter: ((t1.is_delete = 0::numeric) AND (t1.status_code = '00'::bpchar))
SubPlan 1
-> Aggregate (cost=204.21..204.22 rows=1 width=6) (actual time=0.176..0.176 rows=1 loops=10000)
Output: max(t3.unique_id)
-> Nested Loop (cost=0.00..204.20 rows=4 width=6) (actual time=0.024..0.137 rows=40 loops=10000)
Output: t3.unique_id
-> Index Scan using tab31_demo_ix on public.tab31 t2 (cost=0.00..8.76 rows=1 width=11) (actual time=0.007..0.009 rows=1 loops=10000)
Output: t2.item_code, t2.sub_item_code, t2.data, t2.is_delete
Index Cond: ((t2.item_code = t1.item_code) AND (t2.is_delete = 0::numeric))
-> Index Scan using tab311_demo_ix on public.tab311 t3 (cost=0.00..194.84 rows=49 width=17) (actual time=0.013..0.068 rows=40 loops=10000)
Output: t3.unique_id, t3.sub_item_code, t3.data, t3.is_delete
Index Cond: ((t3.sub_item_code = t2.sub_item_code) AND (t3.is_delete = 0::numeric))
Total runtime: 4762.819 ms
(16 行)

時間: 4855.100 ms
scott=>

実行計画上、Filterはなくなりましたが、表ブロックもアクセスしているのでIndex Only Accessにはなっていません。(ほんとにIndex Only AccessというかIndex-only Scanは9.1までは実装されていないんですね。)

scott=> select * from pg_statio_user_tables where relname in ('tab31','tab311');
relid | schemaname | relname | heap_blks_read | heap_blks_hit | idx_blks_read | idx_blks_hit | toast_blks_read | toast_blks_hit | tidx_blks_read | tidx_blks_hit
-------+------------+---------+----------------+---------------+---------------+--------------+-----------------+----------------+----------------+---------------
16401 | public | tab311 | 15390 | 36919 | 1982 | 30034 | 0 | 0 | 0 | 0
16395 | public | tab31 | 401 | 9599 | 62 | 30059 | 0 | 0 | 0 | 0

scott=> select * from pg_statio_user_indexes where relname in ('tab31','tab311');
relid | indexrelid | schemaname | relname | indexrelname | idx_blks_read | idx_blks_hit
-------+------------+------------+---------+----------------+---------------+--------------
16401 | 16411 | public | tab311 | tab311_pk | 0 | 0
16395 | 16454 | public | tab31 | tab31_demo_ix | 62 | 30059
16401 | 16455 | public | tab311 | tab311_demo_ix | 1982 | 30034

PostgreSQL 9.2 Beta4

最後に、PostgreSQL 9.2 Beta4 です。このリリースではPostgreSQLでは初めて、Index Only Access(マニュアルでは Index-only Scanと記載されています)
PostgreSQL方面の方がIndex-only Scanと書くかたが多いのもこの影響でしょうね。日本人からするとIndex Only AccessよりIndex Only Scanの方が発音しやすい?(私だけか?)気がしますw

scott=> explain analyze verbose
scott-> select
scott-> t1.unique_id,
scott-> t1.item_code,
scott-> (
scott(> select
scott(> max(t3.unique_id)
scott(> from
scott(> tab31 t2 join tab311 t3
scott(> on
scott(> t2.sub_item_code = t3.sub_item_code
scott(> and t3.is_delete = 0
scott(> where
scott(> t2.item_code = t1.item_code
scott(> and t2.is_delete = 0
scott(> ) current_sub_item
scott-> from
scott-> tab3 t1
scott-> where
scott-> t1.unique_id between 1 and 10000
scott-> and t1.is_delete = 0
scott-> and t1.status_code = '00'
scott-> ;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------------------
Index Scan using tab3_pk on public.tab3 t1 (cost=0.00..1925706.85 rows=9421 width=22) (actual time=41.205..6202.096 rows=10000 loops=1)
Output: t1.unique_id, t1.item_code, (SubPlan 1)
Index Cond: ((t1.unique_id >= 1::numeric) AND (t1.unique_id <= 10000::numeric))
Filter: ((t1.is_delete = 0::numeric) AND (t1.status_code = '00'::bpchar))
SubPlan 1
-> Aggregate (cost=204.32..204.33 rows=1 width=6) (actual time=0.613..0.614 rows=1 loops=10000)
Output: max(t3.unique_id)
-> Nested Loop (cost=0.00..204.31 rows=4 width=6) (actual time=0.110..0.584 rows=40 loops=10000)
Output: t3.unique_id
-> Index Scan using tab31_pk on public.tab31 t2 (cost=0.00..11.35 rows=1 width=11) (actual time=0.012..0.013 rows=1 loops=10000)
Output: t2.item_code, t2.sub_item_code, t2.data, t2.is_delete
Index Cond: (t2.item_code = t1.item_code)
Filter: (t2.is_delete = 0::numeric)
-> Index Scan using tab311_ix on public.tab311 t3 (cost=0.00..192.47 rows=49 width=17) (actual time=0.095..0.525 rows=40 loops=10000)
Output: t3.unique_id, t3.sub_item_code, t3.data, t3.is_delete
Index Cond: (t3.sub_item_code = t2.sub_item_code)
Filter: (t3.is_delete = 0::numeric)
Total runtime: 6207.935 ms
(18 行)

時間: 6313.789 ms
scott=>

9.2でもIndex Only Accessでなければ表ブロックもアクセスしますよね〜。そりゃそうだ。:)

scott=> select * from pg_statio_user_tables where relname in ('tab31','tab311');
relid | schemaname | relname | heap_blks_read | heap_blks_hit | idx_blks_read | idx_blks_hit | toast_blks_read | toast_blks_hit | tidx_blks_read | tidx_blks_hit
-------+------------+---------+----------------+---------------+---------------+--------------+-----------------+----------------+----------------+---------------
16404 | public | tab311 | 15390 | 36919 | 1649 | 29996 | 0 | 0 | 0 | 0
16398 | public | tab31 | 401 | 9599 | 39 | 30037 | 0 | 0 | 0 | 0

scott=> select * from pg_statio_user_indexes where relname in ('tab31','tab311');
relid | indexrelid | schemaname | relname | indexrelname | idx_blks_read | idx_blks_hit
-------+------------+------------+---------+--------------+---------------+--------------
16404 | 16414 | public | tab311 | tab311_pk | 0 | 0
16398 | 16432 | public | tab31 | tab31_pk | 39 | 30037
16404 | 16434 | public | tab311 | tab311_ix | 1649 | 29996

いよいよ、PostgreSQL9.2 Beta4のIndex-only Scanの番です。:)
お〜〜〜っ、 Index Scan using xxxxという部分が、Index Only Scan using xxxxとなっています! が、 Heap Fetches 400000とある? どゆこと?

scott=> explain analyze verbose
scott-> select
scott-> t1.unique_id,
scott-> t1.item_code,
scott-> (
scott(> select
scott(> max(t3.unique_id)
scott(> from
scott(> tab31 t2 join tab311 t3
scott(> on
scott(> t2.sub_item_code = t3.sub_item_code
scott(> and t3.is_delete = 0
scott(> where
scott(> t2.item_code = t1.item_code
scott(> and t2.is_delete = 0
scott(> ) current_sub_item
scott-> from
scott-> tab3 t1
scott-> where
scott-> t1.unique_id between 1 and 10000
scott-> and t1.is_delete = 0
scott-> and t1.status_code = '00'
scott-> ;

QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
Index Scan using tab3_pk on public.tab3 t1 (cost=0.00..2000896.05 rows=9421 width=22) (actual time=0.410..1728.699 rows=10000 loops=1)
Output: t1.unique_id, t1.item_code, (SubPlan 1)
Index Cond: ((t1.unique_id >= 1::numeric) AND (t1.unique_id <= 10000::numeric))
Filter: ((t1.is_delete = 0::numeric) AND (t1.status_code = '00'::bpchar))
SubPlan 1
-> Aggregate (cost=212.30..212.31 rows=1 width=6) (actual time=0.168..0.168 rows=1 loops=10000)
Output: max(t3.unique_id)
-> Nested Loop (cost=0.00..212.29 rows=4 width=6) (actual time=0.023..0.131 rows=40 loops=10000)
Output: t3.unique_id
-> Index Only Scan using tab31_demo_ix on public.tab31 t2 (cost=0.00..13.13 rows=1 width=11) (actual time=0.006..0.007 rows=1 loops=10000)
Output: t2.item_code, t2.is_delete, t2.sub_item_code
Index Cond: ((t2.item_code = t1.item_code) AND (t2.is_delete = 0::numeric))
Heap Fetches: 10000
-> Index Only Scan using tab311_demo_ix on public.tab311 t3 (cost=0.00..198.67 rows=49 width=17) (actual time=0.013..0.066 rows=40 loops=10000)
Output: t3.sub_item_code, t3.is_delete, t3.unique_id
Index Cond: ((t3.sub_item_code = t2.sub_item_code) AND (t3.is_delete = 0::numeric))
Heap Fetches: 400000
Total runtime: 5412.612 ms
(18 行)

時間: 5465.400 ms
scott=>

やはり! Heap Fetchesとあるのでおかしいと思っていたら...orz. なんで表ブロックアクセスしてんの〜〜〜っ。実行計画は、Index Only Scan。謎。

scott=> select * from pg_statio_user_tables where relname in ('tab31','tab311');
relid | schemaname | relname | heap_blks_read | heap_blks_hit | idx_blks_read | idx_blks_hit | toast_blks_read | toast_blks_hit | tidx_blks_read | tidx_blks_hit
-------+------------+---------+----------------+---------------+---------------+--------------+-----------------+----------------+----------------+---------------
16404 | public | tab311 | 15389 | 36920 | 1983 | 30033 | 0 | 0 | 0 | 0
16398 | public | tab31 | 401 | 9599 | 64 | 30057 | 0 | 0 | 0 | 0

scott=> select * from pg_statio_user_indexes where relname in ('tab31','tab311');
relid | indexrelid | schemaname | relname | indexrelname | idx_blks_read | idx_blks_hit
-------+------------+------------+---------+----------------+---------------+--------------
16404 | 16414 | public | tab311 | tab311_pk | 0 | 0
16398 | 16435 | public | tab31 | tab31_demo_ix | 64 | 30057
16404 | 16436 | public | tab311 | tab311_demo_ix | 1983 | 30033


何故、Inde Only Scanなのに表ブロックをアクセスしてしまうのか、わかった〜〜〜っ、と思う。(vacuum analyze が必要らしい。ちなみに前述の結果はデータをINSERTし、analyzeコマンドだけを実施した状態だった)

気持ちを落ち着けて〜〜〜!

[oracle@leaffish ˜]$ psql -U oracle scott
タイミングは on です。
psql (9.2beta4)
"help" でヘルプを表示します.

scott=# vacuum analyze tab311;
scott=# vacuum analyze tab31;


こんどこそ! できた〜〜〜〜っ!と思う。
Heap Fetchesも0だし、表ブロックへのアクセスもほぼない。ほぼない。大切なので2度書きました。表ブロックへのアクセスは0にはならないようです。今のところ。こまけーことはいいんだよ的で、ワイルド。 :) 数ブロックアクセスしているのはどのようなブロックなのでしょうね

scott=> explain analyze verbose
scott-> select
scott-> t1.unique_id,
scott-> t1.item_code,
scott-> (
scott(> select
scott(> max(t3.unique_id)
scott(> from
scott(> tab31 t2 join tab311 t3
scott(> on
scott(> t2.sub_item_code = t3.sub_item_code
scott(> and t3.is_delete = 0
scott(> where
scott(> t2.item_code = t1.item_code
scott(> and t2.is_delete = 0
scott(> ) current_sub_item
scott-> from
scott-> tab3 t1
scott-> where
scott-> t1.unique_id between 1 and 10000
scott-> and t1.is_delete = 0
scott-> and t1.status_code = '00'
scott-> ;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
Index Scan using tab3_pk on public.tab3 t1 (cost=0.00..188801.90 rows=9921 width=22) (actual time=0.255..1116.525 rows=10000 loops=1)
Output: t1.unique_id, t1.item_code, (SubPlan 1)
Index Cond: ((t1.unique_id >= 1::numeric) AND (t1.unique_id <= 10000::numeric))
Filter: ((t1.is_delete = 0::numeric) AND (t1.status_code = '00'::bpchar))
SubPlan 1
-> Aggregate (cost=18.95..18.96 rows=1 width=6) (actual time=0.108..0.109 rows=1 loops=10000)
Output: max(t3.unique_id)
-> Nested Loop (cost=0.00..18.94 rows=4 width=6) (actual time=0.019..0.081 rows=40 loops=10000)
Output: t3.unique_id
-> Index Only Scan using tab31_demo_ix on public.tab31 t2 (cost=0.00..9.13 rows=1 width=11) (actual time=0.005..0.005 rows=1 loops=10000)
Output: t2.item_code, t2.is_delete, t2.sub_item_code
Index Cond: ((t2.item_code = t1.item_code) AND (t2.is_delete = 0::numeric))
Heap Fetches: 0
-> Index Only Scan using tab311_demo_ix on public.tab311 t3 (cost=0.00..9.32 rows=49 width=17) (actual time=0.012..0.036 rows=40 loops=10000)
Output: t3.sub_item_code, t3.is_delete, t3.unique_id
Index Cond: ((t3.sub_item_code = t2.sub_item_code) AND (t3.is_delete = 0::numeric))
Heap Fetches: 0
Total runtime: 1121.140 ms
(18 行)

時間: 1123.194 ms

scott=> select * from pg_statio_user_tables where relname in ('tab31','tab311');
relid | schemaname | relname | heap_blks_read | heap_blks_hit | idx_blks_read | idx_blks_hit | toast_blks_read | toast_blks_hit | tidx_blks_read | tidx_blks_hit
-------+------------+---------+----------------+---------------+---------------+--------------+-----------------+----------------+----------------+---------------
16404 | public | tab311 | 0 | 3 | 0 | 32015 | 0 | 0 | 0 | 0
16398 | public | tab31 | 0 | 1 | 0 | 30120 | 0 | 0 | 0 | 0

scott=> select * from pg_statio_user_indexes where relname in ('tab31','tab311');
relid | indexrelid | schemaname | relname | indexrelname | idx_blks_read | idx_blks_hit
-------+------------+------------+---------+----------------+---------------+--------------
16404 | 16414 | public | tab311 | tab311_pk | 0 | 0
16398 | 16421 | public | tab31 | tab31_demo_ix | 0 | 30120
16404 | 16422 | public | tab311 | tab311_demo_ix | 0 | 32015




参考:
INDEX FULL SCANを狙う - MySQL Casual Advent Calendar 2011
Covering Index と self-join と MySQL
How are index-only scans implemented in InnoDB
PostgreSQL 9.2 highlight: Index-only scans
PostgreSQLアーキテクチャ入門(INSIGHT OUT 2011)

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

2011年11月 1日 (火)

鬼熱かった! :: Insight out 2011- DB tech showcase

書くのおそくなっちゃいました m(_ _)m

10月19日〜21日に開催されたInsight out 2011- DB tech showcase
に、つまみ食いながらなんとか参加し、インサイトテクノロジーさんの鬼熱い魂を感じてきた :)

無理矢理空き時間作って参加したセッションは以下の通り。

  • Deep Dive into Oracle Database Patch (Oracle) - 諸橋渉
  • Why Why is probably the right answer (Oracle) - Tom Kyte
  • Rac Buffer Sharingの仕組み (Oracle) - 山下正
  • Effective Indexing (Oracle) - Tom Kyte
  • New challenges Information security technologies are facing (others) - David Maman
  • Developer and Indexes (Oracle) - Anjo Kolk

MySQLとかPostgreSQLとかOSSなのはOSCとかでも聴けるかなーと思いきづいたらOracle中心だったw

Effective Indexing/Developer and Indexes というセッションは予想以上だった、Indexを理解してるのって重要だよなーと改めて感じたセッションだった。

Tom Kyteさんが紹介していた書籍、「Relational Database Index Design and the Optimizers」


鬼熱い語りの山下さんのセッション、前回のOOWのUnconferenceの続編か?と思わせるような諸橋さんのセッション、つい引き込まれちゃいましたよ:)

参加者やスピーカが鬼熱いエンジニアであることは間違いないが、何と言っても、世界中からデータベースに関わる凄い方々を集めてしまうインサイトテクノロジーさんが一番、鬼熱いんじゃないかと感じた3日間だった。

来年も開催して頂きたいイベントだ。


Img_2299


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

2009年12月10日 (木)

Firebird徹底入門が発売されたので...

"待望の『Firebird徹底入門』本日発売!"とのことで。このブログでネタに使っている各データベース関連書籍など。。


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

2009年8月 8日 (土)

第18回オープンソーステクノロジー勉強会 - MySQLハッキングの手引き

第18回オープンソーステクノロジー勉強会 - MySQLハッキングの手引きに参加してきた。
定員60名だったようだがそれ以上いたんじゃないかな...(人数が多かったらしく抽選で参加者が選ばれたようだが。。。)
MySQLハッキングの手引きということで入門的な内容だったようだがMySQLのソースを見た事がない私にはなんのことやらってところは多かったものの、ニンマリしてしまうようなデモやら話やら....松信さんのマシンガントークで時間内に終わることを想定していた私は見事に裏切られた(時間オーバーしても長いとは感じませんでしたが)。
おもしろいテーマでした。時間があったらプラグインなんか作ってみようか思ってしまうぐらいだから。。資料は公開されるということなので楽しみにしています。

前回参加したときは懇親会には不参加だったが今回は最後までいましたよ〜〜。:)

Oracleネタ以外がつづいてますが、あしからず。。。ネタ仕込み中なので・・・



第18回オープンソーステクノロジー勉強会 −開催のご報告− GREE Labs

セミナーのアジェンダ

・MySQLアーキテクチャ
・ソースコード入手とビルド方法
・デバッグ方法
・プラグイン開発方法(デモ有り)
・本体拡張方法(デモ有り)
・本家へのコントリビュートの方法

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

2009年5月22日 (金)

DB2 で PL/SQL

DB2新版はPL/SQL対応、Oracleユーザーの移行狙う@ ITmedia

へぇ〜、それじゃ、昨日作ったケンブリッジ関数もDB2 9.7で動作するようになるのか〜〜。へぇ〜。mod_plsqlというかPL/SQL gatewayはどうなんだろうか?、Oracleが提供しているPL/SQLパッケージも対応しているのだろうか? 機会があったら質問しておこうっと。

できれば他のRDBMSでもやってくれるとありがたいかも...

PL/SQL : Write Once Run Any RDBMS なんてね。

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

2009年5月11日 (月)

Cache' デベロッパーズガイドを頂きました。m(_ _)m

先月の今頃だが、[CodeZine_News号外 2009-04-09]オブジェクトDB Caché入門書プレゼントという案内が来ていたので、いつものノリで応募していたのだが、プレゼントに当選したようで、Caché デベロッパーズガイドが本日届いた。ありがとうございました。

(最近よく当選するんだよな〜、くじ運は悪いのに・・・)

Mac で Oracleな当ブログですが過去、Cachéネタも幾つかあったりします。:)

10日後は何日?、翌月末日って何日?
Mac de Caché というか MUMPS というか Objectscript か



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

2009年1月26日 (月)

10日後は何日?、翌月末日って何日?

ichii386さん「相対的な日付って」記事に背骨というか脊髄反応的にコメントした勢いで、今日の10日後は何日?翌月末日って何日?の算出を幾つかやってみた。(「オリジナルの記事は今月末を求めているんですけど・・・・」・・・・ハイ、私が読み間違えて”翌月末”と勘違いしてました。今気付いたよ。w)

なんでgnuとphpだけなの? という突っ込みはなしで…。
なんでFirebirdが無いのかとか、CachéでSQLを使わないでMUMPSというかM言語というかCaché ObjectScriptなのかとか、Oracle11gなのに、MySQLは5.0PostgreSQLは7.4.9なのかとか、というツッコミはなしで...w

前提:
今日は1月24日として、10日後、翌月末日を算出します。

まずはPowerPC版のは古いのしかなかったのでCaché 5.2 for MacOSX(PowerPC)
MUMPS(M言語)がCachéで拡張?されてObjectiveになっちゃってObjectScriptと呼ばれているのには少々戸惑うけど、そこは昔取った杵柄。SQLも使えるけどM言語の方が作り易かったので。。w
ObjectScriptだと日付レベルで何日前とか何日後という計算は簡単なのだが、何ヶ月後とかいう計算は面倒なので。
(算出方法は翌々月の1日の前日が翌月末という考え方です。)

G5Server:˜ discus$ csession cache -U user

USER>
USER>w !,$zversion

Cache for UNIX (Mac OS X/32-bit) 5.2 (Build 329U_su) Wed Jun 21 2006 11:29:29 EDT
USER>
USER>
USER>w !,$zd($h+10,3)

2009-02-03
USER>s now=$h, y=$e($zd(now),7,10), m=$e($zd(now),1,2) w !,$zd($zdh($s(m<11:y_m+2_"01", m>10:y+1_m-10_"01"),5)-1,3)

2009-02-28
USER>
USER>halt
G5Server:˜ discus$

次は、Oracle11g EE 11.1.0.6.0 for Linux(x86)
OracleのSQLだとlast_day()や期間リテラルで簡単に算出できる。お気楽モード :-)

G5Server:˜ discus$ sqlplus /nolog

SQL*Plus: Release 10.1.0.3.0 - Production on 土 1月 24 13:53:33 2009

Copyright (c) 1982, 2004, Oracle. All rights reserved.

> conn scott/tiger@lampeye
接続されました。
SCOTT> select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - Production
PL/SQL Release 11.1.0.6.0 - Production
CORE 11.1.0.6.0 Production
TNS for Linux: Version 11.1.0.6.0 - Production
NLSRTL Version 11.1.0.6.0 - Production

SCOTT>
SCOTT> alter session set nls_date_format = 'yyyy-mm-dd';

セッションが変更されました。

SCOTT> select sysdate + interval '10' day from dual;

SYSDATE+IN
----------
2009-02-03

SCOTT> select last_day(sysdate + interval '1' month) from dual;

LAST_DAY(S
----------
2009-02-28

SCOTT>
SCOTT> exit
Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing optionsとの接続が切断されました。
G5Server:˜ discus$

お次は、MySQL Community Server 5.0.67 for MacOSX(PowerPC)版
MySQL5.0でもOracleと同様にlast_day()と期間リテラルだけで算出できます。こちらもOracle同様、余計なことを悩まなくてすみますね。(^^)

G5Server:˜ discus$ mysql --version
mysql Ver 14.12 Distrib 5.0.67, for apple-darwin8.11.0 (powerpc) using readline 5.1
G5Server:˜ discus$ mysql -u scott -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 177
Server version: 5.0.67 MySQL Community Server (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> select curdate() + interval 10 day;
+-----------------------------+
| curdate() + interval 10 day |
+-----------------------------+
| 2009-02-03 |
+-----------------------------+
1 row in set (0.00 sec)

mysql> select last_day(curdate() + interval 1 month);
+----------------------------------------+
| last_day(curdate() + interval 1 month) |
+----------------------------------------+
| 2009-02-28 |
+----------------------------------------+
1 row in set (0.00 sec)

mysql>
mysql> exit
Bye
G5Server:˜ discus$

最後にPosgreSQL 7.4.9 for MacOSX(PowerPC)版
10日後は期間リテラルで単純に算出可能だが、OracleやMySQLとは異なりlast_day()のような関数が無い(マニュアルをみたけど該当する関数が見当たらない)ので翌々月1日の前日で算出してみた。

G5Server:˜ discus$ 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=# select version();
version
-------------------------------------------------------------------------------------------------------------------------
PostgreSQL 7.4.9 on powerpc-apple-darwin8.3.0, compiled by GCC gcc (GCC) 3.3 20030304 (Apple Computer, Inc. build 1809)
(1 row)

postgresql749=# select cast(current_date + interval '10 day' as date);
date
------------
2009-02-03
(1 row)

postgresql749=# select cast(to_date(to_char(current_date + interval'2 months','yyyymm')||'01','yyyymmdd') - interval '1 day' as date);
date
------------
2009-02-28
(1 row)


postgresql749=# \q
G5Server:˜ discus$


CachéではObjectScript(M言語)を使ったので脇に置いといて、他の3つのデータベースのSQLでは期間リテラル(interval)の書き方が微妙に異なる点は知っておいたほうがいいかも。


今日も息子は保育園でバイバイせず結構泣いてた、最近、保育園にくるとパパもママもSee Ya! といっていなくなってしまうことに気付いた模様。いずれ慣れるだろうけど。。

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

2008年10月31日 (金)

MySQL User Conference Tokyo 2008(二日目)

今日はMySQL User Conference 2008の2日目に参加してきました。
(iPhone Tech Talkとバッディングしていて昨日は参加できなかったので)

その会場で、私が初めてMySQLとPostgreSQLを仕事として使った際にお世話になった方々と再会。お元気そうでなによりでした。(^^)

ところでココログさん最初はPostgreSQLだったのですね、全く知らなかった。しかも今はMySQLだということも知らなかったよ。。移行作業の経緯を知って、あ、あのとき、裏ではそんな事やっていたのか〜〜〜〜〜と、遠い目。

ココログさん(というかSix Apartさんかな)、お疲れさまでした。


Img_0108

懇親会会場では、みなさんお腹減っていたようで、あっという間に・・・・

Img_0110

近くに抽選会でサーバに当選した方が居たので目録だけ撮ってみました。

Img_0113


いつものように頂いたノベルティーはブログ de ノベルティにて。

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

2008年10月23日 (木)

Mac de Caché というか MUMPS というか Objectscript か

Cachéはむか〜〜し、むか〜し日本DEC時代に関わっていたDSM-11やVAX/DSMようするにMUMPSを祖先に持つ。今ではSQL/トランザクション制御/ODBCもサポートしているというからOracle11gと他のデータベース間でOracle Generic Connectivityで遊ぶのも面白いかな・・・ということで試しにインストール。
そういえばCodezineで記事を書いている佐藤さんって日本DEC時代に担当していたディストリクトは違うけどDSM-11やVAX/DSMを担当されていた方だよな〜多分、随分前なので多分としか書けないけど。近いうちに確認できるだろうけど。(^^)


Cachéのéをタイプするためにフランス語タイプできるようにしちゃったし。 w

Cache_001

Cache_002

Cache_003

Cache_004

Cache_005

Cache_006

Cache_007

Cache_008

Cache_009

Cache_010

サポートされているプラットフォームの一覧をみるとPowerPC版MacOSXはTigerまでということになっている。
ちなみに、x86版MacOSXであれば最新版がダウンロードできるようだが、PowerPC版はダウンロードできないようだ。今回インストールしたのは一昨年にダウンロードしていたものなので1年半ぐらい前のバージョン。いつかは試そうと思いつついままで塩漬けだったわけです。
http://www.intersystems.com/cache/technology/product-tables/prodversion.html

無償版ダウンロードページは以下「但し、このシングルユーザライセンスは、評価・テストを目的としたもので商用アプリケーションの開発、販売、運用には使用できません。」とのこと。
http://www.intersystems.co.jp/cache/downloads/index.html

昔のMUMPS(M言語)の言語仕様しか覚えていないので暫しCaché Objectscriptのリファレンスを斜め読み。。イメージはそんなに変ってないか。。。ということでHello World!では面白くないのでMUMPS言語というか、M言語というか Caché ObjectscriptでFizz Buzzしてみた。
(新しいObjectscriptの文法でコーディングするならコマンドや慣習として省略形でコーディングすることが多かったMUMPSだけど、今は省略形は利用しないほうが読み易いよね、きっと。
MUMPSは習慣的に省略形のコマンドや関数でコーディングされているものが多かったから(現在でも省略形でコーディングする事が多いのかは知らない・・・・)、私が初めてMUMPSのコードを見たときは何じゃこれ! なんの記号? プログラムなのかこれ? と感じたことを思い出した。今回のコードも省略形使ってますが。www

MacOSXのTerminalを起動して。。。。(インストール後にはCachéが自動起動してる。。)
う〜〜〜〜ん、MUMPSの子孫だけどサンプルコード見るとJavaとかC的な文法もあるのね今のMUMPSじゃなくてObjectscriptは・・・今回は昔のMUMPSっぽく書いたけど。。

G5Server:˜ discus$ 
G5Server:˜ discus$ csession cache -U user

USER>

USER>f i=1:1:100 w $case(i#15,0:"FizzBuzz",:$case(i#3,0:"Fizz",:$case(i#5,0:"Buzz",:i))),!
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz

・・・・中略・・・・

89
FizzBuzz
91
92
Fizz
94
Buzz
Fizz
97
98
Fizz
Buzz

USER>
USER>halt
G5Server:~ discus$

ついでにシャットダウンしてみるか。。。

G5Server:~ discus$ 
G5Server:˜ discus$ sudo ccontrol stop cache
Password:

Cache Shutdown Status: 3:51 pm 19 Oct 2008

0 interactive jobs (Telnet/Lat)
0 background jobs (from job command)
0 Cache Direct server jobs
0 Cache Objects server jobs
0 CSP server jobs
0 ODBC server jobs
26 system jobs

Do you want to broadcast a message to anyone? No => No
Do you want to see the Cache status report? No => Yes

Cache System Status: 3:51 pm 19 Oct 2008
Process Device Namespace Routine CPU,Glob Pr User/Location
355 CONTROL 0,0 0
379 WRTDMN 227,23 0
380 GARCOL 0,0 0
381 JRNDMN 13830,141 0
389 EXPDMN 0,0 0
382 SLAVWD 7,126 0
385 SLAVWD 0,0 0
383 SLAVWD 0,0 0
388 SLAVWD 0,0 0
384 SLAVWD 0,0 0
387 SLAVWD 0,0 0
386 SLAVWD 0,0 0
419 /dev/null %SYS %SYS.Task 124096,23819 0 TASKMGR
398 /dev/null %SYS MONITOR 46080,3557 0
1838 /dev/ttyp1 %SYS SYS.Process 8256,1067 0 %System
400 /dev/null %SYS CLNDMN 704,47 0
401 /dev/null %SYS RECEIVE 90752,10111 0
402 /dev/null %SYS ECPWork 192,65 0
403 /dev/null %SYS ECPWork 192,64 0
404 /dev/null %SYS ECPWork 192,63 0
405 /dev/null %SYS ECPWork 192,63 0
406 /dev/null %SYS ECPWork 192,63 0
407 /dev/null %SYS ECPWork 192,63 0
408 /dev/null %SYS ECPWork 192,63 0
409 /dev/null %SYS ECPWork 192,63 0
1170 /dev/null %SYS %CSP.Daemon 12224,1290 0
411 |TCP|1972 %SYS %SYS.SERVER 192,65 0
416 /dev/null %SYS %MONAPP 61760,11240 0

2 user, 26 system, 32 mb global/1 mb routine cache

Do you want to broadcast a message to anyone? No => No
Do you want to see the Cache status report? No => No
Do you want to run the user defined shutdown routine? Yes => No
Are you ready for the system to halt? Yes => Yes

15:52:19 Shutting down Cache
15:52:20 Notifying Clients
15:52:20 No user shutdown routines to execute
15:52:20 Stopping User Jobs
15:52:20 Stopping Network Servers
15:52:21 Withdrawing from License Domain
15:52:21 Waiting for users to stop
15:52:21 Stopping Client Networking
15:52:21 Removing database locks
15:52:21 Updating Journal File
15:52:22 Waiting for database updates to complete
15:52:23 Database updates complete
15:52:23 Stopping System Jobs
15:52:27 Shutdown complete
G5Server:˜ discus$


ということで、あとはOracle Generic ConnectivityをOracle11gで試すときまでのお楽しみ・・・?!

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

2008年10月10日 (金)

MySQL User Conference 2008

MySQL User Conference 2008が10月30日と31日に開催される。すでに事前受付サイトもオープンしている。ただ30日のiPhone関連セミナーとバッティングしてるんだよな〜。(iPhoneセミナーが受けられようならそちら優先ということで・・・。。なんで行きたいセミナーってバッティングすることが多いのかね。まったく・・・)

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

2008年10月 1日 (水)

さて・・

Oracle11gMySQL5.0PostgreSQL8.3、(FireBird2.1もやるか)、それにOpenfiler2.3なども利用して旧リリースで試していたことを再度試しておこうかそろそろ。
たとえば、HeterogeneousRACのネタなど。まず、RACからやりますか..。

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

2008年3月10日 (月)

Mac de Ruby on Rails - #9 - ClubDB2番外編

Mac で Oracleな私ですが、第37回 ClubDB2番外編!Ruby on Rails 入門へ行ってきました。

いや〜〜、株式会社万葉の大場さんのセミナー面白かったですね。Mac使ってたし(笑)。
予定があったのでセミナー後の食事会?には参加できませんでしたが、RoRなどDB2から脱線?したネタがあればまた参加したいと思います。XMLDBネタが近々あるようだが、それはそれで聞いてみたい気もする。。


ちなみに、DB2の知識は、DB2 UDB 5.2で止まってる。。はず、と言いつつDBマガジンの記事は読んでますよ。


今回仕入れたネタも使って遊んだ結果などはいずれ。。。

2008/3/15追記
そう言えば、このセミナーで頂いたDB2 9:pureXML overview and fast startの紹介を忘れていたので追記しておきます。 (^^;;;
IBMさんのサイトではPDF版やHTML版が公開されている。

Db2_9_purexml_overview

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

2008年2月 5日 (火)

IBM Informix Dynamic Server Developer Edition for MAC OS X (Cheetah 2" Beta Download)

IBM Informix Dynamic Server for MacOSX("Cheetah 2" Beta Download)がダウンロードできるようになっていますね。

http://www.marketwire.com/mw/release.do?id=811175&sourceType=1
http://www-306.ibm.com/software/info/ids/index.jsp

これでDB2 UDB以外のメジャーな商用DBがMacOSX上でも動く事になりますね。
Oracle11g for MacOSXはどんな状況なんだろうなぁ実際のところ...

日本国内のサポートの有無に関係なくMacOSXで動作する商用データベース(ORDBMS/RDBMS/ODBMSに関係なく)を列挙しておく・・・

データベースMacOSXのバージョン備考
Oracle10g R1 EE/SE/SEONE?MacOSX(PPC) Panther / TIgerTigerでは10.1.0.5.0 patchsetが必要。
Sybase ASE 12.5.xMacOSX(PPC only?) Jaguar以上無償版あり
Caché 2007.1.MacOSX(PPC/Intel) Tiger無償版あり

注1)無償版と書きましたが商用利用などに制限のあるものもありますので詳細は各リンク先を参照してください。
注2)Oracle 10g XEはリリースされていないが、Oracle Mix(ユーザ登録が必要)ではOracle11g XE for MacOSX Leopardがあったらいいな〜なんて話もでている。

ちなみに、MacOSXのOracleに関して、Oracle Certification Matrixのページを見れば詳しい状況がわかります。
http://www.oracle.com/technology/support/metalink/index.html

3

4

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

2008年1月22日 (火)

24(テレビドラマではないよ)

Wigitize

24時間で作られたドットコムサイト『Wigitize』でも取り上げられていたのでいろいろ覗いてみたついでにWidgetを作って貼付けてみた。元からあるココログの「最近の記事」と比べても見劣りしないでしょ。
記事にもあるように24時間でどのようにしてWigitizeを構築していったのか、プロセスが細かく書かれていて実に面白い。


ココログオリジナルの「最新の記事」(左)とWigitizeで作って少々加工した「最新の記事」(右)
9 8

あ、24時間で作るといえば、Wif2008の予選会も24時間で与えられたテーマのWebデザインを完成させるのが条件でしたね。予選の作品が公開されたようです。。。Wif2008ネタは別エントリで。

日本からは8チームエントリしているように見えるが実際には5チームとのこと。
Wif2008_preselect

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

2008年1月17日 (木)

Sun が MySQLを買収

Sun、MySQLを買収

いや〜、驚きましたね!
PostgreSQLのサポートを提供しているSunですがMySQLを買収するとは。

InnoDBなどがOracleに買収されてしまい、なんとなくいやな雰囲気(Oracleさんも買収買収でバックマンになりはじめたねぇ〜と感じ始めていた)を感じていた今日このごろ。Sunによる買収なのでデータベースの世界もおもしろい状況になりそうな雰囲気を感じます。Falconの開発にも拍車がかかる事でしょうね。期待していますよ〜。:)

Oracle AppsLabのエントリでも書かれてますね - Acquisition Wednesday

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

2008年1月13日 (日)

Mac de Ruby on Rails - #1

さて、ウチの奥さんから遅れること?年、rubyをやってみようかと思っていたんですが中々手が進まず、風邪をひいてデータベースを触っていないこの時期に少しでも進めてみようと思い立ち私のPowerBook G4で環境作り。
ただ元来データベース周りが得意分野なのでRubyそのものというよりRuby on Railsで遊ぶことに。。。
今のところはデータベースはSQLite3を利用する環境なのですが・・いずれはOracleと繋げる予定・・・。

というのも・・・

S/N Ratioより引用

先週開催されていたオラクルの年次カンファレンス「Oracle OpenWorld 2007」の開始に合わせて、新サービス「Oracle Mix」のベータがローンチしました。Oracle Mixは、ソーシャル ネットワーク、アイデア共有、グループ コラボレーション、Q&Aフォーラムなどの機能を提供しています。

Oracle Mixは、Oracle Applications (オラクルの業務アプリケーション製品群) の開発チーム内のグループ「Oracle AppsLab」と、Martin Fowlerが所属していることでも有名なThoughtWorksが協力して開発したサービスです。

なんて事もあり興味を持ったとうのもあるんですけどね。

ところで、Oracle AppsLabといえば・・・以前私のエントリがPingback(かな?)でAppsLabのエントリにトラックバックされていたっけ。。。(^^;;;

ちなみに、Oracle Mixに登録しちゃってます。。:)
Oraclemix

さて、前置きはこれくらいにして本題です。。

奥さんのMacBook Proは既にMac OS X LeopardなのでなにもしなくてもRuby on Railsは利用できるんですが、私のPowerBook G4はまだMac OS X Leopardへアップデートしてないんですよいろんな都合で。なのでインストール作業から・・・・・

RubyもRuby on Railsも初めてなので、ググったり奥さんが買っていた書籍などを参考に・・・PowerBook G4 1Ghz(1GB ram) MacOSX Tiger 10.4.11へRuby on Railsをインストールしてみた。

MacPortsがあると便利とのことなのでまずは、MacPorts 1.6.0のTiger版をダウンロード。あとはMacPorts-1.6.0-10.4-Tiger.dmgをダブルクリック、さらにMacPorts-1.6.0.pkgをダブルクリックしてインストールすればOK。
Macport


MacPortsなどは、/opt/local以下にインストールされる。(XCodeは事前にインストールしておくべし。)

Last login: Sat Jan 12 20:01:35 on ttyp1
Welcome to Darwin!
pb17:˜ discus$ cd /opt/local/bin
pb17:/opt/local/bin discus$ ls
daemondo port portf portindex portmirror
pb17:/opt/local/bin discus $ port -v
MacPorts 1.600
Entering interactive mode... ("help" for help, "quit" to quit)
[local/bin] > quit
Goodbye
pb17:/opt/local/bin discus $


次にMacPortsのアップデート。

pb17:/opt/local/bin discus$ sudo ./port -v selfupdate
Password:
Synchronizing local ports tree from rsync://rsync.macports.org/release/ports/
receiving file list ... done
./
aqua/Affiche/
aqua/AppKiDo/
aqua/AquaLess/
aqua/ArpSpyX/

・・・・中略・・・・

zope/zope-zopezen/
zope/zope-zphotoslides/
zope/zope-zphotoslides/files/
zope/zope-zsyncer/

sent 74 bytes received 291810 bytes 20129.93 bytes/sec
total size is 16241925 speedup is 55.65

MacPorts base version 1.600 installed
receiving file list ... done

sent 73 bytes received 6617 bytes 2676.00 bytes/sec
total size is 3962384 speedup is 592.28

Downloaded MacPorts base version 1.600

The MacPorts installation is not outdated and so was not updated
selfupdate done!
pb17:/opt/local/bin discus$
pb17:/opt/local/bin discus$ ruby -v
ruby 1.8.2 (2004-12-25) [powerpc-darwin8.0]

MacOSX Tiger 10.4には、ruby 1.8.2は既にインストールされている。


環境変数 $PATHに/opt/local/binを追加。

pb17:/opt/local/bin discus $ echo $PATH
/opt/local/bin:/usr/local/mysql/bin:/bin:/sbin:/usr/bin:/usr/sbin

pb17:/opt/local/bin discus $ cd


次にRubyGemsパッケージ管理システムをMacPorts1.6を利用してインストール。インストール後には、Rubyも1.8.6へ更新されている。

pb17:˜ discus$ sudo port install rb-rubygems
Password:
---> Fetching expat
---> Attempting to fetch expat-2.0.1.tar.gz from http://downloads.sourceforge.net/expat
---> Verifying checksum(s) for expat

・・・・中略・・・・

---> Installing rb-rubygems 0.9.4_0
---> Activating rb-rubygems 0.9.4_0
---> Cleaning rb-rubygems
pb17:˜ discus$ ruby --version
ruby 1.8.6 (2007-09-23 patchlevel 110) [powerpc-darwin8.11.0]
pb17:˜ discus$


そしてRubyGemsでrailsをインストールしようとしたが、以下のようなエラーが発生して全くうまくいかない。。困った〜〜。

pb17:˜ discus$ sudo gem install rails --include-dependencies
Password:
/opt/local/lib/ruby/vendor_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require': no such file to load -- sources (LoadError)
from /opt/local/lib/ruby/vendor_ruby/1.8/rubygems/custom_require.rb:27:in `require'
from /opt/local/lib/ruby/vendor_ruby/1.8/rubygems/source_info_cache.rb:6
from /opt/local/lib/ruby/vendor_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require'
from /opt/local/lib/ruby/vendor_ruby/1.8/rubygems/custom_require.rb:27:in `require'
from /opt/local/lib/ruby/vendor_ruby/1.8/rubygems/remote_installer.rb:12
from /opt/local/lib/ruby/vendor_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require'
from /opt/local/lib/ruby/vendor_ruby/1.8/rubygems/custom_require.rb:27:in `require'
from /opt/local/lib/ruby/vendor_ruby/1.8/rubygems.rb:112:in `manage_gems'
from /opt/local/bin/gem:10
pb17:˜ discus$


前述のエラーメッセージでググってみたら「ソースからインストールするとうまくいくよ!」という内容のエントリを発見。
/opt以下削除してから再度MacPortsのインストール及びアップデートからやり直し。(尚、$PATH環境変数へは。/opt/local/binは設定したまま)

pb17:˜ discus$ sudo port -v selfupdate
Password:
Synchronizing local ports tree from rsync://rsync.macports.org/release/ports/
receiving file list ... done

sent 74 bytes received 291834 bytes 11447.37 bytes/sec
total size is 16241915 speedup is 55.64

MacPorts base version 1.600 installed
receiving file list ... done

sent 73 bytes received 6621 bytes 4462.67 bytes/sec
total size is 3962384 speedup is 591.93

Downloaded MacPorts base version 1.600

The MacPorts installation is not outdated and so was not updated
selfupdate done!


次に、RubyGems 0.9.4をインストール(1.0.1がリリースされていたが敢て、古いバージョンをインストール)
curlを使わなくてもいいんですが・・・とりあえずコマンドで作業を進めて行きます。(このエントリの後半で1.0.1へアップデートします。)

pb17:˜ discus$ curl -L -O http://rubyforge.org/frs/download.php/20989/rubygems-0.9.4.tgz
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 200k 100 200k 0 0 49807 0 0:00:04 0:00:04 --:--:-- 81744

pb17:˜ discus$ tar zxvf rubygems-0.9.4.tgz
rubygems-0.9.4/
rubygems-0.9.4/.document
rubygems-0.9.4/bin/
rubygems-0.9.4/bin/gem

・・・・中略・・・・

rubygems-0.9.4/test/user_capture.rb
rubygems-0.9.4/test/yaml_data.rb
rubygems-0.9.4/TODO
pb17:˜ discus$


解凍したら setup.rbを実行してRubyGems 0.9.4をインストール。

pb17:˜ discus$ cd rubygems-0.9.4
pb17:˜/rubygems-0.9.4 discus$ sudo ruby ./setup.rb
Password:
---> bin
<--- bin
---> lib
---> lib/rbconfig
<--- lib/rbconfig

・・・・中略・・・・

<--- lib
Successfully built RubyGem
Name: sources
Version: 0.0.1
File: sources-0.0.1.gem
Removing old RubyGems RDoc and ri...
Installing rubygems-0.9.4 ri...
Installing rubygems-0.9.4 rdoc...

As of RubyGems 0.8.0, library stubs are no longer needed.
Searching $LOAD_PATH for stubs to optionally delete (may take a while)...
...done.
No library stubs found.

pb17:˜/rubygems-0.9.4 discus$


ソースからインストールしたRubyGemsを使ってrailsをインストール・・・

pb17:˜/rubygems-0.9.4 discus$ sudo gem install rails --include-dependencies
Bulk updating Gem source index for: http://gems.rubyforge.org
Successfully installed rails-2.0.2
Successfully installed rake-0.8.0
Successfully installed activesupport-2.0.2

・・・・中略・・・・

Installing RDoc documentation for actionpack-2.0.2...
Installing RDoc documentation for actionmailer-2.0.2...
Installing RDoc documentation for activeresource-2.0.2...
pb17:˜/rubygems-0.9.4 discus$ rails -v
Rails 2.0.2
pb17:˜/rubygems-0.9.4 discus$ cd
うまくいった〜〜。パチパチ。


ついでにSQLite3もインストール(こちらはMacPortsでインストールできた。)

pb17:˜ discus$ sudo port install sqlite3
---> Fetching gawk
---> Attempting to fetch gawk-3.1.5.tar.bz2 from http://ftp.gnu.org/gnu/gawk

・・・・中略・・・・

---> Installing sqlite3 3.5.4_0+darwin_8
---> Activating sqlite3 3.5.4_0+darwin_8
---> Cleaning sqlite3
pb17:˜ discus$


さらにSQLite3インターフェースのインストール

pb17:˜ discus$ sudo port install rb-sqlite3
Password:
---> Fetching rb-sqlite3
---> Attempting to fetch sqlite3-ruby-1.2.1.tar.bz2 from http://rubyforge.org/frs/download.php/17096/
---> Verifying checksum(s) for rb-sqlite3
---> Extracting rb-sqlite3
---> Configuring rb-sqlite3
---> Building rb-sqlite3 with target setup
---> Staging rb-sqlite3 into destroot
---> Installing rb-sqlite3 1.2.1_0
---> Activating rb-sqlite3 1.2.1_0
---> Cleaning rb-sqlite3
pb17:˜ discus$ sudo gem install sqlite3-ruby
Select which gem to install for your platform (powerpc-darwin8.11.0)
1. sqlite3-ruby 1.2.1 (mswin32)
2. sqlite3-ruby 1.2.1 (ruby)
3. sqlite3-ruby 1.2.0 (mswin32)
4. sqlite3-ruby 1.2.0 (ruby)
5. Skip this gem
6. Cancel installation
> 2
Building native extensions. This could take a while...
Successfully installed sqlite3-ruby-1.2.1
Installing ri documentation for sqlite3-ruby-1.2.1...
Installing RDoc documentation for sqlite3-ruby-1.2.1...
pb17:˜ discus$


インストールできたのでrailsアプリケーションの作成準備。


pb17:˜ discus$ cd /Volumes/Repository
pb17:/Volumes/Repository discus$ mkdir discus
pb17:/Volumes/Repository discus$ cd discus
pb17:/Volumes/Repository/discus discus$ rails rails-demo
create
create app/controllers
create app/helpers
create app/models
create app/views/layouts

・・・・中略・・・・

create doc/README_FOR_APP
create log/server.log
create log/production.log
create log/development.log
create log/test.log
pb17:/Volumes/Repository/discus discus$
pb17:/Volumes/Repository/discus/rails-demo discus$ script/server
=> Booting WEBrick...
=> Rails application started on http://0.0.0.0:3000
=> Ctrl-C to shutdown server; call with --help for options
[2008-01-13 22:59:27] INFO WEBrick 1.3.1
[2008-01-13 22:59:27] INFO ruby 1.8.6 (2007-09-23) [powerpc-darwin8.11.0]
[2008-01-13 22:59:27] INFO WEBrick::HTTPServer#start: pid=15815 port=3000
127.0.0.1 - - [13/Jan/2008:23:01:02 JST] "GET / HTTP/1.1" 200 7557-
-> /
127.0.0.1 - - [13/Jan/2008:23:01:02 JST] "GET /favicon.ico HTTP/1.1" 200 0
http://localhost:3000/ -> /favicon.ico
127.0.0.1 - - [13/Jan/2008:23:01:02 JST] "GET /javascripts/prototype.js HTTP/1.1" 200 125605
http://localhost:3000/ -> /javascripts/prototype.js
127.0.0.1 - - [13/Jan/2008:23:01:02 JST] "GET /javascripts/effects.js HTTP/1.1" 200 38916
http://localhost:3000/ -> /javascripts/effects.js
127.0.0.1 - - [13/Jan/2008:23:01:02 JST] "GET /images/rails.png HTTP/1.1" 200 1787
http://localhost:3000/ -> /images/rails.png
127.0.0.1 - - [13/Jan/2008:23:01:33 JST] "GET /rails/info/properties HTTP/1.1" 200 920
http://localhost:3000/ -> /rails/info/properties
^C[2008-01-13 23:02:09] INFO going to shutdown ...
[2008-01-13 23:02:09] INFO WEBrick::HTTPServer#start done.
pb17:/Volumes/Repository/discus/rails-demo discus$

なんとかここまでできました〜〜。
Ror_demo2


最後に、はじめにも書いていましたがgemsを最新版にアップデートしておきます。

pb17:˜ discus$ gem -v
0.9.4
pb17:˜ discus$ sudo gem update --system
Updating RubyGems...
Attempting remote update of rubygems-update
Successfully installed rubygems-update-1.0.1
Updating version of RubyGems to 1.0.1
Installing RubyGems 1.0.1
install -c -m 0644 rbconfig/datadir.rb /opt/local/lib/ruby/site_ruby/1.8/rbconfig/datadir.rb
install -c -m 0644 rubygems/builder.rb /opt/local/lib/ruby/site_ruby/1.8/rubygems/builder.rb
install -c -m 0644 rubygems/command.rb /opt/local/lib/ruby/site_ruby/1.8/rubygems/command.rb
install -c -m 0644 rubygems/command_manager.rb /opt/local/lib/ruby/site_ruby/1.8/rubygems/command_manager.rb

・・・・中略・・・・

rm -rf /opt/local/lib/ruby/gems/1.8/doc/rubygems-0.9.4
Installing rubygems-1.0.1 ri into /opt/local/lib/ruby/gems/1.8/doc/rubygems-1.0.1/ri...
Installing rubygems-1.0.1 rdoc into /opt/local/lib/ruby/gems/1.8/doc/rubygems-1.0.1/rdoc...
As of RubyGems 0.8.0, library stubs are no longer needed.
Searching $LOAD_PATH for stubs to optionally delete (may take a while)...
...done.
No library stubs found.
RubyGems system software updated
pb17:˜ discus$ gem -v
1.0.1
pb17:˜ discus$

これでRubyGemsのアップデートもなんとか完了〜〜。ホッ。この続きは暇を見て調べながらやって行きましょうかね・・・・。


参考にしたサイトや書籍など。。
http://feeds.japan.cnet.com/~r/cnet/blog/kenn/~3/761095/
http://www.takezou.com/archives/2007/05/ror_install_on.html
http://i.loveruby.net/ja/projects/setup/doc/usage.html
http://mikilab.doshisha.ac.jp/dia/research/report/2006/1014/002/report20061014002.html
http://lapangan.net/darwinports/index.php?HowTo%2FUseMacPorts
http://rubyforge.org/
http://www.rubyonrails.org/down

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

2007年12月30日 (日)

MyMiniCity で MySQL Error

今現在私のMyMiniCity - DISCUS HAMBURGにはビルも立ち村のような雰囲気からは随分変化してきた。
左のサイドバーに貼付けてあるのが今現在(30日の10時頃)の状況。

ところで今日アクセスした際、以下のようなMySQLの同時接続数オーバーが発生していた。
MyMiniCityだけに利用しているデータベースはMySQLなんですねぇ。

Myminicity_mysql_error

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

2007年12月12日 (水)

大規模Web サイトでのMySQL導入方法および事例紹介」セミナー

20071204001

先週のことだが、大規模Web サイトでのMySQL導入方法および事例紹介」セミナーが六本木にあるスウェーデン大使館内 オーデトリアムで開催されるということで行ってきた。MySQL Conference 2007の内容と多少重複する内容もあったが、DBマガジンでおなじみのMySQL 株式会社 松信 嘉範氏のセッションは興味深い内容だった。

会場となったスウェーデン大使館のオーデトリアムだけでは足りず、ロビーにも椅子とモニターが用意されていたが会場自体が小さいので全体で100名程度で満席となっていた。(オーデトリアム内で立ち見だったし。)

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

2007年11月 8日 (木)

Sun Tech Days 2007 in Tokyo - Last Day

やはり、気になったので、有楽町の無印での買い物ついでにSun Tech Days 2007 in Tokyoの最終日の最終セッションへ。

MacOSX Leopardへも組み込まれているDtrace関連と昨日は全く聞けなかったPostgraSQL関連セッション。

Solarisはないので、LeopardのbashからMacOSX 10.5 Leopardで確認だけ。。ちゃんと入ってますDtrace

Dtrace_macosx_leopard

その他、いろいろ試してみたいのだが、それは後日時間を取ってやってみようかと。。。予定は未定。

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

2007年9月13日 (木)

MySQL Users Conference Japan 2007 #2

MySQL Users Conference Japan 2007の最終日です。

コンファレンスの内容などは、他方々のブログ等のエントリで十分なので特に書く事もないのだが、例によって参加したセッションの一こまを。

● パネルディスカッション: MySQL の独自性と優位点

Kaj Arno, VP Community, MySQL AB
Patrick Bolduan, MTV Japan (Customer)
Kai Seidler, XAMPP (Community Member)
Marten Mickos, CEO, MySQL AB
Michael "Monty" Widenius, MySQL Fellow and Co-founder, MySQL AB
Brian Aker, Director of Architecture, MySQL AB

Cimg6581

● MySQL の Plugin API 詳細解説(ストレージエンジン自作入門)

Brian Aker  - Director of Architecture, MySQL AB
Cimg6582

● MySQL Cluster 入門

Stewart Smith - Cluster Developer, MySQL AB
Cimg6585

● MySQL Cluster の詳細解説

Stewart Smith - Cluster Developer, MySQL AB
Cimg6586

● MySQL 5.1の詳細解説

Brian Aker - Stewart Smith
Cimg6587

● MySQL テクニカルケーススタディ(海外事例解説)

Jimmy Guerrero - Product Manager for MySQL Cluster, MySQL AB
Cimg6588

● レセプション

今日はこの後、しっかりと夕食を食べることになっているので、軽く摘んでおきました。(^^
ワインやビールもありましたが何せ車なのでウーロンだけ〜。
レセプションの最後に抽選があったんですけど、当たっちゃいました。くじ運悪い私が!。
頂いたものは後日、ブログ de ノベルティへ。

Cimg6594

20070912001 20070912002 20070912003

スーツよりジーンズな方が多いのは、それだけで楽しかったりして。

あ、忘れるところだったが、Q&Aで、MySQLの storage engineとしてDB2を利用できるようにするという話題に関しても少々触れていたましたねぇ。今後どうなるんでしょうねぇ。


2007/9/13追記 セッションで使用したプレゼン内容は、あとで公開されるようなことを言っていましたね。そういえば。 ということで、セッションの資料が公開されたらリンクを追加する予定。

以下のエントリは詳細なメモが記載されてますね (^^;。
http://d.hatena.ne.jp/akiyan/20070911

従業員用食堂か〜〜、気付かなかったよ〜。 1200円も払ってまずい煮込みハンバーグ+マッシュポテトだったよ。(><)
http://nonn-et-twk.net/twk/node/93

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

2007年9月11日 (火)

MySQL Users Conference Japan 2007 #1

え〜〜っ。またまた、オラクル以外のネタ。 MySQL Users Conference Japan 2007に来ています。
(Generic ConnectivitiyネタでもMySQLはやってますが、なにせ、4.x及び、4.1なのでね。。。いずれ、5.x系のMySQLと10g R1 又は、11g R1でGeneric Connectivityネタもやりたいし。。。MacOSX版のOracle11gがリリースされればの話ですが。。)

Mysqlucjapan2007

Cimg6560

ということで、本日参加したセッションは、

● MySQL高可用性ソリューションの概要

Overview of MySQL HA solutions
- Jimmy Guerrero (Product Manager for MySQL Cluster, MySQL AB)

● 社内外の開発者が参加するMySQLの開発モデル

MySQL architecture of Participation
- Kaj Arno (VP Community Relations, MySQL AB)

Cimg6564 Cimg6565

● MySQLパフォーマンスチューニング&ベンチマーク

Performance Tuning and Benchmarks
- Colin Charles (Community Relations Manager, APAC at MySQL AB)

Cimg6566

● Web 2.0に向けたMySQLアーキテクチャ

Web 2.0 and emerging web technologies
- Brian Aker (Director of architecture. MySQL AB)

Cimg6568

ちなみに、Brian Akerさんは、Mac使ってプレゼンしてましたね〜。

それに、ランチビュッフェも頂きました。。
Cimg6563 Cimg6562


MySQL 5.1.xのパーティショニングのタイプもOracleと同じようなタイプをサポートしているようなのでコンポジットパーティションで組み合わせる事ができるパーティショニングタイプなんかも調べておこうか。 そういえば、Oracle11gでは、コンポジットパーティションで利用できるパーティションタイプの組み合わせがかなり増えていたなぁ。

明日も楽しみじゃ。

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

2007年6月24日 (日)

OSC 2007 .DB

今日は、Open Source Conference 2007 .DBに行ってきました。 結構な人数が来てましたね。

朝は寝坊したこともあり、10時からのセッションには間に合わず。。。 orz、
ということで、DBマガジンでもおなじみの増永良文氏のセッションなど午後からのものを中心に。。

 


Cimg4826 Cimg4834

頂いたノベルティは、こちら。

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

2006年11月 1日 (水)

Mac De Oracle - Oracle以外のDB

ひさびさに、Mac De Oracle以外のデータベースネタを1つ。

InterSystemsのCache 5.2.0.32.9.0のシングルユーザ版はフル機能で無料
最近は、Oracle10g XEなども無料だ。ただ、Oracle10g XEには、MacOSX版がないのだが、Cache 5.2には、MacOSX版も用意されている。

ちなみに、
MacOSX版はないが、IBM DB2 express-CというDB2の無料版もある。

| | コメント (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>

今日はここまで。

Mac, Oracle, Oracle以外のデータベース, 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 化けないよ