266

前文

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

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

慌てて答える前に、以下をお読みください。

[ツール] ► [オプション] ► [デザイナー] ► [テーブルおよびデータベース デザイナー] ► [テーブルの再作成が必要な変更を保存しない] ボックスのチェックを外します。 5 回のクリックでテーブルの再作成が必要な変更を保存できないようにする ...だから、それで答えないでください!

実際の質問

私の実際の質問は、次のように別のものです。

これを行うことのマイナスの影響/考えられる欠点はありますか?

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

その場合、テーブル コピーはソース テーブルの 100% 正確なレプリカですか?

4

5 に答える 5

254

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

于 2014-06-19T16:21:30.637 に答える
93

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

必要がないときにそれが行われる場合は確かにありますが、Management Studio で行った編集が削除され、再作成されない場合もあります。

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

ALTER TABLEこれが、私が実行していることを隠す (そして率直に言ってバグがある) ビジュアル デザイナーの代わりに、クエリ ウィンドウで使用するのが好きな理由です。テーブルを削除して再作成することです (これは、SSMS がそれを行う頻度よりもいくらか少ない数です)。

これを行うことのマイナスの影響/考えられる欠点はありますか?

もちろん。テーブル全体を再構築せずに自分で変更のスクリプトを作成できる場合は、その方が適切です。テーブルが 10 TB で、データベースが大量にログに記録されている場合 (AG の同期、変更追跡、レプリケーション、不適切に作成されたトリガーを考えてください) を考えてみてください。アクセスが多い - これは災害の潜在的なレシピです。変更が、オンライン ヒントを適用したり、列を追加したり、GUI が行うオール オア ナッシングの代わりにデータをバッチでコピーできるものである場合は、これが優れています。

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

かもしれません。シナリオの長いリストがあり、結果は SSMS のバージョン、SQL Server のバージョン、および場合によってはエディションに依存します。チェックボックスをオンにして、最初にデータベースの無意味なコピーに変更を適用しようとすることで確認できますが、ポイントをクリックするだけの GUI の代わりに実際の ALTER TABLE スクリプトを使用するのが私見です。

その場合、テーブル コピーはソース テーブルの 100% 正確なレプリカですか?

はい、SSMS がテーブルを再構築する必要がある場合、それが完了した後は 100% 正確なレプリカになります (コースの変更を除く) が、それは来週の水曜日になる可能性があります。このプロセスでは、テーブルの新しいバージョンを作成し、そこにすべてのデータをコピーしてから、古いテーブルを削除し、新しいテーブルの名前を変更します。

于 2012-08-03T19:58:10.603 に答える
12

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

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

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

于 2012-09-04T20:47:50.297 に答える
12

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

于 2012-08-04T11:27:10.477 に答える
2

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

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

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

--

/* 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
于 2017-10-15T23:31:51.807 に答える