はじめに
SQLなんて、どのクライアントから実行しても同じ結果になるものだと思っていました。
そう、思っていました。
あの日までは
1. 事件の始まり:SSMSでは完璧だったSQL
ある日、VBA(ADO接続)経由でSQL Serverからデータを引っ張ってくる処理を書いていました。
まずは開発環境である SSMS 上で、以下のようなSQLを組み立ててテストを実行します。
SELECT
UserName,
CONVERT(DATETIME, OrderDateString) AS OrderDate
FROM
Orders;
SSMS上の結果は「成功」。何のエラーもなく、綺麗なデータが返ってきました。
「よし、SQLは完成。あとはこれをVBAに取り込むだけだな」
この時は、数分後に自分が絶望することになるとは露知らず、ドヤ顔でVBA側にコードを組み込んでいました。
※ちなみにコードに直書きではなく外部ファイル参照(.sql)で組みました
2. 絶望:VBA経由だと急にキレる CONVERT
ところが、完成したSQLをVBAに移植してマクロを実行した瞬間、画面に非情なエラーが吐き出されました。
「エラーが発生しました」
「え? さっきSSMSで全く同じSQL流して通ったじゃん…なんで?」
SQL文はもちろんデータも全く同じ。データベースも同じところ。
それなのに、VBA(ADOのプロバイダ)を経由した瞬間に、エラーを起こしてシステムを強制終了させてしまうのです。
日付が~とは出ましたが、元SQLは大作だったためどこが引っかかっているのかわかりませんでした。
3. 試行錯誤:設定系を弄るも全滅の虚しさ
「これはきっと、SSMSとVBAで日付のフォーマット解釈(ロケール設定など)がズレているに違いない」
そうアタリをつけた私は、AIを駆使し、出てきた対策を片っ端から試しました。
- セッション開始時に SET DATEFORMAT ymd を流してみる
- SET LANGUAGE を変更してみる
- データベースの user options あたりの設定を疑ってみる
……しかし、結果はすべて無駄(全滅)。
VBAの接続セッションの頑固さの前には、環境設定系のコマンドは一切効果を発揮せず、エラーの嵐は止みませんでした。
実はAIからはこの時点でSQLを直すようにアドバイスされましたが、SSMSで通るんだから間違ってない!と頑なに設定を弄ってました。
4. 救世主:TRY_CONVERT で優しく黙らせる
無駄に時間を溶かした結果、「設定を変えて環境を直す」のを諦めた私は、AIの指示どおり「クエリの書き方そのもので殴る」方向にシフトしました。試すだけはタダやしな
そこで出会ったのが、SQL Serverが誇るイケメン関数 TRY_CONVERT です。
通常の CONVERT は、1件でも変換できない文字列に遭遇するとクエリ全体をエラーにしてしまいます。
しかし、TRY_CONVERT は違います。
「変換できたら日付を返すけど、無理だったらエラーにせず、優しく NULL を返して進む」 という圧倒的包容力を持った仕様なのです。
クエリを以下のように書き換えました。
SELECT
UserName,
TRY_CONVERT(DATETIME, OrderDateString) AS OrderDate -- ここを変更!
FROM
Orders;
結果は、嘘みたいにスッと通りました。ごめんなさいCopilot
本当の原因までは特定できませんでしたが、TRY_CONVERTで解消したことから、変換不能な値を含むデータが存在していた可能性が高そうです。
まとめ:SSMSで通っても安心するな
今回のトラブルで一番問題だったのは、SQLでもADOでもありませんでした。
「SSMSで通ったんだからSQLは正しい」
そう決めつけて、環境設定ばかり疑っていた自分の思い込みです。
SSMSで通ったから安心。
そう思っていた時期が私にもありました。
現場からは以上です。