同僚が作ったプログラムで怪しげな処理を見かけたのでちょっと確認。
怪しげな処理っていうのは、DECIMAL のフィールドを比較処理。
(1) VB の ADODB.RecordSet で DECIMAL 型のフィールドを普通に取得
(2) CStr$() で文字列に変換
(3) 文字列の比較
とかやってて。それだと 11 < 2 とか評価されちゃうのでは?と思ったわけで。
とりあえず DB2 で試してみた。
db2 => CREATE TABLE TEST (ID DECIMAL(10))
db2 => select id, cast(id as char(12)) from test
ID 2
------------ ------------
0. 0000000000.
1. 0000000001.
2. 0000000002.
10. 0000000010.
-1. -0000000001.
-2. -0000000002.
6 レコードが選択されました。
あれ。CAST した場合は 0 でパディングされるのね。
ということは、場合によっては文字列に変換後でも問題ないんだろうな。
ま、一応確認。
db2 => select id, cast(id as char(12)) from test order by 1
ID 2
------------ ------------
-2. -0000000002.
-1. -0000000001.
0. 0000000000.
1. 0000000001.
2. 0000000002.
10. 0000000010.
6 レコードが選択されました。
CHAR にキャストした後も↑みたいな大小関係があればいいんだけど・・・
db2 => select id, cast(id as char(12)) from test order by 2
ID 2
------------ ------------
-1. -0000000001.
-2. -0000000002.
0. 0000000000.
1. 0000000001.
2. 0000000002.
10. 0000000010.
6 レコードが選択されました。
やっぱりダメでした。
負数は代償関係が逆になってしまいますね。
この方法での比較は フィールド値 > 0 が保証されている場合のみ有効、と。
で・・・ふと自分の PC に SQLServer がインストールされているのを思い出し、この環境でも試してみた。
1> select id, cast(id as char(10)) from test
2> go
id
------------ ----------
0 0
1 1
2 2
10 10
-1 -1
-2 -2
(6 件処理されました)
おー、これこれ。当初は CAST したらこう(0 埋めされず、左寄せに)なると思ってたんだよね。
ということは・・・。
1> select id, cast(id as char(10)) from test order by 1
2> go
id
------------ ----------
-2 -2
-1 -1
0 0
1 1
2 2
10 10
(6 件処理されました)
これはまぁ当然の結果として・・・
1> select id, cast(id as char(10)) from test order by 2
2> go
id
------------ ----------
0 0
1 1
-1 -1
10 10
2 2
-2 -2
(6 件処理されました)
こうな・・・る・・・あれ?
負号の位置が予想と違う・・・。
・・・まぁ SQLServer の照合順序って結構特殊だし、こんなもんかも。
なんか環境によって色々違いそうなので、結局 VB も試してみることに。
同僚がやってたように、CAST は行わず、CStr$() による変換。
Dim cnn As New ADODB.Connection
Dim rs As New ADODB.Recordset
cnn.Open "dsn=hoge;uid=hoge;pwd=hoge;"
Set rs = cnn.Execute("SELECT ID FROM TEST")
Do While rs.EOF = False
Debug.Print "[" & CStr$(rs.Fields(0)) & "]"
rs.MoveNext
Loop
cnn.Close
超手抜きコード。さて、結果は・・・
[0]
[1]
[2]
[10]
[-1]
[-2]
どうやら左寄せの文字列になってしまう模様。やっぱダメじゃん。
ということで、結論。
INTEGER とかに収まりきらない DECIMAL はできるだけ DB 上で比較しましょう、と。
で、会社の先輩は CDbl() で変換して比較してました。
なるほど。今回のフィールドは DECIMAL(13) だからそれでも OK と。