microsoft / DACExtensions

DACExtensions contains samples that extend Data-Tier Applications using DacFx. These samples include deployment contributors and static code analysis rules that can be used with Visual Studio as well as examples of how to use the DacFx public mode
MIT License
125 stars 41 forks source link

IgnoreColumnOrder not working with temporal tables #51

Closed kerwinc closed 8 months ago

kerwinc commented 4 years ago

Hi Guys,

We are experiencing major issues managing temporal tables through SSDT. One major issue is that simple column changes are causing table rebuilds.

Problem

Adding columns to temporal tables are triggering table rebuilds which is a big problem for realtime systems or tables with lots of data. IgnoreColumnOrder=True does not work for temporal tables. I tried configuring the desired behaviour by using a publish profile and specifying the property directly ( /p:IgnoreColumnOrder=true ) resulting in the same output.

Change Script Result:

PRINT N'Starting rebuilding table [dbo].[tb_Settings]...';

BEGIN TRANSACTION;

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

SET XACT_ABORT ON;

CREATE TABLE [dbo].[tmp_ms_xx_tb_Settings] (
    [SettingId]      INT                                         NOT NULL,
    [Key]            NVARCHAR (255)                              NOT NULL,
    [DisplayName]    NVARCHAR (255)                              NOT NULL,
    [Description]    NVARCHAR (MAX)                              NULL,
    [DateTimeValue2] DATETIME2 (2)                               NULL,
    [Value]          NVARCHAR (255)                              NULL,
    [SysStart]       DATETIME2 (2) GENERATED ALWAYS AS ROW START NOT NULL,
    [SysEnd]         DATETIME2 (2) GENERATED ALWAYS AS ROW END   NOT NULL,
    [DateValue]      DATETIME2 (2)                               NULL,
    CONSTRAINT [tmp_ms_xx_constraint_PK_SettingId1] PRIMARY KEY CLUSTERED ([SettingId] ASC),
    PERIOD FOR SYSTEM_TIME ([SysStart], [SysEnd])
)
WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE=[dbo].[tb_Settings_HISTORY], DATA_CONSISTENCY_CHECK=ON));

IF EXISTS (SELECT TOP 1 1
           FROM   [dbo].[tb_Settings])
    BEGIN
        IF EXISTS (SELECT TOP 1 1
                   FROM   [sys].[tables]
                   WHERE  [name] = N'tmp_ms_xx_tb_Settings'
                          AND SCHEMA_NAME(schema_id) = N'dbo'
                          AND temporal_type = 2)
            BEGIN
                ALTER TABLE [dbo].[tmp_ms_xx_tb_Settings] SET (SYSTEM_VERSIONING = OFF);
            END
        IF EXISTS (SELECT TOP 1 1
                   FROM   [sys].[periods]
                   WHERE  [period_type] = 1
                          AND OBJECT_ID('[dbo].[tmp_ms_xx_tb_Settings]', 'U') = object_id)
            BEGIN
                ALTER TABLE [dbo].[tmp_ms_xx_tb_Settings] DROP PERIOD FOR SYSTEM_TIME;
            END
        INSERT INTO [dbo].[tmp_ms_xx_tb_Settings] ([SettingId], [Key], [DisplayName], [Description], [Value], [DateTimeValue2], [SysStart], [SysEnd], [DateValue])
        SELECT   [SettingId],
                 [Key],
                 [DisplayName],
                 [Description],
                 [Value],
                 [DateTimeValue2],
                 [SysStart],
                 [SysEnd],
                 [DateValue]
        FROM     [dbo].[tb_Settings]
        ORDER BY [SettingId] ASC;
        ALTER TABLE [dbo].[tmp_ms_xx_tb_Settings]
            ADD PERIOD FOR SYSTEM_TIME (SysStart, SysEnd);
        ALTER TABLE [dbo].[tmp_ms_xx_tb_Settings] SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE=[dbo].[tb_Settings_HISTORY], DATA_CONSISTENCY_CHECK=ON));
    END

IF EXISTS (SELECT TOP 1 1
           FROM   [sys].[tables]
           WHERE  [name] = N'tb_Settings'
                  AND SCHEMA_NAME(schema_id) = N'dbo'
                  AND temporal_type = 2)
    BEGIN
        ALTER TABLE [dbo].[tb_Settings] SET (SYSTEM_VERSIONING = OFF);
    END

DROP TABLE [dbo].[tb_Settings];

EXECUTE sp_rename N'[dbo].[tmp_ms_xx_tb_Settings]', N'tb_Settings';

EXECUTE sp_rename N'[dbo].[tmp_ms_xx_constraint_PK_SettingId1]', N'PK_SettingId', N'OBJECT';

COMMIT TRANSACTION;

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

Testing

Tested using SQLPackage 18.5 and 18.5.1.

Please advise if this can be resolved in the next version of SQLPackage / DacFx.

ErikEJ commented 4 years ago

What is the definition of the column you are adding?

kerwinc commented 4 years ago
[DateTimeValue2] DATETIME2 (2) NULL,

Just re-ordering the columns in the temporal table triggers a rebuild. IgnoreColumnOrder works fine for normal tables.

dzsquared commented 8 months ago

closing instead of transferring since a duplicate exists on dacfx repo