Cloud SQL for SQL Server でローカル タイムゾーンを使う
Google Cloud Japan Team
※この投稿は米国時間 2022 年 4 月 1 日に、Google Cloud blog に投稿されたものの抄訳です。
Cloud SQL for SQL Server 上で稼働しているデータベースにローカル タイムゾーンを使用したいと考えている方は、ぜひこのブログをご覧ください。
Cloud SQL は、Microsoft SQL Server、MySQL、PostgreSQL 向けのフルマネージド リレーショナル データベース サービスです。Cloud SQL を使用することで、豊富な拡張機能コレクション、構成フラグ、デベロッパー エコシステムを備えた、使い慣れたリレーショナル データベースを運用しつつ、自己管理の煩わしさから解放されます。
Cloud SQL は、マネージド データベース サービスとして、SQL Server インスタンスの保護、パッチ適用、維持における運用オーバーヘッドの大幅な削減を可能にします。インスタンスの安定性と信頼性を実現する方法の 1 つは、ユーザーがコントロールする部分を減らすことです。sysadmin などの高い権限で SQL Server をインストール・管理することに慣れている DBA やデベロッパーにとって、これは新たな方法かもしれません。この場合、SQL Server インスタンスを意図したとおりに動かすには代替方法が必要となることがあります。
先日支援した、SQL Server データベースを Cloud SQL for SQL Server に移行したケースでは、移行評価の際、Cloud SQL for SQL Server はデフォルトで UTC タイムゾーンになっている一方、お客様の所在地は IST タイムゾーンであることがわかりました。このブログの執筆時点で、Cloud SQL for SQL Server ではインスタンス レベルでタイムゾーンの設定を変更することができません。どうすればよいでしょうか?
データベースのタイムゾーンの変更
SQL Server のユーザーがローカル タイムゾーンを取得するには、通常、GETDATE() 関数を INSERT / UPDATE ステートメントと使用するか、SELECT ステートメントの datetime 列へのデフォルト制約として使用します。
1. INSERT / UPDATE ステートメント:
または
2. デフォルトの制約:
Cloud SQL は UTC タイムゾーンを使用するので、上の DML ステートメントを使用するたびに Cloud SQL は各行に UTC 日時を挿入します。
選択したタイムゾーンで UTC タイムゾーンをオーバーライドするには、AT TIME ZONE 関数を使用できます。この関数は、inputdate をターゲット タイムゾーンの対応する datetimeoffset 値に変換します。
例を見ていきましょう。
前提事項
例に進む前に、以下を確認してください。
デフォルト ユーザーの構成を含め、Cloud SQL for SQL Server インスタンスを作成済みであること。
インスタンスを作成するとデフォルトのユーザー アカウントを構成するをご覧ください。SQL Server コマンドライン ツールをクライアントにインストール済みであること。
Cloud SQL インスタンスに接続済みであること。接続オプションとその選択方法については、接続オプションのページをご覧ください。
Cloud SQL for SQL Server インスタンスで稼働するデータベースに接続したら、現在のタイムゾーンを確認します。


タイムゾーンが UTC に設定されていることを確認します。
サンプルのチュートリアル
データベースに datetime 列のあるテーブルを作成します。
テーブルにデータを挿入します。
テーブルを選択して、データが UTC タイムゾーンに保存されていることを確認します。


次のように SalesDate をローカル タイムゾーン(この例では IST タイムゾーン)で取得します。


上の SalesDate と SalesDateIST の違いを確認してください。
この手順は、ローカル タイムゾーンに基づくデータを取得する必要がある新規アプリケーションに適しています。すでに存在するテーブル内にローカル タイムを持つ既存のデータベースを移行する場合、Cloud SQL for SQL Server に挿入される新しいデータはデフォルトで UTC タイムゾーンになり、データ不整合の問題が生じます。この問題を解決するために、次のような現地時間を返す関数を作成します。
これで、次のコマンドを実行すると、SalesDateIST は IST タイムゾーンの SalesDate を返します。


上の SalesDate と SalesDateIST の違いを再度確認してください。
この関数では、任意のタイムゾーンでデータを挿入できます。
この関数を試すには、データをすべて削除し、dbo.udf_localdate 関数を使用してデータを再度挿入します。
これでデータが IST タイムゾーンとしてテーブルに挿入され、以下のとおり、クエリを行うときにこのデータを変換する必要がなくなりました。


この方法は、日付の値が INSERT / UPDATE ステートメントで指定されている場合に問題を部分的に解決します。ただし、テーブルで GETDATE() をデフォルト制約として使用している場合、値を指定しないと、UTC タイムゾーンの現在の日付が datetime 列に挿入されます(下の例参照)。
UTC タイムゾーンが SalesDate に反映されています。


デフォルト制約によって挿入された Datetime 値を、選択したタイムゾーンに設定するには、制約の GETDATE システム関数を先ほど定義した Localdate 関数で置き換えます。置き換えるには、既存のデフォルト制約を削除して、次のように再作成します。
テーブルを選択すると、IST タイムゾーンで挿入されたデータが表示されるようになりました。
SQL Server がサポートしているタイムゾーンの一覧を表示するには、次のコマンドを実行します。


まとめ
データベースを Cloud SQL for SQL Server に移行する場合は、タイムゾーンなどのサポートされている機能にご注意ください。お使いのアプリケーションが UTC 以外のタイムゾーンを使用している場合は、このブログで説明している回避策をご利用ください。そして、移行を成功させて、ビジネスの優先事項に注力しながら Cloud SQL のメリットをフル活用しましょう。
- Cloud セールス、カスタマー エンジニア Rishi Kapoor
- Google Cloud、プロダクト マネージャー Rahul Deshmukh

