Den overordnede proces vil sandsynligvis være meget langsommere med flere overordnede låseomkostninger, men hvis du kun bekymrer dig om størrelsen på transaktionsloggen, kan du prøve følgende.
- Tilføj en kolonne med null-heltal uden identitet (kun ændring af metadata).
- Skriv kode for at opdatere dette med unikke sekventielle heltal i batches. Dette vil reducere størrelsen af hver enkelt transaktion og holde logstørrelsen nede (forudsat en simpel gendannelsesmodel). Min kode nedenfor gør dette i batches af 100, forhåbentlig har du en eksisterende PK, du kan bruge til at fortsætte, hvor du slap, i stedet for de gentagne scanninger, der vil tage mere og mere lang tid mod slutningen.
- brug
ALTER TABLE ... ALTER COLUMN
for at markere kolonnen somNOT NULL
. Dette kræver, at hele tabellen låses og scannes for at validere ændringen, men det kræver ikke megen logning. - Brug
ALTER TABLE ... SWITCH
at gøre kolonnen til en identitetskolonne. Dette er kun en ændring af metadata.
Eksempelkode nedenfor
/*Set up test table with just one column*/
CREATE TABLE table_1 ( original_column INT )
INSERT INTO table_1
SELECT DISTINCT
number
FROM master..spt_values
/*Step 1 */
ALTER TABLE table_1 ADD id INT NULL
/*Step 2 */
DECLARE @Counter INT = 0 ,
@PrevCounter INT = -1
WHILE @PrevCounter <> @Counter
BEGIN
SET @PrevCounter = @Counter;
WITH T AS ( SELECT TOP 100
* ,
ROW_NUMBER() OVER ( ORDER BY @@SPID )
+ @Counter AS new_id
FROM table_1
WHERE id IS NULL
)
UPDATE T
SET id = new_id
SET @Counter = @Counter + @@ROWCOUNT
END
BEGIN TRY;
BEGIN TRANSACTION ;
/*Step 3 */
ALTER TABLE table_1 ALTER COLUMN id INT NOT NULL
/*Step 4 */
DECLARE @TableScript NVARCHAR(MAX) = '
CREATE TABLE dbo.Destination(
original_column INT,
id INT IDENTITY(' + CAST(@Counter + 1 AS VARCHAR) + ',1)
)
ALTER TABLE dbo.table_1 SWITCH TO dbo.Destination;
'
EXEC(@TableScript)
DROP TABLE table_1 ;
EXECUTE sp_rename N'dbo.Destination', N'table_1', 'OBJECT' ;
COMMIT TRANSACTION ;
END TRY
BEGIN CATCH
IF XACT_STATE() <> 0
ROLLBACK TRANSACTION ;
PRINT ERROR_MESSAGE() ;
END CATCH ;