コンテンツに移動
データベース

Cloud SQL for SQL Server でローカル タイムゾーンを使う

2022年4月4日
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 インスタンスで稼働するデータベースに接続したら、現在のタイムゾーンを確認します。

読み込んでいます...

https://storage.googleapis.com/gweb-cloudblog-publish/images/1_local_timezone.max-1000x1000.jpg

タイムゾーンが UTC に設定されていることを確認します。

サンプルのチュートリアル

データベースに datetime 列のあるテーブルを作成します。

読み込んでいます...

テーブルにデータを挿入します。

読み込んでいます...

テーブルを選択して、データが UTC タイムゾーンに保存されていることを確認します。

読み込んでいます...

https://storage.googleapis.com/gweb-cloudblog-publish/images/2_local_timezone.max-900x900.jpg

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

読み込んでいます...

https://storage.googleapis.com/gweb-cloudblog-publish/images/3_local_timezone.max-600x600.jpg

上の SalesDateSalesDateIST の違いを確認してください。

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

読み込んでいます...

これで、次のコマンドを実行すると、SalesDateIST は IST タイムゾーンの SalesDate を返します。

読み込んでいます...

https://storage.googleapis.com/gweb-cloudblog-publish/images/4_local_timezone.max-600x600.jpg

上の SalesDateSalesDateIST の違いを再度確認してください。

この関数では、任意のタイムゾーンでデータを挿入できます。

この関数を試すには、データをすべて削除し、dbo.udf_localdate 関数を使用してデータを再度挿入します。

読み込んでいます...

これでデータが IST タイムゾーンとしてテーブルに挿入され、以下のとおり、クエリを行うときにこのデータを変換する必要がなくなりました。

読み込んでいます...

https://storage.googleapis.com/gweb-cloudblog-publish/images/5_local_timezone.max-900x900.jpg

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

読み込んでいます...

UTC タイムゾーンが SalesDate に反映されています。

https://storage.googleapis.com/gweb-cloudblog-publish/images/6_local_timezone.max-900x900.jpg

デフォルト制約によって挿入された Datetime 値を、選択したタイムゾーンに設定するには、制約の GETDATE システム関数を先ほど定義した Localdate 関数で置き換えます。置き換えるには、既存のデフォルト制約を削除して、次のように再作成します。

読み込んでいます...

テーブルを選択すると、IST タイムゾーンで挿入されたデータが表示されるようになりました。

読み込んでいます...

SQL Server がサポートしているタイムゾーンの一覧を表示するには、次のコマンドを実行します。

https://storage.googleapis.com/gweb-cloudblog-publish/images/7_local_timezone.max-900x900.jpg
読み込んでいます...

まとめ

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


- Cloud セールス、カスタマー エンジニア Rishi Kapoor
- Google Cloud、プロダクト マネージャー Rahul Deshmukh
投稿先