Should the second ALTER TABLE CHECK CONSTRAINT be in an IF (NOT) EXISTS so that the script can be executed repeatedly?
IF NOT EXISTS (
SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE CONSTRAINT_NAME ='fk_RoleId'
)
BEGIN
ALTER TABLE [dbo].[webpages_UsersInRoles] WITH CHECK ADD CONSTRAINT [fk_RoleId] FOREIGN KEY([RoleId])
REFERENCES [dbo].[webpages_Roles] ([RoleId])
END
GO
-- Put me in an IF ... () BEGIN ... END?
ALTER TABLE [dbo].[webpages_UsersInRoles] CHECK CONSTRAINT [fk_RoleId]
GO
It doesn't cause any errors, but if it should be in an IF clause, how do you test if it has been ran (what can the if contain)?
If you do want a check (it's not necessary), sys.foreign_keys has a column is_not_trusted:
FOREIGN KEY constraint has not been verified by the system.
Related
Parent table A with some records.
Child table B with 0 records.
I have a cursor to do truncation on these tables in reverse tree order (i.e. truncate child first, then parent)
But I'm still getting this error when I truncate the parent table 'ORA-02266: unique/primary keys in table referenced by enabled foreign keys' error, despite the fact that the child table has no records at all.
However, when I do 'Delete from ' in the same order, all constraint related errors were avoided. And 'Delete from' takes really long time to run.
I don't want to disable or drop any constraints.
However, when I do 'Delete from ' in the same order, all constraint related errors were avoided.
That's the only way if you have constraints enabled. You cannot truncate. If you still want to truncate the table, then you could find the constraint name from user_constraints, and then DISABLE them:
ALTER TABLE table_name DISABLE CONSTRAINT constraint_name;
Then you could TRUNCATE the table, and re-enable the constraint:
ALTER TABLE table_name ENABLE CONSTRAINT constraint_name;
If your table has ON DELETE CASCADE option, then from Oracle 12.1 onward, you could use:
TRUNCATE TABLE table_name CASCADE;
Note, both the DELETE CASCADE and the TRUNCATE CASCADE will fail if any of the relationships in the hierarchy are not defined with the ON DELETE CASCADE clause.
There are three ways to delete from parent/child tables:
CREATE TABLE par (i NUMBER CONSTRAINT par_pk PRIMARY KEY);
CREATE TABLE chi (i NUMBER CONSTRAINT chi_fk REFERENCES par(i) ON DELETE CASCADE);
INSERT INTO par VALUES(1);
INSERT INTO chi VALUES(1);
1) If you have Oracle 12 or later, and you have foreign keys with ON DELETE CASCADE, you can use TRUNCATE CASCADE, which I expect to be the fastest option:
TRUNCATE TABLE par CASCADE;
Table PAR truncated.
SELECT count(*) FROM par;
0
SELECT count(*) FROM chi;
0
2) If your foreign keys are defined with ON DELETE CASCADE, you can use DELETE, which I expect to be the slowest option:
DELETE FROM par;
1 row deleted.
SELECT count(*) FROM par;
0
SELECT count(*) FROM chi;
0
3) Otherwise, you can disable the foreign keys, truncate the tables and reenable the foreign keys. This is fast, but is a little bit more risky than the other options (please check that the constraints are all valid afterwards):
ALTER TABLE chi DISABLE CONSTRAINT chi_fk;
TRUNCATE TABLE chi;
TRUNCATE TABLE par;
ALTER TABLE chi ENABLE CONSTRAINT chi_fk;
AFAIK, it is not possible to alter a foreign key from normal to ON DELETE CASCADE. I guess you have to drop and recreate them:
ALTER TABLE chi DROP CONSTRAINT chi_fk;
ALTER TABLE chi ADD CONSTRAINT chi_fk REFERENCES par(i) ON DELETE CASCADE;
If I know that the table exists but I don't know whether the foreign key constraint exists, then I can do this:
ALTER TABLE table_name DROP CONSTRAINT IF EXISTS constraint_name
What if I don't know whether the table itself exists? I want a single statement that has outcomes as follows:
if (the table does not exist)
{
nothing happens
}
else if (the table exists, but the foreign key constraint does not exist)
{
nothing happens
}
else
{
the foreign key constraint is dropped, but the table continues to exist
}
As far as your question is concerned, and as commented by Dale K, you can't do that in a single statement.
Instead, one option is to first check catalog table information_schema.referential_constraints for the existence of the constraint before attempting to drop it, like:
if (exists (
select 1
from information_schema.referential_constraints
where constraint_name = 'myconstraint'
))
begin
alter table mytable drop constraint myconstraint;
end
If the table does not exist, then the if condition will not be satisfied, and the alter table statement will not run.
Note that you might want to add a filter on the constraint_schema column of referential_constraints (since constraints of the same name may exist in different schemas).
I need to alter an existing foreign key from "on delete restrict" to "on delete cascade". Unfortunaltey this bug sneaked through Q/A.
In my database I have several forign key relationships that were automatically named (INTEG_1, INTEG_2, ...). The name of the constraint I have to fix is another in a new installation than in an Update from Version 2 and even another than when this Version 2 previously has been updated from Version 1.
As the referencing table only has one foreign key, this statement gives me the name of the constraint:
SELECT RDB$CONSTRAINT_NAME
FROM RDB$RELATION_CONSTRAINTS
where RDB$CONSTRAINT_TYPE = 'FOREIGN KEY'
and RDB$RELATION_NAME = 'MY_TABLE_NAME'
then I can drop and afterwards recreate the foreign key (with a "real" name this time)
alter table MY_TABLE_NAME
drop constraint <result from above>;
alter table MY_TABLE_NAME
add constraint fk_my_table_name_purpose foreign key (other_id)
references other_table(id) on delete cascade;
However, I try to avoid working directly with system tables and I'd like to know whether there is a better / more elegant way to alter my foreign key.
There's no better way, the system tables are the only way to figure out the constraint name.
I'm trying to drop a table in Northwind, and I'm getting:
ALTER TABLE DROP COLUMN Region failed because one or more objects access this column.
I'm using:
use [NorthWind]
go
alter table dbo.Customers
drop column Region
I guess it's because there is a constraint on the column Region. How do I find out which constraint I need to remove?
EXEC sp_MSforeachtable #command1="ALTER TABLE ? NOCHECK CONSTRAINT ALL"
GO
OR
ALTER TABLE table_Name NOCHECK CONSTRAINT all
OR
ALTER TABLE table_Name NOCHECK CONSTRAINT constraint_name
Then try with your SQL.
Please use this when you really want to drop constraints no matter other tables affected.
If disabling the constraints is not enough, you will have to drop the constraints.
You must drop Constraint first and then drop the table.If you have SQL Server Management Studio you can select the constraint and delete it using GUI. Or you can use command line to drop your constraints
How to remove foreign key constraint in sql server?. Taken from this answer
ALTER TABLE <TABLE_NAME> DROP CONSTRAINT <FOREIGN_KEY_NAME>
If you want to go via Sql Server Management Studio on the object explorer window, right click on the object you want to drop,then click view dependencies.
First, you should know the ForeignKey - Constraint. After that, you must drop it.
Something like this:
-- looking for the Constraint's name related the dbo.Customers table
SELECT Table_Name,Constraint_Name
FROM Information_Schema.CONSTRAINT_TABLE_USAGE
WHERE Table_Name 'Customers'
-- Drop/Delete the founded constraint
ALTER TABLE [dbo].[Customers] DROP CONSTRAINT [FOREIGN_KEY_NAME]
Then, you'll run your actual script.
I have a foreign key constraint in my table, I want to add ON DELETE CASCADE to it.
I have tried this:
alter table child_table_name
modify constraint fk_name
foreign key (child_column_name)
references parent_table_name (parent_column_name) on delete cascade;
Doesn't work.
EDIT:
Foreign key already exists, there are data in foreign key column.
The error message I get after executing the statement:
ORA-02275: such a referential constraint already exists in the table
You can not add ON DELETE CASCADE to an already existing constraint. You will have to drop and re-create the constraint. The documentation shows that the MODIFY CONSTRAINT clause can only modify the state of a constraint (i-e: ENABLED/DISABLED...).
First drop your foreign key and try your above command, put add constraint instead of modify constraint.
Now this is the command:
ALTER TABLE child_table_name
ADD CONSTRAINT fk_name
FOREIGN KEY (child_column_name)
REFERENCES parent_table_name(parent_column_name)
ON DELETE CASCADE;
As explained before:
ALTER TABLE TABLENAME
drop CONSTRAINT FK_CONSTRAINTNAME;
ALTER TABLE TABLENAME
ADD CONSTRAINT FK_CONSTRAINTNAME
FOREIGN KEY (FId)
REFERENCES OTHERTABLE
(Id)
ON DELETE CASCADE ON UPDATE NO ACTION;
As you can see those have to be separated commands, first dropping then adding.
Answer for MYSQL USERS:
ALTER TABLE ChildTableName
DROP FOREIGN KEY `fk_table`;
ALTER TABLE ChildTableName
ADD CONSTRAINT `fk_t1_t2_tt`
FOREIGN KEY (`parentTable`)
REFERENCES parentTable (`columnName`)
ON DELETE CASCADE
ON UPDATE CASCADE;
This PL*SQL will write to DBMS_OUTPUT a script that will drop each constraint that does not have delete cascade and recreate it with delete cascade.
NOTE: running the output of this script is AT YOUR OWN RISK. Best to read over the resulting script and edit it before executing it.
DECLARE
CURSOR consCols (theCons VARCHAR2, theOwner VARCHAR2) IS
select * from user_cons_columns
where constraint_name = theCons and owner = theOwner
order by position;
firstCol BOOLEAN := TRUE;
begin
-- For each constraint
FOR cons IN (select * from user_constraints
where delete_rule = 'NO ACTION'
and constraint_name not like '%MODIFIED_BY_FK' -- these constraints we do not want delete cascade
and constraint_name not like '%CREATED_BY_FK'
order by table_name)
LOOP
-- Drop the constraint
DBMS_OUTPUT.PUT_LINE('ALTER TABLE ' || cons.OWNER || '.' || cons.TABLE_NAME || ' DROP CONSTRAINT ' || cons.CONSTRAINT_NAME || ';');
-- Re-create the constraint
DBMS_OUTPUT.PUT('ALTER TABLE ' || cons.OWNER || '.' || cons.TABLE_NAME || ' ADD CONSTRAINT ' || cons.CONSTRAINT_NAME
|| ' FOREIGN KEY (');
firstCol := TRUE;
-- For each referencing column
FOR consCol IN consCols(cons.CONSTRAINT_NAME, cons.OWNER)
LOOP
IF(firstCol) THEN
firstCol := FALSE;
ELSE
DBMS_OUTPUT.PUT(',');
END IF;
DBMS_OUTPUT.PUT(consCol.COLUMN_NAME);
END LOOP;
DBMS_OUTPUT.PUT(') REFERENCES ');
firstCol := TRUE;
-- For each referenced column
FOR consCol IN consCols(cons.R_CONSTRAINT_NAME, cons.R_OWNER)
LOOP
IF(firstCol) THEN
DBMS_OUTPUT.PUT(consCol.OWNER);
DBMS_OUTPUT.PUT('.');
DBMS_OUTPUT.PUT(consCol.TABLE_NAME); -- This seems a bit of a kluge.
DBMS_OUTPUT.PUT(' (');
firstCol := FALSE;
ELSE
DBMS_OUTPUT.PUT(',');
END IF;
DBMS_OUTPUT.PUT(consCol.COLUMN_NAME);
END LOOP;
DBMS_OUTPUT.PUT_LINE(') ON DELETE CASCADE ENABLE VALIDATE;');
END LOOP;
end;
Here is an handy solution!
I'm using SQL Server 2008 R2.
As you want to modify the FK constraint by adding ON DELETE/UPDATE CASCADE, follow these steps:
NUMBER 1:
Right click on the constraint and click to Modify
NUMBER 2:
Choose your constraint on the left side (if there are more than one). Then on the right side, collapse "INSERT And UPDATE Specification" point and specify the actions on Delete Rule or Update Rule row to suit your need. After that, close the dialog box.
NUMBER 3:
The final step is to save theses modifications (of course!)
PS: It's saved me from a bunch of work as I want to modify a primary key referenced in another table.
For anyone using MySQL:
If you head into your PHPMYADMIN webpage and navigate to the table that has the foreign key you want to update, all you have to do is click the Relational view located in the Structure tab and change the On delete select menu option to Cascade.
Image shown below:
If you want to change a foreign key without dropping it you can do:
ALTER TABLE child_table_name WITH CHECK ADD FOREIGN KEY(child_column_name)
REFERENCES parent_table_name (parent_column_name) ON DELETE CASCADE
for postgresql
BEGIN TRANSACTION ;
ALTER TABLE bank_accounts
DROP CONSTRAINT bank_accounts_company_id_fkey;
ALTER TABLE bank_accounts
ADD CONSTRAINT bank_accounts_company_id_fkey FOREIGN KEY (company_id)
REFERENCES companies (id)
ON DELETE CASCADE;
END;
ALTER TABLE `tbl_celebrity_rows` ADD CONSTRAINT `tbl_celebrity_rows_ibfk_1` FOREIGN KEY (`celebrity_id`)
REFERENCES `tbl_celebrities`(`id`) ON DELETE CASCADE ON UPDATE RESTRICT;
MySQL workbench img
Right click at the table you want to alter and click alter table, then click Foreign Keys. You can see Foreign Keys Options on the right side and just select cascade and click apply!