概要
データベースをOracleからSnowflakeに切り替えることとなった
アプリケーション(Java)側の修正が発生したので記録しておく
対応内容
メインはSQLの修正となる
①テーブル名の指定にスキーマ名は付けない
JDBCの接続文字列のなかで、スキーマ名の指定が出来るため、指定するとエラーになる
修正前:select * from scheme.table_a
修正後:select * from table_a
②DUAL表は使えない
SnowflakeにDUAL表は存在しないので、MERGE文等で使っているとエラーになる
直し方は以下のリファレンスを参照
③SYSDATE関数はDATE型ではない
Snowflakeで日付や時刻を表すにはDATE型だけでなくTIMESTAMP型などいくつか存在する
(OracleだとDATE型のみ)
Snowflakeだと、SYSDATEはDATE型ではなくTIMESTAMP型のため
DATE型の列に格納しようとするとエラーになる
対処として、SYSDATEではなくCURRENT_TIMESTAMPをセットする
※日付型の扱いはハマるポイントの一つ。
処理日時を取得する関数はSYSDATE、CURRENT_DATE、CURRENT_TIMESTAMPの3つがあるので、違いを理解したうえで使用すること。
④INSERT文の処理の遅さが気になる
DBの処理の遅さというよりも通信等のオーバーヘッドによる影響だと思うが、
複数レコードをINSERTする処理の遅さが気になるようになった
これまで1件ずつINSERTしていたのをバルクINSERTに変更したところ、大幅に早くなった
⑤NULLの扱いが変わる
select * col1 || col2 as vcol from table_a のSQLを実行したとき、
col1とcol2のどちらかがNULLだと全体(vcol)もNULLになってしまう
例:
col1のデータが「AAA」、col2のデータがNULLだとした時に、
Oracleは「AAA」と表示されるが、SnowflakeだとNULLと表示されることになる
対処としては、NVL関数を使って以下のように修正する
select * col1 || NVL(col2, '') as vcol from table_a
⑥NUMBER型での小数点を含む数値データの扱いが変わる
Oracleだと単にNUMBER型として定義が可能で、精度(全体の桁数)と
スケール(小数点以下の桁数)を指定しなくても、指定した値のまま格納出来た
Snowflakeで同じようにNUMBER型として定義するとスケールが0となり、
小数点以下が格納できず、指定した値とはズレが生じてしまう
対処としては、精度とスケールを指定してNUMBER型の定義を行う
さらに、例としてPRICE列をNUMBER(38, 10)型として定義して、
「0.1」という値を格納したとき、DBで保持されるのは「0.1000000000」となる
「0.1」も「0.1000000000」も同じ意味ではあるが、見た目の差異があるので
このままで良しとするかは確認したほうが良い
⑦UPDATEをすると並び順が変わる
table_aテーブルに対して、UPDATEを実行したあとに、
Oracleで「select * from table_a」を実行すると、UPDATE前後で取得した
レコードの並び順は変わらない(order byが無いので、変わらないのはたまたま)
Snowflakeだとレコードの並び順が都度変わる
※SELECT文にorder by句が無いので、並び順が保証されないのは当然のこと
この話しは参考程度に