web-dev-qa-db-ja.com

外部キータイプをcharからバイナリに移行します-フォールアウトに対処する方法?

私は、char/varcharフィールドを使用しているデータベースをスリム化しているところです。ここで、binary/varbinaryの方が適しています(データがバイト配列の場合)。

私が変更しているフィールドの1つは、他の多くのテーブルの外部キー制約で使用されています。

現在のFK制約を削除して、列を新しいタイプに移行し、データタイプが一致しないため、FK制約を再作成することはできません。

これを移行するにはどのようなアプローチを取るべきですか?それについてどう思いますか?

3
Oded

次の例を考えてみましょう:

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 ---(ここ

5
McNets

関係を維持するには、両方のデータのデータ型が同じである必要があります。

私が変更しているフィールドの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に取り込むことができますが、トリガーを使用する場合は注意してください。将来のアクションで必要な文書と注意です。

2