Generated script with IDENTITY INSERT fails
I'm changing a table schema (with IDENTITY PK) so that the migration has to drop and create the table.
The generated migration script in the ready roll project is:
the build generates the following in {_Package.sql}:
Executing this with vsts on azure database gives me the following error:
Msg 544, Level 16, State 1, Server XYZ, Line 1
Cannot insert explicit value for identity column in table 'RG_Recovery_1_XXX' when IDENTITY_INSERT is set to OFF.
I removed the GO statements in the migration script:
The build generates the script as following:
Which can be executed successfully.
The generated migration script in the ready roll project is:
CREATE TABLE [dbo].[RG_Recovery_1_XXX] ( [ID] [int] NOT NULL IDENTITY(1, 1), ... ) GO SET IDENTITY_INSERT [dbo].[RG_Recovery_1_XXX] ON GO INSERT INTO [dbo].[RG_Recovery_1_XXX]([ID], ...) SELECT [ID], ... FROM [dbo].[XXX] GO SET IDENTITY_INSERT [dbo].[RG_Recovery_1_XXX] OFF GO
the build generates the following in {_Package.sql}:
IF NOT EXISTS (SELECT 1 FROM [$(DatabaseName)].[dbo].[__MigrationLogCurrent] WHERE [migration_id] = CAST ('a412b234-714e-4f72-bd85-d885427b1020' AS UNIQUEIDENTIFIER)) EXECUTE ('CREATE TABLE [dbo].[RG_Recovery_1_XXX] ( [ID] [int] NOT NULL IDENTITY(1, 1), ... ) '); GO IF NOT EXISTS (SELECT 1 FROM [$(DatabaseName)].[dbo].[__MigrationLogCurrent] WHERE [migration_id] = CAST ('a412b234-714e-4f72-bd85-d885427b1020' AS UNIQUEIDENTIFIER)) EXECUTE ('SET IDENTITY_INSERT [dbo].[RG_Recovery_1_XXX] ON '); GO IF NOT EXISTS (SELECT 1 FROM [$(DatabaseName)].[dbo].[__MigrationLogCurrent] WHERE [migration_id] = CAST ('a412b234-714e-4f72-bd85-d885427b1020' AS UNIQUEIDENTIFIER)) EXECUTE ('INSERT INTO [dbo].[RG_Recovery_1_XXX]([ID], ...) SELECT [ID], ... FROM [dbo].[XXX] '); GO IF NOT EXISTS (SELECT 1 FROM [$(DatabaseName)].[dbo].[__MigrationLogCurrent] WHERE [migration_id] = CAST ('a412b234-714e-4f72-bd85-d885427b1020' AS UNIQUEIDENTIFIER)) EXECUTE ('SET IDENTITY_INSERT [dbo].[RG_Recovery_1_XXX] OFF ');
Executing this with vsts on azure database gives me the following error:
Msg 544, Level 16, State 1, Server XYZ, Line 1
Cannot insert explicit value for identity column in table 'RG_Recovery_1_XXX' when IDENTITY_INSERT is set to OFF.
I removed the GO statements in the migration script:
CREATE TABLE [dbo].[RG_Recovery_1_XXX] ( [ID] [int] NOT NULL IDENTITY(1, 1), ... ) GO SET IDENTITY_INSERT [dbo].[RG_Recovery_1_XXX] ON INSERT INTO [dbo].[RG_Recovery_1_XXX]([ID], ...) SELECT [ID], ... FROM [dbo].[XXX] SET IDENTITY_INSERT [dbo].[RG_Recovery_1_XXX] OFF GO
The build generates the script as following:
IF NOT EXISTS (SELECT 1 FROM [$(DatabaseName)].[dbo].[__MigrationLogCurrent] WHERE [migration_id] = CAST ('a412b234-714e-4f72-bd85-d885427b1020' AS UNIQUEIDENTIFIER)) EXECUTE ('EXECUTE ('SET IDENTITY_INSERT [dbo].[RG_Recovery_1_XXX] ON INSERT INTO [dbo].[RG_Recovery_1_XXX]([ID], ...) SELECT [ID], ... FROM [dbo].[XXX] EXECUTE ('SET IDENTITY_INSERT [dbo].[RG_Recovery_1_XXX] OFF ');
Which can be executed successfully.
Tagged:
Comments
I've confirmed that this is a defect in the current version of ReadyRoll (1.13.21). Unfortunately, I do not have a timeline for it's resolution at timeline at this stage.
I will update this thread once I have more information/resolution for the problem
Product Manager
Redgate Software
-- <Migration ID="02805588-769b-4448-8b22-4ce3445b9c0a" />
GO
PRINT N'Rebuilding [dbo].[Products]'
GO
CREATE TABLE [dbo].[RG_Recovery_1_Products]
(
[Id] [int] NOT NULL IDENTITY(1, 1),
[ProductCode] [nchar] (10) NOT NULL,
[ProductName] [nchar] (10) NOT NULL
)
GO
SET IDENTITY_INSERT [dbo].[RG_Recovery_1_Products] ON
GO
INSERT INTO [dbo].[RG_Recovery_1_Products]([Id], [ProductCode], [ProductName]) SELECT [Id], [ProductCode], [ProductName] FROM [dbo].[Products]
GO
SET IDENTITY_INSERT [dbo].[RG_Recovery_1_Products] OFF
GO
DROP TABLE [dbo].[Products]
GO
EXEC sp_rename N'[dbo].[RG_Recovery_1_Products]', N'Products', N'OBJECT'
GO
PRINT N'Creating primary key [PK_Products] on [dbo].[Products]'
GO
ALTER TABLE [dbo].[Products] ADD CONSTRAINT [PK_Products] PRIMARY KEY CLUSTERED ([Id])
GO
and I received the following error message in the log during my VSTS release execution:
2017-07-24T22:10:49.4711906Z ***** EXECUTING MIGRATION "Migrations\0007_Add_UnitPrice_Products.sql", ID: {f337cc1b-48e7-4d23-b671-6bd7deb814f6} *****
2017-07-24T22:10:49.5301889Z Dropping constraints from [dbo].[Products]
2017-07-24T22:10:49.6488548Z Rebuilding [dbo].[Products]
2017-07-24T22:10:49.8333832Z Msg 544, Level 16, State 1, Server SQL01DEV, Line 1
2017-07-24T22:10:49.8333832Z Cannot insert explicit value for identity column in table 'RG_Recovery_1_Products' when IDENTITY_INSERT is set to OFF.
2017-07-24T22:10:49.8919681Z ##[error]A deployment error occurred: sqlcmd.exe exited with a non-zero exit code.
2017-07-24T22:10:49.9019653Z ##[error]System.Management.Automation.RuntimeException: sqlcmd.exe exited with a non-zero exit code. ---> System.Management.Automation.RuntimeException: sqlcmd.exe exited with a non-zero exit code.
2017-07-24T22:10:49.9019653Z --- End of inner exception stack trace ---
2017-07-24T22:10:49.9019653Z at System.Management.Automation.Runspaces.PipelineBase.Invoke(IEnumerable input)
2017-07-24T22:10:49.9019653Z at System.Management.Automation.PowerShell.Worker.ConstructPipelineAndDoWork(Runspace rs, Boolean performSyncInvoke)
2017-07-24T22:10:49.9019653Z at System.Management.Automation.PowerShell.Worker.CreateRunspaceIfNeededAndDoWork(Runspace rsToUse, Boolean isSync)
2017-07-24T22:10:49.9019653Z at System.Management.Automation.PowerShell.CoreInvokeHelper[TInput,TOutput](PSDataCollection`1 input, PSDataCollection`1 output, PSInvocationSettings settings)
2017-07-24T22:10:49.9019653Z at System.Management.Automation.PowerShell.CoreInvoke[TInput,TOutput](PSDataCollection`1 input, PSDataCollection`1 output, PSInvocationSettings settings)
2017-07-24T22:10:49.9019653Z at Microsoft.TeamFoundation.DistributedTask.Handlers.LegacyVSTSPowerShellHost.VSTSPowerShellHost.Main(String[] args)
2017-07-24T22:10:51.4350652Z ##[error]LegacyVSTSPowerShellHost.exe completed with return code: -1.
I removed the GO statements as in the previous post but it did not solve my problem. This is very frustrating as it is preventing our release from executing.
***** EXECUTING MIGRATION "Migrations\0006_Add_Identity_And_PK_To_Products.sql", ID: {02805588-769b-4448-8b22-4ce3445b9c0a} *****';
GO
IF NOT EXISTS (SELECT 1 FROM [$(DatabaseName)].[dbo].[__MigrationLogCurrent] WHERE [migration_id] = CAST ('02805588-769b-4448-8b22-4ce3445b9c0a' AS UNIQUEIDENTIFIER))
EXECUTE ('
PRINT N''Rebuilding [dbo].[Products]''
');
GO
IF NOT EXISTS (SELECT 1 FROM [$(DatabaseName)].[dbo].[__MigrationLogCurrent] WHERE [migration_id] = CAST ('02805588-769b-4448-8b22-4ce3445b9c0a' AS UNIQUEIDENTIFIER))
EXECUTE ('CREATE TABLE [dbo].[RG_Recovery_1_Products]
(
[Id] [int] NOT NULL IDENTITY(1, 1),
[ProductCode] [nchar] (10) NOT NULL,
[ProductName] [nchar] (10) NOT NULL
)
');
GO
IF NOT EXISTS (SELECT 1 FROM [$(DatabaseName)].[dbo].[__MigrationLogCurrent] WHERE [migration_id] = CAST ('02805588-769b-4448-8b22-4ce3445b9c0a' AS UNIQUEIDENTIFIER))
EXECUTE ('SET IDENTITY_INSERT [dbo].[RG_Recovery_1_Products] ON
');
GO
IF NOT EXISTS (SELECT 1 FROM [$(DatabaseName)].[dbo].[__MigrationLogCurrent] WHERE [migration_id] = CAST ('02805588-769b-4448-8b22-4ce3445b9c0a' AS UNIQUEIDENTIFIER))
EXECUTE ('INSERT INTO [dbo].[RG_Recovery_1_Products]([Id], [ProductCode], [ProductName]) SELECT [Id], [ProductCode], [ProductName] FROM [dbo].[Products]
');
GO
IF NOT EXISTS (SELECT 1 FROM [$(DatabaseName)].[dbo].[__MigrationLogCurrent] WHERE [migration_id] = CAST ('02805588-769b-4448-8b22-4ce3445b9c0a' AS UNIQUEIDENTIFIER))
EXECUTE ('SET IDENTITY_INSERT [dbo].[RG_Recovery_1_Products] OFF
');
GO
IF NOT EXISTS (SELECT 1 FROM [$(DatabaseName)].[dbo].[__MigrationLogCurrent] WHERE [migration_id] = CAST ('02805588-769b-4448-8b22-4ce3445b9c0a' AS UNIQUEIDENTIFIER))
EXECUTE ('DROP TABLE [dbo].[Products]
');
GO
IF NOT EXISTS (SELECT 1 FROM [$(DatabaseName)].[dbo].[__MigrationLogCurrent] WHERE [migration_id] = CAST ('02805588-769b-4448-8b22-4ce3445b9c0a' AS UNIQUEIDENTIFIER))
EXECUTE ('EXEC sp_rename N''[dbo].[RG_Recovery_1_Products]'', N''Products'', N''OBJECT''
');
GO
IF NOT EXISTS (SELECT 1 FROM [$(DatabaseName)].[dbo].[__MigrationLogCurrent] WHERE [migration_id] = CAST ('02805588-769b-4448-8b22-4ce3445b9c0a' AS UNIQUEIDENTIFIER))
EXECUTE ('PRINT N''Creating primary key [PK_Products] on [dbo].[Products]''
');
GO
IF NOT EXISTS (SELECT 1 FROM [$(DatabaseName)].[dbo].[__MigrationLogCurrent] WHERE [migration_id] = CAST ('02805588-769b-4448-8b22-4ce3445b9c0a' AS UNIQUEIDENTIFIER))
EXECUTE ('ALTER TABLE [dbo].[Products] ADD CONSTRAINT [PK_Products] PRIMARY KEY CLUSTERED ([Id])
');
This is the modification I had to make to the [DatabaseName]_Package.sql script in order to get it to work, I had to put the IDENTITY_INSERT statements inside the EXECUTE of the INSERT...SELECT statement:
***** EXECUTING MIGRATION "Migrations\0006_Add_Identity_And_PK_To_Products.sql", ID: {02805588-769b-4448-8b22-4ce3445b9c0a} *****';
GO
IF NOT EXISTS (SELECT 1 FROM [$(DatabaseName)].[dbo].[__MigrationLogCurrent] WHERE [migration_id] = CAST ('02805588-769b-4448-8b22-4ce3445b9c0a' AS UNIQUEIDENTIFIER))
EXECUTE ('
PRINT N''Rebuilding [dbo].[Products]''
');
GO
IF NOT EXISTS (SELECT 1 FROM [$(DatabaseName)].[dbo].[__MigrationLogCurrent] WHERE [migration_id] = CAST ('02805588-769b-4448-8b22-4ce3445b9c0a' AS UNIQUEIDENTIFIER))
EXECUTE ('CREATE TABLE [dbo].[RG_Recovery_1_Products]
(
[Id] [int] NOT NULL IDENTITY(1, 1),
[ProductCode] [nchar] (10) NOT NULL,
[ProductName] [nchar] (10) NOT NULL
)
');
GO
--IF NOT EXISTS (SELECT 1 FROM [$(DatabaseName)].[dbo].[__MigrationLogCurrent] WHERE [migration_id] = CAST ('02805588-769b-4448-8b22-4ce3445b9c0a' AS UNIQUEIDENTIFIER))
--EXECUTE ('SET IDENTITY_INSERT [dbo].[RG_Recovery_1_Products] ON');
GO
--IF NOT EXISTS (SELECT 1 FROM [$(DatabaseName)].[dbo].[__MigrationLogCurrent] WHERE [migration_id] = CAST ('02805588-769b-4448-8b22-4ce3445b9c0a' AS UNIQUEIDENTIFIER))
EXECUTE ('SET IDENTITY_INSERT [dbo].[RG_Recovery_1_Products] ON; INSERT INTO [dbo].[RG_Recovery_1_Products]([Id], [ProductCode], [ProductName]) SELECT [Id], [ProductCode], [ProductName] FROM [dbo].[Products]; SET IDENTITY_INSERT [dbo].[RG_Recovery_1_Products] OFF');
GO
--IF NOT EXISTS (SELECT 1 FROM [$(DatabaseName)].[dbo].[__MigrationLogCurrent] WHERE [migration_id] = CAST ('02805588-769b-4448-8b22-4ce3445b9c0a' AS UNIQUEIDENTIFIER))
--EXECUTE ('SET IDENTITY_INSERT [dbo].[RG_Recovery_1_Products] OFF');
GO
IF NOT EXISTS (SELECT 1 FROM [$(DatabaseName)].[dbo].[__MigrationLogCurrent] WHERE [migration_id] = CAST ('02805588-769b-4448-8b22-4ce3445b9c0a' AS UNIQUEIDENTIFIER))
EXECUTE ('DROP TABLE [dbo].[Products]
');
GO
IF NOT EXISTS (SELECT 1 FROM [$(DatabaseName)].[dbo].[__MigrationLogCurrent] WHERE [migration_id] = CAST ('02805588-769b-4448-8b22-4ce3445b9c0a' AS UNIQUEIDENTIFIER))
EXECUTE ('EXEC sp_rename N''[dbo].[RG_Recovery_1_Products]'', N''Products'', N''OBJECT''
');
GO
IF NOT EXISTS (SELECT 1 FROM [$(DatabaseName)].[dbo].[__MigrationLogCurrent] WHERE [migration_id] = CAST ('02805588-769b-4448-8b22-4ce3445b9c0a' AS UNIQUEIDENTIFIER))
EXECUTE ('PRINT N''Creating primary key [PK_Products] on [dbo].[Products]''
');
GO
IF NOT EXISTS (SELECT 1 FROM [$(DatabaseName)].[dbo].[__MigrationLogCurrent] WHERE [migration_id] = CAST ('02805588-769b-4448-8b22-4ce3445b9c0a' AS UNIQUEIDENTIFIER))
EXECUTE ('ALTER TABLE [dbo].[Products] ADD CONSTRAINT [PK_Products] PRIMARY KEY CLUSTERED ([Id])
');
This raises some questions...Why is EXECUTE being used? Why does it appear that the IDENTITY_INSERT command seem to be out of session of the INSERT...SELECT statement when using the EXECUTE commands that ReadyRoll generated as part of the build? Is there a way to tell ReadyRoll during the build to not use EXECUTE statements in the [DatabaseName]_Package.sql script?
You can see how this is a problem, having us change everywhere in the script where IDENTITY_INSERT command is being used defeats the purpose of us using ReadyRoll to generate the [DatabaseName]_Package.sql script. Any word from your developers as to how this can be solved? Thank you.
This is an issue we're aware of - as stated above post Daniel Nolan created a bug for it in ReadyRoll and there is ongoing work on fixing the issue within ReadyRoll itself but there hasn't been a release to fix it as of yet.
The workaround at this point is to go in to the Visual Studio project folder and edit the migration script directly (e.g. \\Projects\DatabaseProj1\DatabaseProj1\Migrations\002_20170728-1122_alex.bartley.sql) to remove the two GO statements - one after the initial SET IDENTITY INSERT ON and one before the final SET IDENTITY INSERT OFF .
Doing this means the change only needs to occur once and will then be deployed properly each time in the packages.
The deployment run in VS against the Shadow DB uses a different mechanism than the deployments - that's why this works initially for the developer but fails afterwards on deployment.
I hope this helps you get up and running and I'll post here when there is a fix available as well!
Kind regards,
Alex
Have you visited our Help Center?
IF NOT EXISTS (SELECT 1 FROM [$(DatabaseName)].[dbo].[__MigrationLogCurrent] WHERE [migration_id] = CAST ('02805588-769b-4448-8b22-4ce3445b9c0a' AS UNIQUEIDENTIFIER))
EXECUTE ('SET IDENTITY_INSERT [dbo].[RG_Recovery_1_Products] ON
INSERT INTO [dbo].[RG_Recovery_1_Products]([Id], [ProductCode], [ProductName]) SELECT [Id], [ProductCode], [ProductName] FROM [dbo].[Products]
SET IDENTITY_INSERT [dbo].[RG_Recovery_1_Products] OFF
');
GO
And yes, we are very anxious to find out our hear about the announcement when this gets fixed. Thanks again!
A quick update on this issue: we just released a new version of ReadyRoll that should resolve the SET IDENTITY_INSERT issue permanently.
However, for the moment, any existing projects will need to "opt in" to receive the fix. After updating your ReadyRoll client and build server (including the ReadyRoll.MSBuild NuGet package, if that applies to your project), make the following addition to your <ProjectName>.sqlproj file:
Please note that any projects you create after installing ReadyRoll 1.14.10 will automatically have this change in place, so no manual edits for new projects will be required from that point onwards.
Product Manager
Redgate Software