เมื่อคุณเปลี่ยนคอลัมน์เป็น NOT NULL, SQL Server จะต้องแตะทุก ๆหน้าแม้ว่าจะไม่มีค่า NULL ก็ตาม ขึ้นอยู่กับปัจจัยการส่งของคุณสิ่งนี้อาจนำไปสู่การแยกหน้าได้เป็นจำนวนมาก แน่นอนว่าทุกหน้าที่ถูกแตะต้องเข้าสู่ระบบและฉันสงสัยว่าเนื่องจากการแยกที่ต้องทำการเปลี่ยนแปลงสองรายการสำหรับหลาย ๆ หน้า แม้ว่าจะทำเสร็จในรอบเดียว แต่บันทึกจะต้องพิจารณาการเปลี่ยนแปลงทั้งหมดเพื่อที่ว่าหากคุณกดยกเลิกก็จะรู้ว่าจะยกเลิกอะไร
ตัวอย่าง. ตารางง่าย ๆ :
DROP TABLE dbo.floob;
GO
CREATE TABLE dbo.floob
(
id INT IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
bar INT NULL
);
INSERT dbo.floob(bar) SELECT NULL UNION ALL SELECT 4 UNION ALL SELECT NULL;
ALTER TABLE dbo.floob ADD CONSTRAINT df DEFAULT(0) FOR bar
ตอนนี้เรามาดูรายละเอียดหน้า ก่อนอื่นเราต้องค้นหาว่าเพจใดและ DB_ID ที่เราติดต่อด้วย ในกรณีของฉันฉันสร้างฐานข้อมูลที่เรียกว่าfoo
และ DB_ID เกิดขึ้นเป็น 5
DBCC TRACEON(3604, -1);
DBCC IND('foo', 'dbo.floob', 1);
SELECT DB_ID();
ผลลัพธ์แสดงว่าฉันสนใจหน้า 159 (แถวเดียวในDBCC IND
เอาต์พุตด้วยPageType = 1
)
ตอนนี้เรามาดูรายละเอียดหน้าเลือกบางอย่างเมื่อเราผ่านสถานการณ์ของ OP
DBCC PAGE(5, 1, 159, 3);
UPDATE dbo.floob SET bar = 0 WHERE bar IS NULL;
DBCC PAGE(5, 1, 159, 3);
ALTER TABLE dbo.floob ALTER COLUMN bar INT NOT NULL;
DBCC PAGE(5, 1, 159, 3);
ตอนนี้ฉันไม่มีคำตอบทั้งหมดสำหรับเรื่องนี้เพราะฉันไม่ใช่คนเจ้าเล่ห์ แต่เป็นที่ชัดเจนว่า - ในขณะที่ทั้งการดำเนินการอัปเดตและการเพิ่มข้อ จำกัด NOT NULL อย่างปฏิเสธไม่ได้เขียนไปยังหน้า - หลังทำในลักษณะที่แตกต่างกันอย่างสิ้นเชิง ดูเหมือนว่าจะเปลี่ยนโครงสร้างของเรกคอร์ดแทนที่จะเป็นเพียงซอกับบิตโดยการสลับคอลัมน์ nullable สำหรับคอลัมน์ที่ไม่ใช่ null ทำไมต้องทำเช่นนั้นฉันไม่แน่ใจ - คำถามที่ดีสำหรับทีมเก็บข้อมูลฉันเดา ฉันเชื่อว่า SQL Server 2012 จัดการกับสถานการณ์เหล่านี้ได้ดีขึ้นมาก FWIW - แต่ฉันยังไม่ได้ทำการทดสอบใด ๆ
NOT NULL
คอลัมน์ที่มีค่าเริ่มต้นเป็นการดำเนินการข้อมูลเมตา ยังเห็น "การเพิ่มคอลัมน์ไม่เป็นโมฆะเป็นการดำเนินงานออนไลน์" ในเอกสาร