Home > 2011年02月

2011年02月 Archive

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
  • Comments (Close): -
  • TrackBack (Close): -

フレームワーク開発時代のSQLチューニング基礎(2)SQLのやっちゃだめ前編 について確認してみた の続き

  • Posted by: Nakunaru
  • 2011-02-18 Fri 00:18:19
  • メモ
フレームワーク開発時代のSQLチューニング基礎(2)SQLのやっちゃだめ前編 について確認してみた

の続きです。



GROUP BYやORDER BYにインデックスを使う。



に対して突っ込もうと思ったら、ほんとにINDEXを使っててあれれ?
となっていたのですが、ふと思いついてもう一度検証して見ました。

まずサンプルの表構造

mysql> desc tab1;
+-------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+----------------+
| col1 | int(11) | NO | PRI | NULL | auto_increment |
| col2 | int(11) | YES | | NULL | |
| col3 | int(11) | YES | | NULL | |
| col4 | int(11) | YES | | NULL | |
+-------+---------+------+-----+---------+----------------+

mysql> show indexes from tab1;
+-------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| tab1 | 0 | PRIMARY | 1 | col1 | A | 1000245 | NULL | NULL | | BTREE | |
| tab1 | 1 | tab1_123_idx | 1 | col1 | A | 1000245 | NULL | NULL | | BTREE | |
| tab1 | 1 | tab1_123_idx | 2 | col2 | A | 1000245 | NULL | NULL | YES | BTREE | |
| tab1 | 1 | tab1_123_idx | 3 | col3 | A | 1000245 | NULL | NULL | YES | BTREE | |
| tab1 | 1 | tab1_col4_idx | 1 | col4 | A | 17 | NULL | NULL | YES | BTREE | |
+-------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
5 rows in set (0.07 sec)



col1 のINDEXはPRIMARYになっています。
それと、col1, col2, col3のコンポジットINDEX、およびcol4のINDEXがある状態です。
表の件数は100万程で、col1をカウントアップしながらINSERTしたので、内部の行データはcol1の順で物理的にソートされているはずです。



この状態でORDER BY col1をやってみます。


mysql> explain select col4, max(col1) from tab1 group by col1;
+----+-------------+-------+-------+---------------+---------+---------+------+---------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+------+---------+-------+
| 1 | SIMPLE | tab1 | index | NULL | PRIMARY | 4 | NULL | 1000245 | |
+----+-------------+-------+-------+---------------+---------+---------+------+---------+-------+
1 row in set (0.00 sec)


うん。やっぱりINDEXフルスキャンが発生しています。

では次。


mysql> explain select * from tab1 order by col4;
+----+-------------+-------+------+---------------+------+---------+------+---------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+---------+----------------+
| 1 | SIMPLE | tab1 | ALL | NULL | NULL | NULL | NULL | 1000386 | Using filesort |
+----+-------------+-------+------+---------------+------+---------+------+---------+----------------+
1 row in set (0.01 sec)

こんどは表のフルスキャンになり、INDEXは使ってません。
はーはー。なるほど。
ちょっとわかった気がしますが、確認のためにもう1つ。


mysql> explain select * from tab1 order by col1,col2,col3;
+----+-------------+-------+------+---------------+------+---------+------+---------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+---------+----------------+
| 1 | SIMPLE | tab1 | ALL | NULL | NULL | NULL | NULL | 1000386 | Using filesort |
+----+-------------+-------+------+---------------+------+---------+------+---------+----------------+
1 row in set (0.01 sec)


うん。やっぱりINDEXはつかいません。


原因はクラスタINDEXのせいです。多分。
InnoDBのPRIMARY INDEXは、クラスタINDEXで作成されます。
クラスタINDEXは、簡単にいえば、そのキーの順で表の行も格納しようとするINDEXです。
つまり、col1のINDEXがPRIMARYなら、表の行データも物理的にcol1の順でソート済みの状態になっているわけです。
なおかつ、このINDEXをたどるとリーフページには、行データそのもが格納されているため、INDEXを見てから表へアクセスという2つのステップを踏まなくてよいことになります。

参考:知って得するInnoDBセカンダリインデックス活用術!

つまり、col1でソートした結果が欲しいなら、col1のクラスタINDEXの最小値まで一旦辿って、そこから次のリーフ、次のリーフとINDEXフルスキャンをすると、必要な行データは全て得られ、かつ既にソート済みの状態で読み込まれるわけです。
なので、MySQLはcol1のINDEXを使ってくれたわけですね。


ところが、ORDER BY col1, col2, col3 とすると、INDEXを使わずに表のフルスキャンになってしまいます。
これは、col1だけの索引では、第二ソートキーのcol2、第三ソートキーのcol3までの並び順には対応できないですよね。
なので、次に候補にあがるINDEXはcol1+col2+col3のINDEXになるはずです。
しかに、こいつはクラスタINDEXではないため、INDEXを辿って行アドレスを取得したあと、改めて表へアクセスする必要があります。
しかもこれは、1行単位でINDEX→表→INDEX→表→・・・と繰り返すことになります。
当然、I/O回数が膨大になるので、それをやるくらいなら最初から表をフルスキャンで読み込み、あとでメモリ内でソートしたほうが速いとオプティマイザが判断した結果だと思われます。
もちろん、ORDER BY col4も同じ理屈です。


と、いうことで、MySQLであっても、ORDER BYのためだけにINDEXを使うとは限らない(というか使わない)ということになります。
WHEREの条件との組み合わによってソート処理がスキップできる場合がある、という程度に覚えておくとよいかも。


ソートとINDEXの関係については、マニュアルにちゃんと書いてあったので、こちらを参照してください。
http://dev.mysql.com/doc/refman/5.1/ja/order-by-optimization.html


そんなわけで、昨日のもやもやはこれで解決できました。
めでたし。



フレームワーク開発時代のSQLチューニング基礎(2)SQLのやっちゃだめ前編 について確認してみた

  • Posted by: Nakunaru
  • 2011-02-17 Thu 00:12:42
  • メモ

追加情報をこちらに書きました。合わせてどうぞ。



フレームワーク開発時代のSQLチューニング基礎(2)SQLのやっちゃだめ前編






こちらの記事をみて、いくつか気になったので確認してみました。
ただ、あらかじめ言っておくと、この記事の主張は概ね正しいと思います。
ちょっと重箱の角をつつくような内容なので、あしからず。


まずはこの文章。

 ワイルドカードを使った場合、必要のないデータまでメモリ上に展開されますが、項目を指定した場合は必要なデータのみメモリ上に展開されます。メモリは高速ですが、無限の容量がある訳ではないので、効率よく使用するために項目指定をするようにしましょう。



これだけ読むと、データのI/Oが列単位に行われているような印象を受けてしまいます。
InnoDBでは、ページ単位のI/Oで、バッファキャッシュへのキャッシュもページ単位のはずなのでSELECT句の列を*で書いても、特定の列だけ書いてもメモリーの使用量は変わらないはず。
MyISAMだとどうなんだろう。昔BtrieveというISAM系のDBを使ってたことがありますけど、I/Oはページ単位だったので、多分MyISAMでも一緒じゃないかと予想。←すいません、マニュアルも見ないで書いてます。

結論としての、SELECT * は使うな、には100%同意です。








また、項目指定の方が明らかに速い検索も存在します。例をみてみましょう。


こちらは、カバリングINDEXによって、INDEXスキャンのみで検索が完了できる例ですね。
これは、SELECT句の列は最小限にすること+INDEXは複数列の索引で作成の2つの組み合わせによって、表スキャンが必要なくするテクニックとして多くの人に知ってもらいたい内容ですね。




範囲検索はBETWEENを使う



これについてはちょっと気になったので、色々調べてみました。

以上以下の複数の条件を各よりSQLのBETWEENを使った方が高速になります。



とありますが、Oracleでは、BETWEENで書いたSQLを、Oracleがパースしたタイミングで、列名<値 AND 列名>値 の形に変換してから、選択性の評価を行っていたように記憶しています。
(今手元に使えるOracle環境がなくて未検証です。識者の突っ込み待ちです)

DB2でも、BETWEENを投げると、DB2が勝手に< AND > の式に変換してたように記憶していたので、これは検証してみました。
以下、DB2 9.1のSAMPLEデータベースでの検証内容です。

db2 SET CURRENT EXPLAIN MODE YES

db2 -tvf "$DB2PATH/misc/EXPLAIN.DDL"

db2 SET CURRENT EXPLAIN MODE YES

db2 "select * from employee where empno between '000020' and '000050'"


この時の実行計画などをdb2exfmtで確認します。
結果が結構長いので、一部抜粋


db2exfmt -d sample -t -1

Optimized Statement:
-------------------
SELECT Q1."EMPNO" AS "EMPNO", Q1."FIRSTNME" AS "FIRSTNME", Q1."MIDINIT" AS
"MIDINIT", Q1."LASTNAME" AS "LASTNAME", Q1."WORKDEPT" AS "WORKDEPT",
Q1."PHONENO" AS "PHONENO", Q1."HIREDATE" AS "HIREDATE", Q1."JOB" AS
"JOB", Q1."EDLEVEL" AS "EDLEVEL", Q1."SEX" AS "SEX", Q1."BIRTHDATE"
AS "BIRTHDATE", Q1."SALARY" AS "SALARY", Q1."BONUS" AS "BONUS",
Q1."COMM" AS "COMM"
FROM HITAI.EMPLOYEE AS Q1
WHERE (Q1."EMPNO" <= '000050') AND ('000020' <= Q1."EMPNO") ← ここに注目!



Predicates:
----------
2) Stop Key Predicate
Comparison Operator: Less Than or Equal (<=)
Subquery Input Required: No
Filter Factor: 0.0952381  ← ここ

Predicate Text:
--------------
(Q1."EMPNO" <= '000050')

3) Start Key Predicate
Comparison Operator: Less Than or Equal (<=)
Subquery Input Required: No
Filter Factor: 0.97619   ← ここ

Predicate Text:
--------------
('000020' <= Q1."EMPNO")





ということで、BETWEENでSQLを投げても、内部の最適化処理で< and > に変換され、それぞのフィルタファクタ(選択性)の計算を行ってから、実行計画の決定をしているように見えます。
選択性の計算式は、どっかのサイトにあったと思いますが、OracleでもDB2でも基本的な考えはだいたい同じです。
で、おそらくMySQLも一緒じゃないかなーと思って調べてみたのですが、明確なドキュメントは見つけられませんでした。この件も識者の突っ込みをお待ちしています。

で、ドキュメントがないなら、自分で確認すればいいじゃない、ということで最適化された後のSQLを見ようとしたのですが、これも適切な方法がみつけられず。
MySQLでOracleのstatspack的なことをやれるよ、というブログエントリも見つけましたが、多分これも投げられたSQLしかみれないですよね。試してないけど。
そんなわけで、最適化後のSQLの確認方法をご存知の方、教えてください。

で、話を戻すと、BETWEENと< AND > のどちらが早いか、についてMySQLでは確認できませんでした。
でも、おそらく最近のバージョンであれば、どちらでも同じように最適化されるはずなので、読みやすい、書きやすい方でもいいかなーとは思います。





GROUP BYやORDER BYにインデックスを使う。


これは製品によって違うかもしれないんですが、Order by や group by のためだけにindexスキャンは選択されない気がします。
→ と書くつもりでいたのすが、試してみるとINDEXフルスキャンで使ってますね。
実行計画のTypeがINDEXとなっているので、INDEXを全件なめて、その順で表アクセスしてるってことですかね。
いくつかのパターンで確認しましたが、ORDER BYのためにINDEXをつかってるように見えますねぇ・・・
WHERE句とORDER BYで同じ列を使っていれば、その列のINDEXによってソート処理がスキップできる。と認識していたのですが、MySQLではちょっと違うのかもしれません。

ここらへんの、オプティマイザの判断基準とか、マニュアルでも見つけられなかったので、ここ読んどけオラっていう情報がありましたら教えてください。
うーん。もやもやする。







キーに演算はしない。


これはその通りで、SQLを書く全ての人に知ってもらいたい内容ですね。

で、よくありがちなので日付の絞りこみです。
ちょっとORACLEでの例になりますが、

SELECT empno, ename, hiredate FROM emp
WHERE TO_CHAR(hiredate, 'YYYY/MM/DD') = '2011/02/16';


よくありがちですが、これはHIREDATE列にINDEXがあっても使えません。
列値が関数などで加工されると、INDEX内の列値を使ってマッチングができないからですね。
日付での絞り込みが遅いシステムの原因としてよく見かけます。
でも、この書き方じゃINDEXが使えないのはわかったので、改良してみます。

SELECT empno, ename, hiredate FROM emp
WHERE hiredate = TO_DATE('2011/02/16', 'YYYY/MM/DD');



で、これを実行すると、データが1件もヒットしなかったりします。
原因は、DATE型は年月日 時分秒を持っているため、「年月日」だけの文字列を変換すると、時刻部分は00:00:00扱いになるためです。
なので、時刻部分は無視できるようにします。

SELECT empno, ename, hiredate FROM emp
WHERE hiredate >= TO_DATE('2011/02/16 00:00:00', 'YYYY/MM/DD HH:MI:SS')
AND hiredate <= TO_DATE('2011/02/16 23:59:59', 'YYYY/MM/DD HH:MI:SS');


betweenのほうがすっきりするかもしれませんが。

同様に、データ型の暗黙変化でもINDEXは使えなくなるので、文字と数値の比較などを行わないように注意が必要です。




以上が気になった点を調べた結果です。
今回は、twitterでうっかりツッコミたい的な発言をしてしまったのですが、結局はツッコミ所はほとんどなく(または自分のスキル不足で確認すらできず)元記事はやっぱり良いエントリだったなーという結果になりました。

逆に、普段仕事でつかってないMySQLの勉強になったのが収穫でしたし、調べきれなくて疑問のままになっている点については、是非、MySQLのえらい人からのツッコミをお待ちしています。
漢の人の鍵本買っておけばよかった。


参考URL
漢のコンピュータ道 MySQLのEXPLAINを徹底解説!!
http://nippondanji.blogspot.com/2009/03/mysqlexplain.html

SH2の日記 MySQL 5.1のmysqldumpslowで快速チューニング
http://d.hatena.ne.jp/sh2/20090414

MySQL 5.1 リファレンスマニュアル
http://dev.mysql.com/doc/refman/5.1/ja/index.html


Cygwinでrlwrap

  • Posted by: Nakunaru
  • 2011-02-13 Sun 15:28:15
  • ORACLE
追記:Cygwin版のrlwrapで余計な改行が出力される問題があり、以下の記事で解決しています。
検索で飛んできた方はどうぞ。
http://hitai.blog72.fc2.com/blog-entry-85.html





WindowsのDOSプロンプトでSQL*Plusを起動すると、上下の矢印キーでコマンドヒストリが呼び出せますけど、Cygwinのプロンプトではできません。
DB2のCLPも一緒で、矢印キーによるコマンドヒストリは使えません。

こういったコマンドヒストリ機能がないツールでも、ヒストリ機能を無理やり使えるようにしてしまうのがReadLineWrapperと呼ばれるもので、Linuxではrlwrapというパッケージが提供されています。

で、Cygwinでは使えないの?と探してみたらあっさりありました。


こちらからダウンロードできました。
http://ftp.yz.yamagata-u.ac.jp/pub/cygwin/release/rlwrap/



適当にダウンロードしてきたら、展開するとusrというディレクトリが作成される。

tar jxf rlwrap-0.24-1.tar.bz2




└─usr
├─bin
│ rlwrap.exe

└─share
├─doc
│ ├─Cygwin
│ │ rlwrap-0.24.README
│ │
│ └─rlwrap-0.24
│ AUTHORS
│ BUGS
│ ChangeLog
│ COPYING
│ INSTALL
│ NEWS
│ README
│ TODO

├─man
│ └─man1
│ rlwrap.1.gz

└─rlwrap
ftp
testclient


この中のrlwrap.exeを適当にパスが通ったディレクトリに置いて、

rlwrap sqlplus / as sysdba



とすればヒストリ機能が使えるようになる。



ただし、このままだ

SQL> connect / as sysdba
?????????????B


こんな感じで、日本語メッセージが化けてしまう。

解決するには、

.bashrcに以下を追加
export LANG=ja_JP.SJIS
export TZ=JST-9
export JLESSCHARSET=japanese-sjis
alias ls='ls --show-control-chars'

.inputrcに以下を追加
set kanji-code sjis
set convert-meta off
set meta-flag on
set output-meta on

参考:http://seiza.dip.jp/computer/20071028001115338.html

これで解決。日本語も通ります。


rlwrap.exe sqlplus / as sysdba
SQL*Plus: Release 11.1.0.6.0 - Production on 木 2月 10 15:38:05 2011
Copyright (c) 1982, 2007, Oracle. All rights reserved.
Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
に接続されました。
SQL>
SQL> select * from hr.regions;
REGION_ID REGION_NAME
---------- -------------------------
1 Europe
2 Americas
3 Asia
4 Middle East and Africa
SQL>
SQL> insert into hr.regions values(11,'新世界');
1行が作成されました。
SQL> select * from hr.regions;
REGION_ID REGION_NAME
---------- -------------------------
11 新世界
1 Europe
2 Americas
3 Asia
4 Middle East and Africa
SQL> rollback;
ロールバックが完了しました。




もちろんDB2のCLPでも日本語が通ります。


./rlwrap.exe db2
(c) Copyright IBM Corporation 1993,2002
DB2 ADCL 9.1.0 コマンド行プロセッサー
コマンド・プロンプトからデータベース・マネージャーのコマンド、および SQL
ステートメントを呼び出せます。 例:
db2 => connect to sample
db2 => bind sample.bnd
一般ヘルプには ? をタイプしてください。
コマンドのヘルプには ? command をタイプしてください。 command
は、データベース・マネージャー・コマンドの主要なキーワードの
いくつかです。 例:
す。
? CATALOG は全 CATALOG コマンドのヘルプです。
db2 対話モードを抜けるには、コマンド・プロンプトで QUIT
とタイプしてください。対話モード以外では、すべてのコマンドに接頭語 'db2'
を付ける必要があります。
現在のコマンド・オプションの設定をリストするには、 LIST COMMAND OPTIONS
とタイプしてください。
詳細は、「オンライン・リファレンス」を参照してください。
db2 =>




あとは、rlwrapの置き場所だけ決めればOKです。
私の場合は、/optの配下に本体を配置し、/usr/binの配下のシンボリックリンクを置いてみました。

ln -s /opt/rlwrap/usr/bin/rlwrap.exe /usr/bin/rlwrap.exe



そして、sql*plusとかclpはaliasをはっておきます。
.bashrc

#rlwrap Settings
alias sqlplus='rlwrap.exe sqlplus'
alias db2='rlwrap.exe db2'





[関連]
http://hitai.blog72.fc2.com/blog-entry-77.html
http://hitai.blog72.fc2.com/blog-entry-76.html

Windowsのコマンドプロンプトを便利にしてくれるCKW

  • Posted by: Nakunaru
  • 2011-02-13 Sun 14:58:17
  • メモ
http://hitai.blog72.fc2.com/blog-entry-76.html

上のエントリでCKWってものを使って、DB2のCLPを便利に使うって話をしましたが、そもそもCKWってなんだって話です。

そこらへんについてまとめてくれたエントリがあったので紹介しときます。
http://nyaos.org/d/index.cgi?p=%282010.06.20%29#p1

色んな派生バージョンがあったみたいですが、とりあえず今のとこ最新バージョンはgithubに上がっているようです。

https://github.com/deflis/ckw-mod

modってついてるけど、今はこれが最新版ってことみたいです。

バイナリでダウンロードした人はこっち
https://github.com/deflis/ckw-mod/downloads


マニュアルはこちら
https://github.com/deflis/ckw-mod/wiki/%E3%83%9E%E3%83%8B%E3%83%A5%E3%82%A2%E3%83%AB

Windows版のDB2 CLPをかっこ良く使いたい → Cygwin + CKW + CLP

  • Posted by: Nakunaru
  • 2011-02-06 Sun 18:20:30
  • db2
db2のCLPはCommand Line Processor の略で、オラクルでいうSQL*Plusの役割を果たすコマンドラインツールです。
UNIXだろうがLinuxだろうがWindowsだろうが、db2を使うならCLPでの作業ははずせません。

で、このCLP、Windowsなら当然DOSのコマンドプロンプトで使うわけですが、SQL*Plusとはちょっと使い勝手が違います。
Oracleでは、管理作業はほぼすべてSQL*Plusから行いますよね。例えばインスタンスの起動も、SQL*Plusからstartupコマンドですし。
でもdb2は、CLPから実行する管理コマンドと、OSコマンドとして実行する管理コマンドが混在しています。
例えばインスタンス起動は、OS上でdb2start コマンドを叩きます。
つまり、いったんCLPから抜けて実行しなければならないわけです。

また、Oracleで初期化パラメータを確認するには、show parameterコマンドがお手軽ですが、これはキーワードでの絞り込みが簡単ですよね?

show parameter db_


などとすると、「db_」が含まれるパラメータだけが表示されると。
でもdb2では、CLPを起動した状態で、

get dbm cfg


というコマンドを叩くと、全パラメータが出力されます。
絞り込みの機能はありません。
で、これでは不便なので、

db2 "get dbm cfg" | grep SVR


などとして、CLPを非対話モードで実行し、その結果をgrepするとかそんな使い方になります。
前置きが長くなりましたけど、要するにCLPは非対話モードで、OSコマンドの一部として使うことが多いということを言いたかったわけです。


そんで、そうなると気になるがコマンドラインそのものの使い勝手。
例えばファイル名のTABキーによる補完とか、DIRの代わりにlsを使いたいとか、ログファイルをtail -f で監視したいとかとかとか。
Windowsのコマンドプロンプトを便利に使うツールがないか、探してみると以下がヒットしました。

http://www.nyaos.org/
http://www.winunix.dreamhosters.com/winunix/shell.htm

そして、このnyacusというワードで検索すると、CKWというツールもヒットしてきます。
http://lucy.moe-nifty.com/blog/2009/10/windowslinux-88.html

ふむふむ。なるほど。
CKWはコマンドプロンプトで、ウィンドウの透過などの設定ができる。
nyacusはシェルの強化ができる。
そんで、ckwでは起動シェルが選択できるから、nyacusで実行すればよい。
とかそんな内容っぽい。
これはなかなかに面白い、ということで色々カスタマイズをしてみたのですが、CLPの使用で問題がありました。


WindowsのDOSプロンプトで、CLPを起動しようとすると、「DB21061E コマンド行環境は初期化されていません。」と表示されて起動できません。
これは、Windows版のCLPは環境変数だったりクライアント情報だったりを読み込まないと起動できないっぽいのですが、生のDOSプロンプトではそれらが読めてないからだということらしい。
こちらのブログで、いろいろ試しているようですので気になる方はどうぞ。
http://plaza.rakuten.co.jp/u703331/diary/200705160001/

で、私もなんとかCKWでclpが使えないか色々やってみた結果、使えるようにはなりましたが、dbへ接続しても1秒程で切断されてしまう現象は解決できませんでした。

そんなわけで方向転換です。
シェルの拡張は、Cygwinで解決しようということで、CygwinからCLPが使えないか調査。
で、調査を開始してすぐ見つかったのがやっぱりこのブログ。
いつもいつも助かります。
http://db2.jugem.cc/?eid=865

ここでは.bashrcとしていますが、まぁ読み込まれるファイルならどこでもいいでしょう。
環境に合わせて、以下を追記すればオッケーなようです。

export DB2CLP=**$$**
export DB2PATH=C:\\SQLLIB



上記設定で、CygwinからCLPが使えるようになりました。



で、ここではたと思いついたわけです。
CKWの「Ckw*exec」パラメータに、Cygwin.batを指定したら使えるんじゃね?と。

で、やってみたらこれがビンゴ。
透過ウィンドウでCygwinが動いて、db2も使えちゃいました。
そんなわけで、現在のcfgファイルは以下の通り。


!
! ckw setting
!
Ckw*foreground: #00ff00
Ckw*background: #000000
Ckw*cursorColor: green
Ckw*cursorImeColor: red
Ckw*title: ckw[Cygwin]
Ckw*exec: D:\Cygwin\Cygwin.bat ! ## ←これをいれるだけ ##
Ckw*chdir: d:\
Ckw*scrollHide: no
Ckw*scrollRight: yes
Ckw*internalBorder: 1
Ckw*lineSpace: 0
Ckw*topmost: no
Ckw*transp: 180
Ckw*transpColor: #000000
Ckw*font: MS Gothic
Ckw*fontSize: 14
Ckw*geometry: 110x35
Ckw*saveLines: 800
Ckw*color0: #333333
Ckw*color1: #4682B4
Ckw*color2: #90EE90
Ckw*color3: #00BFFF
Ckw*color4: #FF00FF
Ckw*color5: #FF8080
Ckw*color6: #FFFF00
Ckw*color7: #CCCCCC
Ckw*color8: #333333
Ckw*color9: #4682B4
Ckw*color10: #90EE90
Ckw*color11: #00BFFF
Ckw*color12: #FF00FF
Ckw*color13: #FF8080
Ckw*color14: #FFFF00
Ckw*color15: #CCCCCC



はい、というわけで、現在はCygwin + CKW + CLPという環境で快適に作業しております。

今回の件で、改めて参考URLをあさっていたら、あたらしいバージョンを作っている方を発見しました。
http://craftwave.blogspot.com/2010/05/ckw-2-copyall.html
これ、メニューのなかに「CopyALL」というメニューを追加してくれているんですが、地味に便利です。






[関連]Windowsのコマンドプロンプトを便利にしてくれるCKW
http://hitai.blog72.fc2.com/blog-entry-77.html

DB2のSELECT文でNULLを選択したい

  • Posted by: Nakunaru
  • 2011-02-06 Sun 17:34:11
  • db2
表題の通り。
Oracleなんかでは普通にできる、以下のようなSELECT文を実行したわけです。


SELECT empno, null, ename from employees;



で、実行すると

SQL0206N "NULL" is not valid in the context where it is used. SQLSTATE=42703


と表示されてエラーに。
今回はNULL除外の条件などがWHERE句にごちゃごちゃ入っていたので、どこで構文がちがったのかと小一時間ハマっておりました。
そんで、Google先生に聞いてみるとやっぱり以下のブログがヒット。
http://db2.jugem.cc/?eid=940
いやー、まいど助かります。

ということで、結論としてはデータ型が不定なままでNULLはイカンでしょうと。
CASTで適当なデータ型を指定すればオッケーとのことでした。

SELECT empno, CAST(NULL AS int), ename from employee







Index of all entries

Home > 2011年02月

タグクラウド
Categories
Monthly
Recent Entries
Recent Comments
Recent Trackbacks
Appendix

Nakunaru

    Author:Nakunaru

    データベース(ORACLEとかSQL ServerとかDB2とかMySQLとか)とか技術者教育とかプログラムとか。
    気になる技術を少しずつ勉強していきます。


Return to page top

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。