T-SQL foreign key check constraint - tsql

When you create a foreign key constraint in a table and you create the script in MS SQL Management Studio, it looks like this.
ALTER TABLE T1 WITH CHECK ADD CONSTRAINT FK_T1 FOREIGN KEY(project_id)
REFERENCES T2 (project_id)
GO
ALTER TABLE T1 CHECK CONSTRAINT FK_T1
GO
What I don't understand is what purpose has the second alter with check constraint.
Isn't creating the FK constraint enough? Do you have to add the check constraint to assure reference integrity ?
Another question: how would it look like then when you'd write it directly in the column definition?
CREATE TABLE T1 (
my_column INT NOT NULL CONSTRAINT FK_T1 REFERENCES T2(my_column)
)
Isn't this enough?

First it creates the constraint and here you can specify whether data allready in the table should be checked or not against your new constraint. WITH { CHECK | NOCHECK }
The second part specifies that the constraint is enabled. ALTER TABLE TableName { CHECK | NOCHECK } CONSTRAINT ConstraintName

The second statement is compelled by the "WITH CHECK" in the first statement. There is a setting you can toggle to not do this.

Related

With Check Option Postgresql

I have an ALTER TABLE statement, written in T-SQL (SQL Server):
ALTER TABLE myTable WITH CHECK ADD CONSTRAINT [FK_myTable_myColumn] FOREIGN KEY(myColumn) REFERENCES otherTable (Column)
If I want to translate this statement in Postgresql, how can I make this? Paying attention to WITH CHECK ADD CONSTRAINT
You need to
remove WITH CHECK - I don't know what this is supposed to do, but you can't have a "check constraint" together with a foreign key constraint in Postgres
use standard compliant identifiers (without the square brackets)
ALTER TABLE my_table
ADD CONSTRAINT fk_mytable_mycolumn
FOREIGN KEY(my_column) REFERENCES other_table (column)

How to alter a foreign key in postgresql

I created a table in PostgreSQL with a foreign key constraint.
I dropped the table to which the foreign key belongs. Now how to alter the table or how to defer the foreign key present in the table?
To clarify:
I have a table named test. It has a column called subjectName, which is a foreign key of subject Table. Now I dropped subject table. How to remove the FK constaint on table test
Assuming the following tables:
create table subject
(
name varchar(10) primary key
);
create table test
(
some_column integer,
subject_name varchar(10) not null references subject
);
there are two scenarios what could have happened when you dropped the table subject:
1. you didn't actually drop it:
drop table subject;
ERROR: cannot drop table subject because other objects depend on it
Detail: constraint test_subject_name_fkey on table test depends on table subject
Hint: Use DROP ... CASCADE to drop the dependent objects too.
2. you did drop it, then the foreign key is gone as well.
drop table subject cascade;
NOTICE: drop cascades to constraint test_subject_name_fkey on table test
which tells you that the foreign key constraint was automatically dropped.
Perhaps your question in not exactly what you mean. Are you wanting to remove the which was a foreign key from the table. As amply indicated if you dropped the parent table then the FK is also dropped. However the column itself is not dropped from the child table. To remove that you need to alter the table.
alter table test drop column subject_name;
See demo here

Make a previously existing foreign key column have a unique constraint in postgres

I need to create a migration for an already existing table to make it's foreign key have a UNIQUE constraint. How do I do this?
From the examples I found in the documentation, it is mostly done when the table is created. The issue is I need to add this onto a column that already exists and is already set as a foreign key. This is what the table looks like at it's creation:
CREATE TABLE IF NOT EXISTS "myTable" (
"_id" SERIAL NOT NULL,
"myForeignKeyId" INTEGER NOT NULL,
"name" VARCHAR(255) NOT NULL,
CONSTRAINT "pk_myTable" PRIMARY KEY ("_id"),
CONSTRAINT "fk_myTable_myForeignKeyId" FOREIGN KEY ("myForeignKeyId") REFERENCES "myOtherTable" ("_id")
);
What I want to do is on a migration make myForeignKeyId unique. How do I do that?
I have tried to following:
CREATE UNIQUE INDEX CONCURRENTLY "myTable_myForeignKeyId"
ON province ("myForeignKeyId");
ALTER TABLE IF EXISTS "myTable"
ADD CONSTRAINT "myForeignKeyId"
UNIQUE USING INDEX "myTable_myForeignKeyId";
First off, when I try this in a migration I get the error:
CREATE INDEX CONCURRENTLY cannot run inside a transaction block
So that part cannot be done, but even just doing it through SQL, the second part doesn't work either as it claims myForeignKeyId already exists. Even if I add an ALTER COLUMN myForeignKeyId it just says there is an error on that line.
This seems like it should be a simple enough operation, how can I do this?
After digging some more found quite a simple way to do this, was clearly originally off target.
To add a unique constraint to a column:
ALTER TABLE "myTable"
ADD CONSTRAINT "myUniqueKeyNameOfChoice" UNIQUE ("myColumn");
To remove it:
ALTER TABLE "myTable"
DROP CONSTRAINT "myUniqueKeyNameOfChoice";

How to alter "REFERENCES" in PostgreSQL?

How can I alter the reference to a table in PostgreSQL when the table name has been changed?
Say I have:
CREATE TABLE example1 (
id serial NOT NULL PRIMARY KEY,
name varchar(100)
);
CREATE TABLE example2 (
id serial NOT NULL PRIMARY KEY,
example1fk integer REFERENCES example1 (id) DEFERRABLE INITIALLY DEFERRED
);
Later I do:
ALTER TABLE example1 RENAME TO example3;
How to change the definition of the foreign key constraint?
example1fk integer REFERENCES example1 (id) DEFERRABLE INITIALLY DEFERRED,
Internal dependencies between tables and / or other objects are never bound to the object name. Internally, every object is stored in a catalog table and the OID (internal primary key) of the object is used for everything else.
Accordingly, a FOREIGN KEY reference is stored in the catalog tables pg_constraint (the constraint itself incl. its name) and pg_depend. Changing table names will not impair functionality at all.
The name of the constraint remains unchanged. You can ignore that, or you may want to rename the constraint so it's not misleading.
However, since you did not specify a constraint name at creation time, the system picked a default, which is example2_example1fk_fkey in your case unless the name was taken. No reference to the referenced table name. But the column name will likely have to change in your example, too. And that is used in the constraint name.
ALTER TABLE example2 RENAME example1fk TO example3fk; -- rename column
In Postgres 9.2 or later you can just rename the constraint as well (as dequis commented):
ALTER TABLE example2 RENAME CONSTRAINT example2_example1fk_fkey TO example2_example3fk_fkey;
In older versions, you have to drop and recreate the constraint to rename it, best in a single statement:
ALTER TABLE example2 -- rename constraint
DROP CONSTRAINT example2_example1fk_fkey
, ADD CONSTRAINT example2_example3fk_fkey FOREIGN KEY (example3fk)
REFERENCES example3 (id) DEFERRABLE INITIALLY DEFERRED;
Details in the manual.

ALTER TABLE [dbo].[MyTable] CHECK CONSTRAINT [FK_MyTable_SomeCol]

If I script a table with a foreign key, it looks like this:
GO
ALTER TABLE [dbo].[MyTable] WITH CHECK ADD CONSTRAINT [FK_MyTable_SomeCol] FOREIGN KEY([SomeCol])
REFERENCES [dbo].[MyOtherTable] ([SomeCol])
GO
ALTER TABLE [dbo].[MyTable] CHECK CONSTRAINT [FK_MyTable_SomeCol]
GO
What is the second part for (ALTER TABLE [dbo].[MyTable] CHECK CONSTRAINT [FK_MyTable_SomeCol])?
It's an artifact of the way that the constraint is scripted - although it's unnecessary to specify these options (since they're the defaults for new constraints), the same generator can also generate NOCHECK options in exactly the same manner.
Documentation for ALTER TABLE indicates two distinct uses of CHECK/NOCHECK:
WITH CHECK | WITH NOCHECK
Specifies whether the data in the table is or is not validated against a newly added or re-enabled FOREIGN KEY or CHECK constraint. If not specified, WITH CHECK is assumed for new constraints, and WITH NOCHECK is assumed for re-enabled constraints.
And:
{ CHECK | NOCHECK } CONSTRAINT
Specifies that constraint_name is enabled or disabled.
So one option is saying "check the current contents of the table", the other is saying "Validate new data as it is added".
This is a way of implementing referential integrity for your tables.