Spanner は RDB のようにかっちりとスキーマを定義する DB なので、
Datastore などのように、プロパティをふわっと追加してデータ投入などできません。
RDB と同じように DDL を利用してカラム追加して利用しますが、
NOT NULL
のカラムの追加ができないという特性があります。
今回は以下のようなスキーマで考えます。
CREATE TABLE Member ( ID STRING(256) NOT NULL, Name STRING(256) NOT NULL, ) PRIMARY KEY (ID);
NOT NULL カラムが追加できないことを確認する
以下のようなクエリを実行し、 NOT NULL の制約のあるカラムを追加しようとしてみます
ALTER TABLE Member ADD COLUMN Nickname STRING(256) NOT NULL;
→ 実行すると、 NOT NULL なカラムは追加できないよ。
という感じに怒られてしまいます。
NULL 許可したカラムを追加してみる
NOT NULL なカラムは追加できないが、 Nullable なカラムは追加できるはずなので追加してみます。
ALTER TABLE Member ADD COLUMN Nickname STRING(256);
→ 問題なく追加できますね。
Nickname カラムをなんとか NOT NULL にしてみる
例えば、 NOT NULL にカラムを変更しようとしても、 Nullable なカラムを追加した状態では NULL が入っているので、変更は失敗するはず。
なので、 NULL な値をなくして、 NOT NULL なカラムに変更するというのを試してみる。
ためしに、 Nullable なカラムに NULL が入った状態で NOT NULL に 変更してみる。
ALTER TABLE Member ALTER COLUMN Nickname STRING(256) NOT NULL;
→ 予想通り Adding a NOT NULL constraint on a column Member.Nickname is not allowed because it has a NULL value at key: [xxx]
といった形で NULL な値があるので NOT NULL の制約はつけられないと怒られた
NULL 値を Empty String に置き換えてみる(なにか特定のデフォルト値でもいいと思います)
UPDATE Member SET Nickname = '' WHERE Nickname IS NULL;
NULL を置き換えたら NOT NULL 制約をつけてみる
ALTER TABLE Member ALTER COLUMN Nickname STRING(256) NOT NULL;
→ 結果うまく行きます。
最終的にこのようなテーブル構成になります
CREATE TABLE Member ( ID STRING(256) NOT NULL, Name STRING(256) NOT NULL, Nickname STRING(256) NOT NULL, ) PRIMARY KEY (ID)
NOT NULL なカラムを追加するための流れの要約
- NULL 許可する形でカラムを追加する
- NOT NULL にしたいカラムの場合には NULL ではない値にカラムを書き換える (注意点あり *1)
- NOT NULL 制約を満たせる状態になったら ALTER 文で改めてスキーマ変更する。
の3つの手順を経る必要がある。(default的なものがない)
注意(この点注意しましょう!!)
*1) カラム書き換えはUPDATEステートメントなどを利用するが、Spannerの制約で 20k 以上の変更が1クエリで行えないので注意。(また、20k はレコード数でもない点も注意すること)
まとめ
機能的には NOT NULL のカラムを追加することはできるようなのですが、最後の 注意
の点だけ気をつけましょう
運用が始まって大量のレコードが追加されているテーブルの場合、Spanner の一度に更新できる制限(20k)のために非常に大変なことになります
場合によってはパーティション DML を利用したりするのかな?(参考のリンク先参照)