web-dev-qa-db-ja.com

「テーブルの再作成が必要な変更を保存しないようにする」悪影響

前文

今日、SQL Server 2008の列を変更して、データ型をcurrency(18,0)のようなものから(19,2)に変更しました。

SQL Serverから "変更を加えるには、次の表を削除して再作成する必要があります"というエラーが表示されました。

答える前に次を読んでください:

[ツール]►[オプション]►[デザイナ]►[テーブルとデータベースのデザイナ]►チェッ​​クボックスをオフにします "テーブルの再作成が必要な変更を保存しない"に、オプションがあることはすでにわかります。 Prevent saving changes that require table re-creation in five clicks ...だからと答えないでください!

実際の質問

私の実際の質問は、次のように、他の何かに対するものです。

これを行うことによる悪影響/考えられる欠点はありますか?

このチェックボックスをオフにすると、テーブルは実際に削除されて自動的に再作成されますか。

もしそうなら、そのテーブルはソーステーブルの100%正確なレプリカであるか?

238
CF_HoneyBadger

SQL ServerのManagement Studioがそれを実行する方法を知るためにプログラムされている唯一の方法である場合にのみ、テーブルは削除されて再作成されます。

そうでなくてもよい場合もあるでしょうが、Management Studioで編集した内容がnotdrop and re-willになることもあります。それはする必要がないので作成しなさい。

問題は、すべてのケースを列挙して、どちらに該当するかを判断するのは非常に面倒なことです。

自分がしていることを隠すビジュアルデザイナーの代わりに ALTER TABLE をクエリウィンドウで使用するのが好きなのはこのためです(そして率直に言ってバグがあります) - 何が起きるのかは正確にわかっています。テーブルを削除して再作成することが唯一の可能性である場合に備えて準備できます(これはSSMSがそれを行う頻度よりも少ない数です)。

86
Aaron Bertrand

「ツール」 - >「オプション」 - >「デザイナー」ノード - >「テーブルの再作成が必要な変更を保存しない」のチェックを外します。

247

参照 - このオプションをオフにすると、テーブルの再作成を避けることができます。変更が失われることに。たとえば、SQL Server 2008の変更追跡機能を有効にしてテーブルへの変更を追跡するとします。テーブルを再作成する原因となる操作を実行すると、「現象」に記載されているエラーメッセージが表示されます。ただし、このオプションをオフにすると、テーブルが再作成されたときに既存の変更追跡情報が削除されます。したがって、マイクロソフトでは、オプションをオフにしてこの問題を回避しないことをお勧めします。

11
user1499112

次の場合に限り、SQL Serverはテーブルを削除して再作成します。

  • 新しい列を追加
  • 列の[NULLを許可]設定を変更する
  • テーブル内の列の順序を変更する
  • 列のデータ型を変更する

テーブルの再作成中にメタデータが失われると、データが失われるため、ALTERを使用する方が安全です。

11

はい、これによる悪影響があります。

このフラグによってブロックされた変更をスクリプト化すると、以下のスクリプトのようになります(ContactのID列を自動番号付けされたIDENTITY列に変換していますが、テーブルには依存関係があります)。以下の実行中に発生する可能性のあるエラーに注意してください。

  1. Microsoftでも、これによりデータが失われる可能性があると警告しています(そのコメントは自動生成されます)。
  2. しばらくの間、外部キーは施行されません。
  3. これを手動でssmsで実行し、 'EXEC(' INSERT INTO 'が失敗し、以下のステートメントを実行させると(デフォルトでは' go 'で分割されているため)これらのステートメントは0行挿入されます。古いテーブル.
  4. これが大きなテーブルの場合、挿入のランタイムは大きくなる可能性があり、トランザクションはスキーマ変更ロックを保持しているため、manythingsをブロックします。

-

/* To prevent any potential data loss issues, you should review this script in detail before running it outside the context of the database designer.*/

BEGIN TRANSACTION
GO
ALTER TABLE raw.Contact
    DROP CONSTRAINT fk_Contact_AddressType
GO
ALTER TABLE ref.ContactpointType SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
BEGIN TRANSACTION
GO
ALTER TABLE raw.Contact
    DROP CONSTRAINT fk_contact_profile
GO
ALTER TABLE raw.Profile SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
BEGIN TRANSACTION
GO
CREATE TABLE raw.Tmp_Contact
    (
    ContactID int NOT NULL IDENTITY (1, 1),
    ProfileID int NOT NULL,
    AddressType char(2) NOT NULL,
    ContactText varchar(250) NULL
    )  ON [PRIMARY]
GO
ALTER TABLE raw.Tmp_Contact SET (LOCK_ESCALATION = TABLE)
GO
SET IDENTITY_INSERT raw.Tmp_Contact ON
GO
IF EXISTS(SELECT * FROM raw.Contact)
     EXEC('INSERT INTO raw.Tmp_Contact (ContactID, ProfileID, AddressType, ContactText)
        SELECT ContactID, ProfileID, AddressType, ContactText FROM raw.Contact WITH (HOLDLOCK TABLOCKX)')
GO
SET IDENTITY_INSERT raw.Tmp_Contact OFF
GO
ALTER TABLE raw.PostalAddress
    DROP CONSTRAINT fk_AddressProfile
GO
ALTER TABLE raw.MarketingFlag
    DROP CONSTRAINT fk_marketingflag_contact
GO
ALTER TABLE raw.Phones
    DROP CONSTRAINT fk_phones_contact
GO
DROP TABLE raw.Contact
GO
EXECUTE sp_rename N'raw.Tmp_Contact', N'Contact', 'OBJECT' 
GO
ALTER TABLE raw.Contact ADD CONSTRAINT
    Idx_Contact_1 PRIMARY KEY CLUSTERED 
    (
    ProfileID,
    ContactID
    ) 

GO
ALTER TABLE raw.Contact ADD CONSTRAINT
    Idx_Contact UNIQUE NONCLUSTERED 
    (
    ProfileID,
    ContactID
    ) 

GO
CREATE NONCLUSTERED INDEX idx_Contact_0 ON raw.Contact
    (
    AddressType
    ) 
GO
ALTER TABLE raw.Contact ADD CONSTRAINT
    fk_contact_profile FOREIGN KEY
    (
    ProfileID
    ) REFERENCES raw.Profile
    (
    ProfileID
    ) ON UPDATE  NO ACTION 
     ON DELETE  NO ACTION 

GO
ALTER TABLE raw.Contact ADD CONSTRAINT
    fk_Contact_AddressType FOREIGN KEY
    (
    AddressType
    ) REFERENCES ref.ContactpointType
    (
    ContactPointTypeCode
    ) ON UPDATE  NO ACTION 
     ON DELETE  NO ACTION 

GO
COMMIT
BEGIN TRANSACTION
GO
ALTER TABLE raw.Phones ADD CONSTRAINT
    fk_phones_contact FOREIGN KEY
    (
    ProfileID,
    PhoneID
    ) REFERENCES raw.Contact
    (
    ProfileID,
    ContactID
    ) ON UPDATE  NO ACTION 
     ON DELETE  NO ACTION 

GO
ALTER TABLE raw.Phones SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
BEGIN TRANSACTION
GO
ALTER TABLE raw.MarketingFlag ADD CONSTRAINT
    fk_marketingflag_contact FOREIGN KEY
    (
    ProfileID,
    ContactID
    ) REFERENCES raw.Contact
    (
    ProfileID,
    ContactID
    ) ON UPDATE  NO ACTION 
     ON DELETE  NO ACTION 

GO
ALTER TABLE raw.MarketingFlag SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
BEGIN TRANSACTION
GO
ALTER TABLE raw.PostalAddress ADD CONSTRAINT
    fk_AddressProfile FOREIGN KEY
    (
    ProfileID,
    AddressID
    ) REFERENCES raw.Contact
    (
    ProfileID,
    ContactID
    ) ON UPDATE  NO ACTION 
     ON DELETE  NO ACTION 

GO
ALTER TABLE raw.PostalAddress SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
2
Andrew Hill