†闇† テーブル定義(SQLServer)に対する呪いの解呪法、そして蘇生の秘術

#はじめに
この記事は[闇の魔術に対する防衛術 Advent Calendar 2018](https://qiita.com/advent-calendar/2018/yami)の24日目の記事です。

#近況
現在、主業務でSQLServerを使ってるのですが、
今の会社は中途入社でして、入社する前のシステムに関しては何をやってきたのかはよくわからん状況なのですよ。
特に(自称)DBAっぽい動きをしてた人が入社の６年前に突然の失踪。ノー引き継ぎでフィニッシュしたらしく、
 **✨技術的負債ＭＡＸ✨** の状態からそれを切り戻すのが昨今の私のミッションとなっております。

#制約
弊社は上がＩＴに無理解なので、システムは原則、
24/365でダウンタイム０で動き続けると思っています。
当然、そんな事ができるわけはないのですが、一応そんな雰囲気は醸し出さないといけません。
いわゆるシュレディンガーの猫みたいなやつです。にゃーん。

#✨技術的負債ＭＡＸ✨　とは？
吉幾三先生の「俺ら東京さ行ぐだ」風にまとめると以下のような状態です。
・概要設計書も無ェ
・基本設計書も無ェ
・当然詳細設計書も無ェ
・テストもそれほど走って無ェ
・担当者も１人しか残って無ェ
・開発からそろそろ２０年

要はソースコードとデータしかないです。
入って思ったのは、「すげえ…　良く動いてたなこいつ！」みたいな感じ。

#へいしゃのでーたべーす
別に社外公開してるシステムでもないし、一応SELECT @@VERSIONした結果を貼っておきますね。
（あまり意味は無いとは思うけど）

```sql
SELECT @@VERSION
```
　　↓結果↓

```
Microsoft SQL Server 2014 (SP2-CU11) (KB4077063) - 12.0.5579.0 (X64) 
	Feb 21 2018 12:19:47 
	Copyright (c) Microsoft Corporation
	Standard Edition (64-bit) on Windows NT 6.3 <X64> (Build 9600: )
```

#ふういんされた　のろいが　いま　ときはなたれる！
で、テーブルのカラムの定義が今更間違ってたやつがある事がわかり、
カラムの定義を変えたい（int→Varchar2(3)）
※注:もともと入ってるのがMAX数字３桁であることは保証されている

という状況になったので、まあサクサクっとAlter Table Alter Column文を流し込んでみたのですよ。
すると…

```sql
Alter Table [hogehoge].[hogehogeテーブル] Alter Column hogehogeコード nvarchar(3)
```
　　↓結果↓

```
SQL   : Alter Table [hogehoge].[hogehogeテーブル] Alter Column hogehogeコード nvarchar(3)
SQL   : ALTER TABLE ALTER COLUMN hogehogeコード は失敗しました。1 つ以上のオブジェクトがこの列を参照しています。
オブジェクト 'UW_ZeroDefault' は 列 'hogehogeコード' に依存しています。
```
なんか依存性があって更新に失敗してるようです。
そしていろいろ調べたのですが、どうにもsys.sysobjectsとsys.columnsから情報を引いてもこの依存性が拾えませんでした。
（単純に私の調べ方が下手なのかもしれない）

よくわかんなくなってきたので[A5:SQL](https://a5m2.mmatsubara.com/)さんの力を借りて、テーブル定義を見てみたところ

```SQL
create table [hogehoge].[hogehogeテーブル] (
  hogehogeID int default CREATE DEFAULT hogehoge.UW_ZeroDefault AS 0 not null
  , hogehogeID2 int default CREATE DEFAULT hogehoge.UW_ZeroDefault AS 0
  , hogehogeID3 int default CREATE DEFAULT hogehoge.UW_ZeroDefault AS 0
  , hogehogeID4 int default CREATE DEFAULT hogehoge.UW_ZeroDefault AS 0
  , hogehogeID5 int default CREATE DEFAULT hogehoge.UW_ZeroDefault AS 0
  , hogehogeID6 int default CREATE DEFAULT hogehoge.UW_ZeroDefault AS 0
  , hogehogeID7 int default CREATE DEFAULT hogehoge.UW_ZeroDefault AS 0
(以下略)
  , primary key (hogehogeID)
);
```

なんか謎の定義がいっぱいおる。
「CREATE DEFAULT hogehoge.UW_ZeroDefault AS 0」って何なん！？
色々調べてみたところ、なんか移行マネージャを使ってAccessからテーブル引越をすると
現代に召喚されてしまう闇の魔術(※もはやよくわからない制約)だそうです。

実際、単純に「default 0」となっていればいいだけのところを何かの定義を嵌めてしまう模様。
もはや実質、のろいですやん…　(　ﾟдﾟ)ﾎﾟｶｰﾝ

なお、幾度の大戦を超えて生き残った伝説の戦士（※一人だけ残ってる担当者）に
古代の知恵（開発時から残っている属人的な知識みたいな情報がいっぱいあるので…）を伺っても
「よくわからない」というお返事が。

もう、どうしようもないので、解呪をこころみたいとおもいます。

#ささやき － いのり － えいしょう － ねんじろ！
いまわたしたちに必要なのは現代におけるカント寺院のアレです。
エクスペクト・パトローナムでもいいかもしれませんが。

今回、私たちは現代におけるカント寺院のアレの部分的な再現に成功しました！
以下、詳細なアレの手順を解説していきましょう。

##新しい魂(※データ)の入れものを創る
A5SQLで出てきたCREATE TABLE文を置換してアレしましょう。
(" CREATE DEFAULT hogehoge.UW_ZeroDefault AS " → NULL)します。

すると、普通にテーブル定義がDBで通せるようになりましたね。
テーブル名は仮に後ろにでも_WKとかつけておきましょう。
(移行して問題なかったらそのうち元データは消すので)

```SQL
create table [hogehoge].[hogehogeテーブル_WK] (
  hogehogeID int default 0 not null
  , hogehogeID2 int default 0
  , hogehogeID3 int default 0
  , hogehogeID4 int default 0
  , hogehogeID5 int default 0
  , hogehogeID6 int default 0
  , hogehogeID7 int default 0
(以下略)
  , primary key (hogehogeID)
);
```

## 蘇生の秘術を用いて魂(※データ)を救済(※データ移植)する
アレな秘術を使えば、綺麗な肉体に魂を移植する事ができますね。
(※綺麗すぎてオプティマイザ的にアレかもしれませんが気にせず対応。)
先の制約がある関係で、ここからはアキラ１００％顔負けレベルの早業が必要です。
控え目にいって **‡闇‡** を感じますが、気にしてはいけません。

まず**魂**(※データ)を移植します。

```SQL
INSERT INTO hogehogeテーブル_WK
 SELECT * 
 FROM   hogehogeテーブル
;
```

次に**老いた体**(※現行テーブル)の名前を変更します。
※この世界線にはsp_renameがあって本当によかった…

```SQL
sp_rename 'hogehogeDB.hogehogeテーブル', 'hogehogeテーブル_WK';
```

最後に**新しい体**(※新テーブル)の名前を**老いた体**(※現行テーブル)の名前に変更します。

```SQL
sp_rename 'hogehogeDB.hogehogeテーブル_WK', 'hogehogeテーブル';
```

これで魂が救済されましたね！　尊い…

#おわりに
結局のところ既存の定義がクソすぎてどうしようもない時は
サクッと新テーブル切って移植したほうが早い　という話でした。

今日はクリスマス・イブですね。
メリークルシミマス！（言いたかっただけ）