Guys my question is I don't know the constraint names that I've added to a table. But I need to remove or disable all those foreign key constraints. But how?
SQL> desc orders;
Name Null? Type
----------------------------------------- -------- ----------------------------
ORDER_ID NOT NULL VARCHAR2(10)
PRODUCT_ID VARCHAR2(10)
DATE_OF_ORDER TIMESTAMP(6)
CUST_ID VARCHAR2(10)
QUANTITY NUMBER(38)
TOTAL_PRICE FLOAT(10)
DELIVERY_STATUS VARCHAR2(10)
The related foreign constraints might be determined by using user_constraints dictionary view, and you can disable the foreign key constraint of this table by the following code block
BEGIN
FOR c IN
(
SELECT *
FROM user_constraints c
WHERE c.constraint_type = 'R'
AND c.table_name = 'ORDERS')
LOOP
EXECUTE IMMEDIATE 'ALTER TABLE '||c.table_name||
' DISABLE CONSTRAINT '||c.constraint_name;
END LOOP;
END;
/
If you're using a tool like sql developer you can just right click the table name in the navigator and select constraint > disable all or drop
I am trying to create a script that will drop and create all the primary keys in my Netezza database. Something similar to this article for SQL Server: https://social.technet.microsoft.com/wiki/contents/articles/2321.script-to-create-or-drop-all-primary-keys.aspx
What's the best way to go about that? I found another solution that uses cross apply, but like cursor, that's not supported in Netezza. Thanks!
Here you go:
--DROP CONSTRAINTS
SELECT DISTINCT ' ALTER TABLE '||RTRIM(SCHEMA)||'.'||RELATION|| ' DROP CONSTRAINT '
|| constraintname || ' CASCADE;' from _V_RELATION_KEYDATA
--optional: WHERE DATABASE=<DATABASE>
--OR WHERE SCHEMA='<SCHEMANAME>;
--ADD PK CONSTRAINTS
SELECT DISTINCT ' ALTER TABLE '||RTRIM(SCHEMA)||'.'||RELATION|| ' ADD CONSTRAINT '
|| constraintname || ' PRIMARY KEY('|| trim(trailing ',' from replace(replace
(XMLSerialize(XMLagg(XMLElement('X',attname)))
,'<X>','')
,'</X>',',')) ||' ) INITIALLY IMMEDIATE;'
from _V_RELATION_KEYDATA
GROUP BY SCHEMA,CONSTRAINTNAME, RELATION;
--optional: WHERE DATABASE=<DATABASE>
--OR WHERE SCHEMA='<SCHEMANAME>;
Make sure to run the --ADD PK Constraints and save the DDL output before dropping the constraints
Does Postgres have any way to say ALTER TABLE foo ADD CONSTRAINT bar ... which will just ignore the command if the constraint already exists, so that it doesn't raise an error?
A possible solution is to simply use DROP IF EXISTS before creating the new constraint.
ALTER TABLE foo DROP CONSTRAINT IF EXISTS bar;
ALTER TABLE foo ADD CONSTRAINT bar ...;
Seems easier than trying to query information_schema or catalogs, but might be slow on huge tables since it always recreates the constraint.
Edit 2015-07-13:
Kev pointed out in his answer that my solution creates a short window when the constraint doesn't exist and is not being enforced. While this is true, you can avoid such a window quite easily by wrapping both statements in a transaction.
This might help, although it may be a bit of a dirty hack:
create or replace function create_constraint_if_not_exists (
t_name text, c_name text, constraint_sql text
)
returns void AS
$$
begin
-- Look for our constraint
if not exists (select constraint_name
from information_schema.constraint_column_usage
where table_name = t_name and constraint_name = c_name) then
execute constraint_sql;
end if;
end;
$$ language 'plpgsql'
Then call with:
SELECT create_constraint_if_not_exists(
'foo',
'bar',
'ALTER TABLE foo ADD CONSTRAINT bar CHECK (foobies < 100);')
Updated:
As per Webmut's answer below suggesting:
ALTER TABLE foo DROP CONSTRAINT IF EXISTS bar;
ALTER TABLE foo ADD CONSTRAINT bar ...;
That's probably fine in your development database, or where you know you can shut out the apps that depend on this database for a maintenance window.
But if this is a lively mission critical 24x7 production environment you don't really want to be dropping constraints willy nilly like this. Even for a few milliseconds there's a short window where you're no longer enforcing your constraint which may allow errant values to slip through. That may have unintended consequences leading to considerable business costs at some point down the road.
You can use an exception handler inside an anonymous DO block to catch the duplicate object error.
DO $$
BEGIN
BEGIN
ALTER TABLE foo ADD CONSTRAINT bar ... ;
EXCEPTION
WHEN duplicate_table THEN -- postgres raises duplicate_table at surprising times. Ex.: for UNIQUE constraints.
WHEN duplicate_object THEN
RAISE NOTICE 'Table constraint foo.bar already exists';
END;
END $$;
http://www.postgresql.org/docs/9.4/static/sql-do.html http://www.postgresql.org/docs/9.4/static/plpgsql-control-structures.html
http://www.postgresql.org/docs/9.4/static/errcodes-appendix.html
you can run query over pg_constraint table to find constraint exists or not.like:
SELECT 1 FROM pg_constraint WHERE conname = 'constraint_name'"
Creating constraints can be an expensive operation on a table containing lots of data so I recommend not dropping constraints only to immediately create them again immediately after - you only want to create that thing once.
I chose to solve this using an anonymous code block, very similar to Mike Stankavich, however unlike Mike (who catches an error) I first check to see if the constraint exists:
DO $$
BEGIN
IF NOT EXISTS ( SELECT constraint_schema
, constraint_name
FROM information_schema.check_constraints
WHERE constraint_schema = 'myschema'
AND constraint_name = 'myconstraintname'
)
THEN
ALTER TABLE myschema.mytable ADD CONSTRAINT myconstraintname CHECK (column <= 100);
END IF;
END$$;
Using information_schema.constraint_column_usage to check for the constraint doesn't work for foreign keys. I use pg_constraint to check for primary keys, foreign keys or unique constraints:
CREATE OR REPLACE FUNCTION add_constraint(t_name text, c_name text, constraint_sql text)
RETURNS void
AS $$
BEGIN
IF NOT EXISTS(
SELECT c.conname
FROM pg_constraint AS c
INNER JOIN pg_class AS t ON c.conrelid = t."oid"
WHERE t.relname = t_name AND c.conname = c_name
) THEN
EXECUTE 'ALTER TABLE ' || t_name || ' ADD CONSTRAINT ' || c_name || ' ' || constraint_sql;
END IF;
END;
$$
LANGUAGE plpgsql;
Examples:
SELECT add_constraint('client_grant_system_scopes', 'client_grant_system_scopes_pk', 'PRIMARY KEY (client_grants_id, tenant, "scope");');
SELECT add_constraint('client_grant_system_scopes', 'client_grant_system_scopes_fk', 'FOREIGN KEY (tenant,"scope") REFERENCES system_scope(tenant,"scope") ON DELETE CASCADE;');
SELECT add_constraint('jwt_assertion_issuers', 'jwt_assertion_issuers_issuer_key', 'UNIQUE (issuer);');
Take advantage of regclass to reduce verbosity, increase performance, and avoid errors related to table naming clashes between schemas:
DO $$ BEGIN
IF NOT EXISTS (SELECT FROM pg_constraint
WHERE conrelid = 'foo'::regclass AND conname = 'bar') THEN
ALTER TABLE foo ADD CONSTRAINT bar...;
END IF;
END $$;
This will also work for tables in other schemas, e.g.:
DO $$ BEGIN
IF NOT EXISTS (SELECT FROM pg_constraint
WHERE conrelid = 's.foo'::regclass AND conname = 'bar') THEN
ALTER TABLE s.foo ADD CONSTRAINT bar...;
END IF;
END $$;
In psql You can use metacommand \gexec for run generated query.
SELECT 'ALTER TABLE xx ADD CONSTRAINT abc' WHERE not EXISTS (SELECT True FROM pg_constraint WHERE conname = 'abc') \gexec
For me those solutions didn't work because the constraint was a primary key.
This one worked for me:
ALTER TABLE <table.name> DROP CONSTRAINT IF EXISTS <constraint.name> CASCADE;
Considering all the above mentioned answers , the below approach help if you just want to check if a constraint exist in the table in which you are trying to insert and raise a notice if there happens to be one
DO
$$ BEGIN
IF NOT EXISTS (select constraint_name
from information_schema.table_constraints
where table_schema='schame_name' and upper(table_name) =
upper('table_name') and upper(constraint_name) = upper('constraint_name'))
THEN
ALTER TABLE TABLE_NAME ADD CONSTRAINT CONTRAINT_NAME..... ;
ELSE raise NOTICE 'Constraint CONTRAINT_NAME already exists in Table TABLE_NAME';
END IF;
END
$$;
Don't know why so many lines of code ?
-- SELECT "Column1", "Column2", "Column3" , count(star) FROM dbo."MyTable" GROUP BY "Column1" , "Column2" , "Column3" HAVING count(*) > 1;
alter table dbo."MyTable" drop constraint if exists "MyConstraint_Name" ;
ALTER TABLE dbo."MyTable" ADD CONSTRAINT "MyConstraint_Name" UNIQUE("Column1", "Column3", "Column2");
In Oracle 10g, how can I drop a unique constraint on a column without knowing the name of the constraint (e.g. a system generated name, which won't necessarily be the same across database instances)? Dropping and recreating the table isn't an option. Is it possible?
You can retrieve the constraint's name with:
SELECT CONSTRAINT_NAME
FROM USER_CONSTRAINTS WHERE TABLE_NAME = 'xxx'
AND CONSTRAINT_TYPE = 'U'
You can for instance create a stored procedure that executes the previous sql, stores its result in a variable and uses this variable in ALTER TABLE DROP CONSTRAINT
EDIT: e.g.:
BEGIN
FOR r IN (
SELECT TABLE_NAME, CONSTRAINT_NAME
FROM USER_CONSTRAINTS WHERE TABLE_NAME = 'xxx'
AND CONSTRAINT_TYPE = 'U') LOOP
EXECUTE IMMEDIATE REPLACE(REPLACE(
'ALTER TABLE #TABLE# DROP CONSTRAINT #CON#'
,'#TABLE#',r.TABLE_NAME)
,'#CON#',r.CONSTRAINT_NAME);
END LOOP;
END;
I need to rename a constraint in an Oracle databse, but I don't know the old name at design-time.
What I would like to do is this:
declare
vOldName string;
begin
select CONSTRAINT_NAME
into vOldName
from user_constraints
where TABLE_NAME='AGREEMENT' and CONSTRAINT_TYPE='R';
alter table Agreement rename constraint vOldName to AGREEMENT_FK1;
end;
but I get the error message "PLS-00103: Encountered the symbol "ALTER" when expecting one of the following: begin case ".
How do I solve this problem?
Use dynamic PL/SQL:
declare
vOldName user_constraints.constraint_name%TYPE;
begin
select CONSTRAINT_NAME
into vOldName
from user_constraints
where TABLE_NAME='AGREEMENT' and CONSTRAINT_TYPE='R';
execute immediate 'alter table Agreement rename constraint '
|| vOldName || ' to AGREEMENT_FK1';
end;