“ ป้องกันการเปลี่ยนแปลงการบันทึกที่ต้องการให้สร้างตารางใหม่” ผลกระทบเชิงลบ


255

คำนำ

ฉันแก้ไขคอลัมน์ใน SQL Server 2008 วันนี้เปลี่ยนประเภทข้อมูลจากสกุลเงิน (18,0) เป็น (19,2)

ฉันได้รับข้อผิดพลาด "การเปลี่ยนแปลงที่คุณทำต้องใช้ตารางต่อไปนี้เพื่อทำการดร็อปและสร้างใหม่" จาก SQL Server

ก่อนที่คุณจะตอบคำถามโปรดอ่านสิ่งต่อไปนี้:

ฉันรู้แล้วว่ามีตัวเลือกในเครื่องมือ►ตัวเลือก►ผู้ออกแบบ►นักออกแบบตารางและฐานข้อมูล►ยกเลิกการทำเครื่องหมายในช่อง "ป้องกันการบันทึกการเปลี่ยนแปลงที่ต้องมีการสร้างตารางใหม่" ป้องกันการบันทึกการเปลี่ยนแปลงที่ต้องสร้างตารางใหม่ในห้าคลิก ... ดังนั้นอย่าตอบด้วย!

คำถามจริง

คำถามจริงของฉันมีไว้สำหรับอย่างอื่นดังนี้:

มีผลเสีย / ข้อเสียที่เป็นไปได้ของการทำเช่นนี้หรือไม่?

จริง ๆ แล้วตารางจะถูกดร็อปและสร้างใหม่โดยอัตโนมัติเมื่อไม่ได้ทำเครื่องหมายในช่องนี้หรือไม่?

ถ้าเป็นเช่นนั้นตารางจะคัดลอกแบบจำลองที่แน่นอน 100% ของตารางต้นฉบับหรือไม่


65
เครื่องมือ> ตัวเลือก> ผู้ออกแบบ ... นั่นคือสิ่งที่ฉันกำลังมองหา! ขอบคุณ!
nrod


2
และถ้าคุณอยู่กับ MS SQL Server 2014 -> พิเศษ> ตัวเลือก> ผู้ออกแบบจากเมนูด้านบน
Vityata

คำตอบ:


89

ตารางจะถูกดร็อปและสร้างใหม่ในกรณีที่นั่นเป็นวิธีเดียวที่ Studio Studio จัดการของ SQL Server ได้รับการตั้งโปรแกรมให้รู้วิธีการทำ

มีบางกรณีที่มันจะทำอย่างนั้นเมื่อไม่ต้องการ แต่ก็มีหลายกรณีที่การแก้ไขที่คุณทำใน Management Studio จะไม่ลดลงและสร้างใหม่เพราะไม่จำเป็นต้องทำ

ปัญหาคือการแจกแจงทุกกรณีและการพิจารณาว่าด้านใดของเส้นที่พวกเขาตกลงจะค่อนข้างน่าเบื่อ

นี่คือเหตุผลที่ฉันชอบที่จะใช้ALTER TABLEในหน้าต่างแบบสอบถามแทนนักออกแบบภาพที่ซ่อนสิ่งที่พวกเขากำลังทำ (และค่อนข้างมีข้อบกพร่อง) - ฉันรู้ว่าสิ่งที่จะเกิดขึ้นและฉันสามารถเตรียมกรณีที่เป็นไปได้เท่านั้น คือการวางและสร้างตารางใหม่ (ซึ่งมีจำนวนน้อยกว่าความถี่ที่ SSMS จะทำกับคุณ)


5
ในขณะที่คำตอบที่ดีจริงๆฉันรู้สึกว่ามันไม่ได้ให้คำตอบสำหรับคำถามทั้งหมดที่ยกมาจาก OP และคำถามเหล่านั้นเป็นคำถามที่ฉันสนใจ โดยเฉพาะมีผลเสีย / ข้อเสียที่เป็นไปได้ในการทำเช่นนี้หรือไม่? และถ้าเป็นเช่นนั้นตารางจะคัดลอกแบบจำลองที่แน่นอน 100% ของตารางต้นฉบับหรือไม่ . คุณมีข้อมูลเกี่ยวกับคำถามเหล่านี้หรือไม่?
tfrascaroli

252

เครื่องมือ -> ตัวเลือก -> โหนดนักออกแบบ -> ยกเลิกการเลือก "ป้องกันการบันทึกการเปลี่ยนแปลงที่ต้องมีการเล่นตาราง"


12

การอ้างอิง - การปิดตัวเลือกนี้สามารถช่วยให้คุณหลีกเลี่ยงการสร้างตารางขึ้นมาใหม่ได้นอกจากนี้ยังสามารถนำไปสู่การเปลี่ยนแปลงที่สูญหายได้ ตัวอย่างเช่นสมมติว่าคุณเปิดใช้งานคุณลักษณะการติดตามการเปลี่ยนแปลงใน SQL Server 2008 เพื่อติดตามการเปลี่ยนแปลงของตาราง เมื่อคุณทำการดำเนินการที่ทำให้ตารางถูกสร้างขึ้นใหม่คุณได้รับข้อความแสดงข้อผิดพลาดที่กล่าวไว้ในส่วน "อาการ" อย่างไรก็ตามหากคุณปิดตัวเลือกนี้ข้อมูลการติดตามการเปลี่ยนแปลงที่มีอยู่จะถูกลบเมื่อสร้างตารางขึ้นใหม่ ดังนั้น Microsoft แนะนำให้คุณไม่แก้ไขปัญหานี้ด้วยการปิดตัวเลือก


11

SQL Server ทำการดร็อปและสร้างตารางใหม่เฉพาะเมื่อคุณ:

  • เพิ่มคอลัมน์ใหม่
  • เปลี่ยนการตั้งค่าอนุญาตให้ Nulls สำหรับคอลัมน์
  • เปลี่ยนลำดับคอลัมน์ในตาราง
  • เปลี่ยนชนิดข้อมูลคอลัมน์

การใช้ ALTER นั้นปลอดภัยกว่าในกรณีที่ข้อมูลเมตาหายไปในขณะที่คุณสร้างตารางขึ้นใหม่ข้อมูลของคุณจะหายไป


8
รายการของคุณไม่ครบถ้วนสมบูรณ์ IDENTITYตัวอย่างเช่นเพิ่ม / ลบคุณสมบัติในคอลัมน์
Aaron Bertrand

2
การเพิ่มคอลัมน์ใหม่ไปยังจุดสิ้นสุดของเขตข้อมูลที่เป็น NULLABLE ไม่จำเป็นต้องมีการสร้างตารางใหม่
PseudoToad

2

ใช่มีผลกระทบเชิงลบจากสิ่งนี้:

หากคุณสคริปต์การเปลี่ยนแปลงที่ถูกบล็อกโดยการตั้งค่าสถานะนี้คุณจะได้รับบางสิ่งบางอย่างเช่นสคริปต์ด้านล่าง (ฉันเปลี่ยนคอลัมน์ ID ใน Contact เป็นคอลัมน์ประจำตัวประชาชนโดยอัตโนมัติ แต่ตารางมีการขึ้นต่อกัน) หมายเหตุข้อผิดพลาดที่อาจเกิดขึ้นที่อาจเกิดขึ้นในขณะที่ทำงานต่อไปนี้:

  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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.