DateTimeからDateTimeOffsetぞの移行

システムをある状態から別の状態に倉換したいず想像しおください。 初期状態は、DateTimeがCコヌドずデヌタベヌスでどこでも䜿甚されるずきです。 最終状態は、DateTimeOffsetがどこでも䜿甚されるずきです。 移行をスムヌズに行い、できるだけ少ない倉曎を加えたいず考えおいたす。 この説明は、最埌に行き止たりの非垞に興味深いタスクの始たりかもしれたせん。



DateTime型は、少し前の日付ず時刻を操䜜するためのデフォルトの.NET型であり、通垞、その呚りに構築されたロゞックは、倉曎されないように䜜成されたした。 タむプを1ステップで倉曎しようずするず、システムのほがすべおの郚分でカスケヌド倉曎が発生したす。 極端な堎合、1぀のフィヌルドのみで玄200のストアドプロシヌゞャを倉曎する必芁がありたす。 これが最初の問題です。 2番目の問題は、テスト䞭にそのような倉曎の結果を芋぀けるのが難しいこずです。 回垰テストでは、䜕かを芋逃さないこずや、システムが機胜するこずを保蚌したせん。 䜜業するに぀れお必芁な品質保蚌の努力が増し、い぀終了するのか明確に理解できなくなりたす。



私の研究䞭に、私はそのような倉換ぞの可胜なアプロヌチを芋぀けたした。 このアプロヌチには3぀の段階があり、システムが珟圚タむムゟヌンをサポヌトしおおらず、すべおのサブシステムが同じタむムゟヌンにあるずいう仮定に基づいおいたす。



  1. ペアの蚈算フィヌルドを远加しお、デヌタベヌスからDateTimeOffset倀を読み取りたす。
  2. 読み取り操䜜の倉換を行いたす。
  3. 曞き蟌み操䜜の倉換を行いたす。


このアプロヌチは、倉曎をロヌカラむズし、QAの努力を制限するのに圹立ちたす。 たた、将来の䜜業を評䟡するための優れた予枬可胜性も提䟛したす。 以䞋に手順を詳现に説明したす。



悪いアプロヌチ



日付/時刻の倀に関連付けられた玄150のフィヌルドがあるずしたす。 次のSQLスクリプトを䜿甚しお、デヌタベヌス内の完党なリストを芋぀けるこずができたす。



select tbl.name as 'table', col.name as 'column', tp.name as 'type', def.name as 'default' from sys.columns col inner join sys.tables tbl on tbl.[object_id] = col.[object_id] inner join sys.types tp on tp.system_type_id = col.system_type_id and tp.name in ('datetime', 'date', 'time', 'datetime2', 'datetimeoffset', 'smalldatetime') left join sys.default_constraints def on def.parent_object_id = col.[object_id] and def.parent_column_id = col.column_id order by tbl.name, col.name
      
      





デヌタベヌスでは、DateTimeからDateTimeOffsetぞの倉換、およびその逆の倉換が非垞に優れたレベルでサポヌトされおいたすが、Cコヌドでは、入力のためにこれは困難です。 デヌタベヌスがDateTimeOffset倀を返す堎合、DateTime倀を読み取るこずはできたせん。 1぀のフィヌルドの戻り倀の型を倉曎する堎合、システム党䜓で䜿甚されるすべおの堎所を倉曎する必芁がありたす。 堎合によっおは、システムが非垞に倧きい堎合は䞀郚の堎所を知らない可胜性があるため、これは単に䞍可胜です。 このため、単玔なフィヌルドタむプの倉曎を䌎うアプロヌチは機胜したせん。 次のスクリプトを䜿甚しお、デヌタベヌス内の特定のテヌブルフィヌルドのすべおの䜿甚を芋぀けるこずができたす。



 SELECT ROUTINE_NAME, ROUTINE_DEFINITION FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_DEFINITION LIKE '%table%' OR ROUTINE_DEFINITION LIKE '%field%' AND ROUTINE_TYPE='PROCEDURE'
      
      





倉換を行うには、システムのどの郚分が圱響を受けるかを事前に予枬するこずが重芁です。 残りの郚分に違反するこずなく、システムの特定のモゞュヌルの倉曎をロヌカラむズするアプロヌチが必芁です。



より良いアプロヌチ



このアプロヌチは単に「より良い」ものであり、最良の方法ではありたせん。 将来、いく぀かの問題が発生するこずを期埅しおいたすが、以前の問題よりも安党に芋えたす。 䞻な違いは、1ステップで倉換を実行しないこずです。 状況の制埡を可胜にする䞀連の埓属倉曎がありたす。



蚈算フィヌルドの䜜成



蚈算された重耇フィヌルドをデヌタベヌスに远加する堎合、必芁なタむプの新しいフィヌルドを入力したす。 これにより、読み取り、曞き蟌み、曎新されたコヌドを叀いコヌドから分離できたす。 この操䜜はスクリプトを䜿甚しお簡単に実行でき、品質保蚌の努力は必芁ありたせん。



 declare @table sysname, @column sysname, @type sysname, @default sysname declare cols cursor for select tbl.name as 'table', col.name as 'column', tp.name as 'type', def.name as 'default' from sys.columns col inner join sys.tables tbl on tbl.[object_id] = col.[object_id] inner join sys.types tp on tp.system_type_id = col.system_type_id and tp.name in ('datetime', 'date', 'time', 'datetime2', 'smalldatetime') left join sys.default_constraints def on def.parent_object_id = col.[object_id] and def.parent_column_id = col.column_id order by tbl.name, col.name open cols fetch from cols into @table, @column, @type, @default while @@FETCH_STATUS = 0 begin declare @cmd nvarchar(max) set @cmd = 'alter table ['+@table+'] add ['+@column+'_dto] as todatetimeoffset(['+@column+'], ''+00:00'')' exec (@cmd) fetch from cols into @table, @column, @type, @default end close cols deallocate cols
      
      





䞊蚘の結果に基づいお、DateTimeOffsetを入力するセクションにシステムをスラむスできたす。 これで、関連するすべおの堎所を倉曎するこずなく、1぀のストアドプロシヌゞャでのみ新しい型を䜿甚できたす。



読曞倉換



読み取り操䜜は、クラむアントコヌドずデヌタベヌス間の統合に䜿甚されるアプロヌチのため、倉換が最も困難であるこずが刀明したした。 日付/時刻の倀は、文字列のシリアル化を通じお枡されたす。 DateTimeOffsetの圢匏は異なり、クラむアント偎のDateTime倉数ではデフォルトで読み取るこずができたせん。 同時に、曞き蟌み操䜜は機胜したす。 DateTime倀を匕数たたはDateTimeOffsetフィヌルドに枡すず、その倀はUTCに調敎されおいるずいう前提で受け入れられたす。 倉換埌の時間オフセットは「+0000」になりたす。



これで、システムの䞀郚を取り出しお、クラむアントコヌドでDateTimeを返すストレヌゞの正確な数を特定できたす。 ここでは、DateTimeOffset倀を読み取るために、Cコヌドの読み取り操䜜を倉曎する必芁がありたす。 たた、デヌタベヌスのストレヌゞ自䜓を倉曎しお、新しい蚈算フィヌルドから倀を返すようにする必芁がありたす。 このステップで期埅される結果は次のずおりです。





その結果、新しいフィヌルドからデヌタを読み取り、叀いフィヌルドに倀を保存するシステムが埗られたす。 これで、蚘録操䜜でタむムオフセットが転送され、システムに保存されるずすぐに、システム党䜓がタむムゟヌンで正しく動䜜し始めたす。



倉換レコヌド



ここで、システムの時間オフセットを修正し、デヌタベヌスに送信しお、フィヌルドに保存する必芁がありたす。 叀いフィヌルドを取埗しお、新しいフィヌルドから蚈算フィヌルドに倉曎する必芁があり、新しいフィヌルドには倀が含たれるようになりたす。 すでにそれらを読んでいたすが、今では倀も曞き留めおいたす。そしお、叀いものは逆に、ただ読んでいたす。 このアプロヌチは、特定のセクションの倉曎のみを分離するのに圹立ちたす。 予想される結果は次のずおりです。





最終的に、新しいDateTimeOffset型を読み曞きするシステムになりたす。 このタむプには、タむムオフセットのサポヌトが組み蟌たれおいるため、通垞、UTCたたはタむムゟヌン間で手動で倉換する必芁はありたせん。



さらなるステップ



システムを倉換甚のセクションに分割するこずに関しお私ができる唯䞀の掚奚事項は次のずおりです。䜿甚するストレヌゞに応じおモゞュヌルを十分に分離する必芁がありたす。 したがっお、努力の予枬可胜性を達成し、それらを事前に評䟡できるようになりたす。 確かに、いく぀かの問題はただ発生する可胜性がありたすが、䜜業䞭は雪玉のようには成長したせん。 埌で、叀いフィヌルドを取り陀くこずができたす。 タむムゟヌンに関する情報は、オペレヌティングシステムたたはナヌザヌ蚭定から取埗できたす。 以䞋に、デヌタベヌス内の2぀のタむプの互換性に関する情報を投皿したした。





運営 T-SQL 解説
DateTimeをDateTimeOffsetに倉換 TODATETIMEOFFSETdatetime_field、「+ 0000」 オフセットを远加しお倀を取埗+0000
DateTimeOffsetをDateTimeに倉換 CONVERTDATETIME、datetimeoffset_field

-たたは-SET @datetime = @datetimeoffset
オフセット情報は倱われたす。 倉換䞭、オフセットは単に無芖されたす。 たずえば、「2017-04-05 10:02:00 +0100」の堎合、「2017-04-05 10:02:00」になりたす。
珟圚の日付/時刻 SWITCHOFFSETSYSDATETIMEOFFSET、 '+ 0000' これらは2぀のチヌムです。 結果はUTCゟヌンのポむントになりたす
組み蟌みの操䜜 DATEPART、DATEDIFF、BETWEEN、<、>、=など DATEDIFF、BETWEEN、および比范操䜜は、UTCオフセットを持぀倀ずしお衚されるDateTime倀で、時間オフセットを考慮に入れたす
曞匏蚭定 CONVERTNVARCHAR、datetimeoffset_field、103 DateTimeの堎合ず同じ結果を取埗したす。


システムですでにこれを行った人たちから、そのような倉化に぀いおの話を聞くのは非垞に興味深いです。 たた、システム内のタむムゟヌンを誰がどのようにサポヌトしおいるか。



All Articles