私は、char
/varchar
フィールドを使用しているデータベースをスリム化しているところです。ここで、binary
/varbinary
の方が適しています(データがバイト配列の場合)。
私が変更しているフィールドの1つは、他の多くのテーブルの外部キー制約で使用されています。
現在のFK制約を削除して、列を新しいタイプに移行し、データタイプが一致しないため、FK制約を再作成することはできません。
これを移行するにはどのようなアプローチを取るべきですか?それについてどう思いますか?
次の例を考えてみましょう:
CREATE TABLE A
(
[ID] VARCHAR(10) NOT NULL,
CONSTRAINT [PK_A] PRIMARY KEY ([ID])
);
CREATE TABLE B
(
[ID] INT PRIMARY KEY,
[A_ID] VARCHAR(10) NOT NULL,
CONSTRAINT [FK_B] FOREIGN KEY ([A_ID]) REFERENCES A([ID])
);
CREATE TABLE C
(
[ID] INT PRIMARY KEY,
[A_ID] VARCHAR(10) NOT NULL,
CONSTRAINT [FK_C] FOREIGN KEY ([A_ID]) REFERENCES A([ID])
);
INSERT INTO A VALUES ('001'), ('010'), ('100');
INSERT INTO B VALUES (1, '001'), (2, '001'), (3, '010');
INSERT INTO C VALUES (4, '010'), (5, '100'), (6, '100');
0-データベースのバックアップ、バックアップ、バックアップ。
1- varcharをvarbinaryに変換しようとしているため、明示的な変換がないため、テーブルに新しい列を追加する必要があります。 注:nullablesにすることはできません。
ALTER TABLE A ADD [ID_VB] VARBINARY(10);
ALTER TABLE B ADD [A_ID_VB] VARBINARY(10);
ALTER TABLE C ADD [A_ID_VB] VARBINARY(10);
2-現在の値を新しい列にコピーします。
BEGIN TRANSACTION
UPDATE A SET [ID_VB] = CAST([ID] AS VARBINARY(10));
UPDATE B SET [A_ID_VB] = CAST([A_ID] AS VARBINARY(10));
UPDATE C SET [A_ID_VB] = CAST([A_ID] AS VARBINARY(10));
COMMIT TRANSACTION
3-現在の制約を削除:
ALTER TABLE B DROP CONSTRAINT [FK_B];
ALTER TABLE C DROP CONSTRAINT [FK_C];
ALTER TABLE A DROP CONSTRAINT [PK_A];
4-新しい値が正しいことを確認したら、実際の列を削除します。
ALTER TABLE A DROP COLUMN [ID];
ALTER TABLE B DROP COLUMN [A_ID];
ALTER TABLE C DROP COLUMN [A_ID];
5-新しい列の名前を古い名前に変更します。
EXEC sp_rename 'A.ID_VB', 'ID', 'COLUMN';
EXEC sp_rename 'B.A_ID_VB', 'A_ID', 'COLUMN';
EXEC sp_rename 'C.A_ID_VB', 'A_ID', 'COLUMN';
6-新しい列をNULL可能にしない:
ALTER TABLE A ALTER COLUMN [ID] VARBINARY(10) NOT NULL;
ALTER TABLE B ALTER COLUMN [A_ID] VARBINARY(10) NOT NULL;
ALTER TABLE C ALTER COLUMN [A_ID] VARBINARY(10) NOT NULL;
7-制約を再度追加します。
ALTER TABLE A ADD CONSTRAINT [PK_A] PRIMARY KEY ([ID]);
ALTER TABLE B ADD CONSTRAINT [FK_B] FOREIGN KEY ([A_ID]) REFERENCES A([ID]);
ALTER TABLE C ADD CONSTRAINT [FK_C] FOREIGN KEY ([A_ID]) REFERENCES A([ID]);
8-最終結果を確認します。
SELECT * FROM A;
SELECT * FROM B;
SELECT * FROM C;
| ID | | :---- | 0x303031 | | 0x303130 | | 0x313030 | ID | A_ID -:| :------- 1 | 0x303031 2 | 0x303031 3 | 0x303130 ID | A_ID -:| :------- 4 | 0x303130 5 | 0x313030 6 | 0x313030
db <> fiddle ---(ここ
関係を維持するには、両方のデータのデータ型が同じである必要があります。
私が変更しているフィールドの1つは、他の多くのテーブルの外部キー制約で使用されています。
だから私はこれを行う別の解決策を見ることができません:
テーブルAに新しい列を作成し、テーブルBの制約をこの新しい列に変更します。
1 - Create another column (colX) in table A
2 - Cast and repply date into column colX
3 - Remove constraint FK of table B
4 - Cast data type in table B
5 - Create a new constraint FK in table B with colX of table A
トリガーを作成して、この新しい列を表Aに取り込むことができますが、トリガーを使用する場合は注意してください。将来のアクションで必要な文書と注意です。