Is there a way to enable / disable constraints in db2 v7? - database

I have to copy tables from an Oracle database to a db2 v7 one, and in order to do this (avoiding millions of drops and creates) I'd like to know if db2 has a feature like Oracle to enable / disable constraints temporarily without dropping them.
Thanks in advance,
Mauro.

You can do:
ALTER TABLE <table-name> ALTER FOREIGN KEY <constraint-name> NOT ENFORCED
and then to re-enable:
ALTER TABLE <table-name> ALTER FOREIGN KEY <constraint-name> ENFORCED
http://publib.boulder.ibm.com/infocenter/mptoolic/v1r0/index.jsp?topic=/com.ibm.db2tools.ama.doc.ug/amacric0.htm

I'm not sure if this works in version 7, but you can try the following:
set integrity for table_name off
set integrity for table_name foreign key immediate unchecked
And then you can do your inserts. To re-enable, you can then do the following:
set integrity for table_name immediate checked

Related

SQL Server: Insert into two tables at the same time with FK to each other

I need to do an insert on 2 tables where both have a foreign key to each other (non-nullable)
Unfortunately, using transactions does not work. Any other way to do this?
Unfortunately, using transactions does not work. Any other way to do this?
The only way to do this in SQL Server is to alter the table to NOCHECK one of the constraints while you insert data (or use bulk insert or replication which can both bypass constraint checking). Obviously, this is not something you want to do at runtime.
The typical solution is to allow one of the FKs to be nullable.

Oracle imp tables fail due to restraints

I am using the Oracle imp utility to import data into a set of empty tables in Oracle 10g. When I try to perform the import much of it fails due to referential integrity constraints. E.g. Can't import data into table A because foreign key in table B does not exist yet.
Here is my import command:
imp C_PLUS/<password> rows=y file=db.dmp ignore=y FROMUSER=C_PLUS
TOUSER=C_PLUS tables=...
I could manually go through each table on import and when it fails import the missing table first, but I have over 400 tables that need imported and it would take far too long.
Is there a way around this or does anyone have any ideas?
Thanks
Since you want every table owned by C_PLUS, you can omit the TABLES clause. Just specify the FROMUSER. You can also omit the TOUSER parameter since you're not changing the schema name but that won't affect the behavior of the import. Omitting the TABLES clause should fix the problem with constraints assuming that all the foreign key constraints reference other tables in the same schema and assuming that the data in the export file allows the constraints to be enabled (if the export was done without setting CONSISTENT=Y, there may be orphaned rows in the dump file that will prevent the constraints from being created for example).
For each table you can disable the primary key/foreign key constraints before import. Then enable each primary and foreign key constrains after the import.
Disable contraints
ALTER TABLE table_name DISABLE PRIMARY KEY CASCADE;
Enable constraint
ALTER TABLE table_name ENABLE CONSTRAINT constraint_name;
If the number of table and the number of constraints are too many to do it manually, you can write scripts to generate the ALTER TABLE commands using the data dictionary views.
Disable PK/FK contraints
SELECT 'ALTER TABLE '||table_name||' DISABLE PRIMARY KEY CASCADE' sql_statement
FROM USER_TABLES;
Enable PK constraint
SELECT 'ALTER TABLE '||table_name||' ENABLE CONSTRAINT '||constraint_name sql_statement
FROM USER_CONSTRAINTS
where constraint_type ='P';
Enable FK constraint
SELECT 'ALTER TABLE '||table_name||' ENABLE CONSTRAINT '||constraint_name sql_statement
FROM USER_CONSTRAINTS
where constraint_type ='R';

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

Change primary key value in Oracle

Is there a way to change the value of a primary key which is referenced by another table as foreign key?
An easier alternative is to insert a new row and delete the old one. (Update any referencing rows in other tables before you do the delete)
There isn't an in-built UPDATE CASCADE if that's what you're after. You'd need to do something like disable any FK constraints; run UPDATE statements; re-enable the constraints.
Note that updating Primary Keys is (usually always) a bad idea.
You will need to disable the foreign key constraints before changing the primary key values, and then re-enable them afterwards.
If you actually want to implement "update cascade" functionality instead then see Tom Kyte's Update Cascade package
It is possible even without disabling constraints, in case if you would like only to swap keys (which is also a change's subset, so it might be still answer to your question). I wrote an example here: https://stackoverflow.com/a/26584576/1900739
update MY_TABLE t1
set t1.MY_KEY = (case t1.MY_KEY = 100 then 101 else 100 end)
where t1.MYKEY in (100, 101)
Yes, there is a way to do the cascading update in Oracle, even within a transaction (which does not hold true for the option of enabling/disabling constraints). However, you'll have to implement it yourself. It can be done via before/after-row-update triggers.
It is possible due to the fact that triggers are executed before any constraints are checked. (Well, at least in Oracle 11.2 it was true. Haven't checked against 12.1, but I honestly believe it hasn't changed.)
Anyway, as said before, updating primary keys is usually a bad idea.
The principe is to disable constrainsts, run your udates based on key, and reenable the constrainst. That for here is a script that run the disable script :
(Assuming all the constraints are enable at start)
Generate the script
SELECT 'alter table ' || uc.table_name|| ' disable constraint '|| uc.constraint_name|| ' ;'
FROM user_constraints uc inner join user_cons_columns ucc on uc.constraint_name = ucc.constraint_name where column_name = 'MYCOLUMN_USED_AS_FOREIGN_KEY' and constraint_type='R'
Copy/paste the generated script and run it
alter table MYTABLE1 disable constraint FK_MYTABLE1 ;
alter table MYTABLE2 disable constraint MYTABLE2 ;
alter table MYTABLE3 disable constraint FK3_MYTABLE3 ;
...
Then update your PK values :
update MYTABLE1 set MYFIELD= 'foo' where MYFIELD='bar';
update MYTABLE2 set MYFIELD= 'foo' where MYFIELD='bar';
update MYTABLE3 set MYFIELD= 'foo' where MYFIELD='bar';
commit;
Generate the enable constraints script :
SELECT 'alter table ' || uc.table_name|| ' enable constraint '|| uc.constraint_name|| ' ;'
FROM user_constraints uc inner join user_cons_columns ucc on uc.constraint_name = ucc.constraint_name where column_name = 'MYCOLUMN_USED_AS_FOREIGN_KEY' and constraint_type='R'
Another way you can do this is by changing the foreign key constraints so that the validation of the constraint is deferred until you commit - i.e. instead of Oracle validating the constraints statement-by-statement, it'll do it transaction-by-transaction.
Note you can't do this via the "alter table" statement, but you can drop and re-create the foreign key constraint to be deferrable, i.e:
alter table <table name> drop constraint <FK constraint name>;
alter table <table name> add constraint <FK constraint name> foreign key .... initially deferrable;
Once you've done that, just update the tables in whatever order you like, and commit - at which point, either:
All your FK constraints are satisfied, and everyone's happy; or
You've violated a FK constraint somewhere - you'll get an error and you'll have to fix up the data and commit, or rollback.
Note this feature is quite safe, as Oracle does not allow dirty reads so they'll only see the effects of your updates once you commit. So from the perspective of every other session, referential integrity appears to be preserved.
Also, this is a once-off change, so you don't need to go executing DDL each time you want to go updating the primary keys.

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