What is the use of generated CHECK CONSTRAINT sql - sql-server

In SSMS, if I open a table with constraints, right click on one and select "Script Constraint As" > "CREATE TO", these are the lines that are generated automatically:
ALTER TABLE [dbo].[table] DROP CONSTRAINT [CK_table_col]
GO
ALTER TABLE [dbo].[table] WITH CHECK ADD CONSTRAINT [CK_table_col] CHECK (([col] IN('SUP', 'ADM')))
GO
ALTER TABLE [dbo].[table] CHECK CONSTRAINT [CK_table_col]
GO
I get what the first two lines do, that's not a problem. However, the CHECK CONSTRAINT at the end seems unclear. If I remove it, it still checks that the existing records match the new constraint. If I run the CHECK CONSTRAINT on it's own, it just tells me that the query succeeded... Why is it needed? What does it do?

A CONSTRAINT can be disabled, using NOCHECK. This cannot be done when you CREATE the CONSTRAINT, but has to be done explicitly afterwards, such as with the following:
ALTER TABLE dbo.MyTable NOCHECK CONSTRAINT chk_MyTable;
If you disable a constraint and then use the CREATE TO script option, then that would be reflected too. As such SSMS explicitly defines whether the constraint is to be checked or not afterwards. Although yes enforcing the CHECK is redundant, it creates consistent scripts.

Related

Add Check constraints in SQL Server: ADD CONSTRAINT vs ADD CHECK

I want use a check constraint for a column in any table in SQL Server 2008.
I would like give a qualified name to the check constraint.
I have seen several syntax version on how to create it:
ALTER TABLE [dbo].[Roles2016.UsersCRM] WITH CHECK
ADD CHECK (([Estado]=(4) OR [Estado]=(3) OR [Estado]=(2) OR [Estado]=(1)))
ALTER TABLE [dbo].[Roles2016.UsersCRM] WITH CHECK
ADD CONSTRAINT [CK_UsuariosCRM_Estado]
CHECK (([Estado]=(4) OR [Estado]=(3) OR [Estado]=(2) OR [Estado]=(1)))
What's difference ADD CHECK and ADD CONSTRAINT for a check constraint?
It is possible, but a very bad habit to add constraints without a name:
CREATE TABLE tbl(SomeColumn VARCHAR(10) DEFAULT('test'))
will create a CONSTRAINT with a random name. Better use this
CREATE TABLE tbl(SomeColumn VARCHAR(10) CONSTRAINT DF_YourTable_SomeColumm DEFAULT('test'))
This will do the same, but will name the constraint like you want it.
This is extremely important if you run upgrade scripts in deployed environments. Just imagine, you want to change a constraint later and the name of this constraint is all different on your customers machines... That's a real pain!
So: Always name your constraints!

Detect foreign key validity without enable it

I need a way to check if a constraint is valid or not, but I need not to enable it. I need to know if constraints are ok/wrong before enabling them.
If I use the usual code, at the same time I enable it:
alter table ATEST_B with check check constraint all
Otherwise if I use the nocheck clause, constraints are not checked:
alter table ATEST_B with check nocheck constraint all
Thanks
You can copy your actual table with dummy table and check your Constraint. If its ok then drop dummy table and constraint. Apply the same on the actual table.
SELECT * INTO A_DUMMY FROM ATEST_B
Run a query that tests for the data that would violate the constraint you want to check.
Looking forward I found DBCC command:
DBCC CHECKCONSTRAINTS ('fk_name')
The command returns all values that not respect the foreign key.It's a bit much detailed and I don't get yes/no answer, but it works fine.

Enable foreign key with Check existing data

I love foreign keys, but I'm running into one problem with them. I have a conversion program where I am disabling foreign keys to tables. The reason I'm doing this is so that I can reconvert all records in the main table, but leave the other tables dependent on that one untouched without having to reconvert them every time because they are HUGE.
I'm using these commands to disable and re-enable the foreign keys:
ALTER TABLE MyTable NOCHECK CONSTRAINT MyConstraint
ALTER TABLE MyTable CHECK CONSTRAINT MyConstraint
However, after I re-enable the constraint "Check Existing Data on Creation or Re-Enabling" is still set to No. I understand that it is set to No because I disabled the constraint, but by doing this it altered my database schema, which I don't like. I thought this would be considered re-enabling the constraint and would check the existing data, but apparently not.
Is there no way to change this with the ALTER TABLE command? I know I can if I drop the constraint and recreate it, but I'm not about to write the script to recreate every foreign key I have and maintain that.
I'm using SQL Server 2008 R2.
To re-enable a constraint:
-- Enable the constraint
ALTER TABLE MyTable
WITH CHECK CHECK CONSTRAINT MyConstraint
GO
Note: you have to specify CHECK twice to force a check that all foreign key values are valid.
FOREIGN KEY and CHECK constraints that are disabled are marked
is_not_trusted.These are viewable in the sys.check_constraints and
sys.foreign_keys catalog views. This means that the constraint is no
longer being verified by the system for all rows of the table. Even
when you re-enable the constraint, it will not reverify the existing
rows against the table unless you specify the WITH CHECK option of
ALTER TABLE. Specifying WITH CHECK marks the constraint as trusted
again.
Ref.: Guidelines for Disabling Indexes and Constraints
As noted in comments (for search engines), this corresponds to
sys.foreign_keys.is_not_trusted
in the catalog view

SQL Server check constraint

I have a table in my database and I did a: Script table as > Create to > query editor and some of my columns have this code:
ALTER TABLE [dbo].[TableName] WITH CHECK ADD CONSTRAINT [ConstraintName] FOREIGN KEY([ColumnName])
REFERENCES [dbo].[ForeignKeyTable] ([ColumnName])
GO
ALTER TABLE [dbo].[TableName] CHECK CONSTRAINT [ConstraintName2]
GO
What does the second constraint do? Other columns in the table only have the first constraint.
The second constraint turns on (activates) the check constraint. It is just template code from SSMS
It is possible to generate the create check constraints snippet with or without activating it (e.g. nocheck) - so that is itself one of 2 snippets. Because you opted for the constraints to end up activated, SSMS follows with the activation, not really caring if it was activated already or not. It doesn't really hurt and is just something SSMS does

Deleting a SQL row ignoring all foreign keys and constraints

I have a row in a table. This row has an ID column referenced in a few other tables with millions of rows. The SQL statement to delete the row always times out. From my design, I know the row I wish to delete is never referenced any where else. Hence I would like SQL to ignore having to check all other tables for a foreign key reference to this row and delete the row immediately. Is there a quick way to do this in SQL 2008?
Perhaps something along the lines of:
DELETE FROM myTable where myTable.ID = 6850 IGNORE CONSTRAINTS
Or something along those lines.
You can set the constraints on that table / column to not check temporarily, then re-enable the constraints. General form would be:
ALTER TABLE TableName NOCHECK CONSTRAINT ConstraintName
Then re-enable all constraints with
ALTER TABLE TableName CHECK CONSTRAINT ConstraintName
I assume that this would be temporary though? You obviously wouldn't want to do this consistently.
Yes, simply run
DELETE FROM myTable where myTable.ID = 6850
AND LET ENGINE VERIFY THE CONSTRAINTS.
If you're trying to be 'clever' and disable constraints, you'll pay a huge price: enabling back the constraints has to verify every row instead of the one you just deleted. There are internal flags SQL keeps to know that a constraint is 'trusted' or not. You're 'optimization' would result in either changing these flags to 'false' (meaning SQL no longer trusts the constraints) or it has to re-verify them from scratch.
See Guidelines for Disabling Indexes and Constraints and Non-trusted constraints and performance.
Unless you did some solid measurements that demonstrated that the constraint verification of the DELETE operation are a performance bottleneck, let the engine do its work.
Do not under any circumstances disable the constraints. This is an extremely stupid practice. You cannot maintain data integrity if you do things like this. Data integrity is the first consideration of a database because without it, you have nothing.
The correct method is to delete from the child tables before trying to delete the parent record. You are probably timing out because you have set up cascading deltes which is another bad practice in a large database.
I know this is an old thread, but I landed here when my row deletes were blocked by foreign key constraints. In my case, my table design permitted "NULL" values in the constrained column. In the rows to be deleted, I changed the constrained column value to "NULL" (which does not violate the Foreign Key Constraint) and then deleted all the rows.
I wanted to delete all records from both tables because it was all test data. I used SSMS GUI to temporarily disable a FK constraint, then I ran a DELETE query on both tables, and finally I re-enabled the FK constraint.
To disable the FK constraint:
expand the database object [1]
expand the dependant table object [2]
expand the 'Keys' folder
right click on the foreign key
choose the 'Modify' option
change the 'Enforce Foreign Key Constraint' option to 'No'
close the 'Foreign Key Relationships' window
close the table designer tab
when prompted confirm save changes
run necessary delete queries
re-enable foreign key constraint the same way you just disabled it.
[1] in the 'Object Explorer' pane, can be accessed via the 'View' menu option, or key F8
[2] if you're not sure which table is the dependant one, you can check by right clicking the table in question and selecting the 'View Dependencies' option.
This is the way to disable foreign key checks in MySQL. Not relevant to OP's question since they use MS SQL Server, but google search results do turn this up so here's for reference:
SET FOREIGN_KEY_CHECKS = 0;
/ Run your script /
SET FOREIGN_KEY_CHECKS = 1;
See if this helps, This is for ignoring the foreign key checks.
But deleting disabling this is very bad practice.
On all tables with foreign keys pointing to this one, use:
ALTER TABLE MyOtherTable NOCHECK CONSTRAINT fk_name
You can disable all of the constaints on your database by the following line of code:
EXEC sp_MSforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"
and after the runing your update/delete command, you can enable it again as the following:
EXEC sp_MSforeachtable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"
You could maybe disable and re-enable constraints:
http://sqlforums.windowsitpro.com/web/forum/messageview.aspx?catid=60&threadid=48410&enterthread=y
For the testing purpose only, I used the following command in MySQL to delete only one record from a table that has foreign key references.
SET FOREIGN_KEY_CHECKS = 0; -- Disabling foreign key checks before running the following query.
DELETE FROM table_name WHERE id = id_to_delete; -- Deleting a record from a table that has foreign key reference.
SET FOREIGN_KEY_CHECKS = 1; -- Enabling foreign key checks after running the above query.
Temporarily disable constraints on a table T-SQL, SQL Server
MSSQL
ALTER TABLE TableName NOCHECK CONSTRAINT ALL
ALTER TABLE TableName CHECK CONSTRAINT ALL
ALTER TABLE TableName NOCHECK CONSTRAINT FK_Table_RefTable
ALTER TABLE TableName CHECK CONSTRAINT FK_Table_RefTable
ref
DELETE FROM TableName
DBCC CHECKIDENT ('TableName', RESEED, 0)
MySql
SET FOREIGN_KEY_CHECKS = 0; -- Disable foreign key checking.
TRUNCATE TABLE [YOUR TABLE];
SET FOREIGN_KEY_CHECKS = 1;

Resources