dnlnln / generate-sql-merge

Generate SQL MERGE statements with Table data

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Change FK with check when using @disable_constraints

vminds opened this issue · comments

Not sure if this is concerned an issue, or known by design. When requesting to disable the FK constraints (@disable_constraints param set to 1) it changes the with check option to with nocheck (so it will no longer validate the existing data integrity).
To be clear generate-sql-merge instructs:

ALTER TABLE dbo.Table1 NOCHECK CONSTRAINT ALL

ALTER TABLE dbo.Table1 CHECK CONSTRAINT ALL

For example:

-- original 
ALTER TABLE dbo.Table1  WITH CHECK ADD  CONSTRAINT [FK_Table1_Table2] FOREIGN KEY([tbl2Id])
REFERENCES dbo.Table2 ([Id])
GO

ALTER TABLE dbo.Table1 CHECK CONSTRAINT [FK_Table1_Table2]
GO

-- after executing ALTER TABLE dbo.Table1 NOCHECK CONSTRAINT ALL
ALTER TABLE dbo.Table1  WITH NOCHECK ADD  CONSTRAINT [FK_Table1_Table2] FOREIGN KEY([tbl2Id])
REFERENCES dbo.Table2 ([Id])
GO

ALTER TABLE dbo.Table1 NOCHECK CONSTRAINT [FK_Table1_Table2]
GO


-- after executing ALTER TABLE dbo.Table1 CHECK CONSTRAINT ALL
ALTER TABLE dbo.Table1  WITH NOCHECK ADD  CONSTRAINT [FK_Table1_Table2] FOREIGN KEY([tbl2Id])
REFERENCES dbo.Table2 ([Id])
GO

ALTER TABLE dbo.Table1 CHECK CONSTRAINT [FK_Table1_Table2]
GO


-- after executing ALTER TABLE dbo.Table1 WITH CHECK CHECK CONSTRAINT ALL
ALTER TABLE dbo.Table1  WITH CHECK ADD  CONSTRAINT [FK_Table1_Table2] FOREIGN KEY([tbl2Id])
REFERENCES dbo.Table2 ([Id])
GO

ALTER TABLE dbo.Table1 CHECK CONSTRAINT [FK_Table1_Table2]
GO

That's interesting. So, in this example, the state of the table is changed by simply neglecting to perform a check of the data upon re-enabling the constraint.

For background, @disable_constraints is one of the parameters that was inherited from the original project, sp_generate_inserts, so I can't be exactly sure what the intent behind this behaviour was.

As a developer, this seems like a bug: the state of the table structure ought not be changed by a tool that is focused on data movement. If it needs to temporarily modify the table in order to achieve its aim, then that's fine, but it should change it back to the way it was (whether that state was WITH CHECK or WITH NOCHECK) once the operation is complete.

@vminds I've submitted PR #62 to resolve this by including WITH CHECK when re-enabling table constraints. If you have a chance, would you be able to try the ensure-constraint-data-is-checked branch out and confirm whether this works as expected?

@readyroll This only works as expected if the table definition prior merge is specifying the "WITH CHECK" instruction, but not when "WITH NOCHECK". Chances are the original table definition is defined using "WITH NOCHECK" hence the merge script will alter its DDL. I guess you need to save that somehow into a variable so you can reuse it when done. I can have a closer look if you like, let me know.
image

@vminds Must admit I got a bit lazy with this one upon coming to the same realization as you, with respect to the need to capture the state of the "Check existing data on creation" property at runtime. The difficulty there is that the generated statements (i.e. ALTER TABLE [Table] NOCHECK CONSTRAINT; MERGE...; ALTER TABLE [Table] CHECK CONSTRAINT) are currently performed in separate batches. I'd prefer to avoid using temp tables if at all possible, so if you can think of a way that avoids that it would be great to hear.

The alternative solution would be to try and source the state of the property at design time (i.e. when the MERGE is generated), which would get around that particular problem but won't take into account different states in other target db environments. For my use cases, that would be an acceptable compromise but would be keen to hear your thoughts.

@readyroll I understand the complexity to address this in the current design. For me this is not a blocking problem btw, but decided to report it anyway. I believe we should not merge the branch to main though, as it does not fix the issue. Thanks.

@vminds #63 has now been raised which will preserve the WITH CHECK or WITH NOCHECK status of individual table constraints. If you have any feedback, please let me know