I want to drop a foreign key from a table but I do not know its identifier.
I get the identifier from the SYSCAT.KEYCOLUSE table.
After that I try to use that identifier to drop the FK.
Getting identifier
SELECT keycoluse.CONSTNAME FROM SYSCAT.KEYCOLUSE keycoluse WHERE TABSCHEMA = 'USER1' AND TABNAME = 'TABLE1' AND COLNAME = 'ID_TABLE'
result = ID000000001
Dropping FK
ALTER TABLE TABLE1
DROP FOREIGN KEY (SELECT keycoluse.CONSTNAME FROM SYSCAT.KEYCOLUSE keycoluse WHERE TABSCHEMA = 'USER1' AND TABNAME = 'TABLE1' AND COLNAME = 'ID_TABLE');
this throw error: [Error Code: -104, SQL State: 42601]
But if I use the identifier I got before in this way, it works:
ALTER TABLE TABLE1
DROP FOREIGN KEY ID000000001;
In this way, it does not work:
ALTER TABLE TABLE1
DROP FOREIGN KEY 'ID000000001';
When I execute the SELECT to get the id, it gets a varchar 'ID000000001' and that gives the error.
¿Is there a way to cast the result of the SELECT into the same type that we have in this command?
ALTER TABLE TABLE1
DROP FOREIGN KEY ID000000001;
You cannot use a variable (returned by a subselect) or a literal where an identifier is required.
What you can do is generate a script from the query you have, although I cannot imagine why you would want to use such a complex approach to drop a single constraint:
SELECT
'ALTER TABLE', 'TABLE1',
'DROP FOREIGN KEY', keycoluse.CONSTNAME
FROM
SYSCAT.KEYCOLUSE keycoluse
WHERE
TABSCHEMA = 'USER1' AND TABNAME = 'TABLE1' AND COLNAME = 'ID_TABLE'
The query will return a correct ALTER statement. You can copy/paste it into your favourite client software or write results to a text file and execute it, for example, with
db2 -f mydropscript.sql
Related
So I have a query that should add Primary Key to the Id field:
IF NOT EXISTS(SELECT *
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'PRIMARY KEY' AND TABLE_NAME = 'CAL')
BEGIN
DROP INDEX IF EXISTS CAL$01 ON dbo.CAL;
ALTER TABLE BTS.dbo.CAL
ALTER COLUMN Intern INT NOT NULL;
ALTER TABLE BTS.dbo.CAL
ADD CONSTRAINT PK_CAL_Intern PRIMARY KEY (Intern);
CREATE INDEX CAL$01
ON CAL (Intern);
END
The problem is that when I chose all this code and execute (F5), I get this error:
Whereas when I'm choosing every statement one by one it works as expected:
I am sure that the IF works as expected
I tried to use GO between statements, it's not allowed.
I should execute this code on a large number of tables
Maybe I don't know something about how SQL Server Management Studio executes statements
Before a query is run it is parsed. This is why what you're doing is failing. SQL server is checking the details of the Intern before the script is run. At the point you start to try to run the script, Intern in the table BTS.dbo.CAL is NULLable, and so the script fails.
You can get around this by running the statement to create the primary key cosntraint in a separate scope:
IF NOT EXISTS(
SELECT *
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'PRIMARY KEY' AND TABLE_NAME = 'CAL'
)
BEGIN
DROP INDEX IF EXISTS CAL$01 ON dbo.CAL;
ALTER TABLE
BTS.dbo.CAL
ALTER COLUMN
Intern
INT NOT NULL;
EXEC sys.sp_executesql N'ALTER TABLE BTS.dbo.CAL ADD CONSTRAINT PK_CAL_Intern PRIMARY KEY (Intern);';
CREATE INDEX [CAL$01]
ON CAL (Intern);
END'
Even though question is answer, I just wanted to add one more option.
You can separate statments into two separate batches, so that your change is available to the subsequent batch
CREATE TABLE #test(a int null);
-- DDL Changes
if exists(SELECT 1)
BEGIN
ALTER TABLE #test ALTER COLUMN a int not null;
END
GO
-- Index changes
if exists(SELECT 1)
BEGIN
ALTER TABLE #test ADD CONSTRAINT PK_test PRIMARY KEY(a)
END
GO
I am trying to do this:
ALTER TABLE CompanyTransactions DROP COLUMN Created
But I get this:
Msg 5074, Level 16, State 1, Line 2
The object 'DF__CompanyTr__Creat__0CDAE408' is dependent on column 'Created'.
Msg 4922, Level 16, State 9, Line 2
ALTER TABLE DROP COLUMN Created failed because one or more objects access this column.
This is a code first table. Somehow the migrations have become all messed up and I am trying to manually roll back some changed.
I have no idea what this is:
DF__CompanyTr__Creat__0CDAE408
You must remove the constraints from the column before removing the column. The name you are referencing is a default constraint.
e.g.
alter table CompanyTransactions drop constraint [df__CompanyTr__Creat__0cdae408];
alter table CompanyTransactions drop column [Created];
The #SqlZim's answer is correct but just to explain why this possibly have happened. I've had similar issue and this was caused by very innocent thing: adding default value to a column
ALTER TABLE MySchema.MyTable ADD
MyColumn int DEFAULT NULL;
But in the realm of MS SQL Server a default value on a colum is a CONSTRAINT. And like every constraint it has an identifier. And you cannot drop a column if it is used in a CONSTRAINT.
So what you can actually do avoid this kind of problems is always give your default constraints a explicit name, for example:
ALTER TABLE MySchema.MyTable ADD
MyColumn int NULL,
CONSTRAINT DF_MyTable_MyColumn DEFAULT NULL FOR MyColumn;
You'll still have to drop the constraint before dropping the column, but you will at least know its name up front.
As already written in answers you need to drop constraints (created automatically by sql) related to all columns that you are trying to delete.
Perform followings steps to do the needful.
Get Name of all Constraints using sp_helpconstraint which is a system stored procedure utility - execute following exec sp_helpconstraint '<your table name>'
Once you get the name of the constraint then copy that constraint name and execute next statement i.e alter table <your_table_name>
drop constraint <constraint_name_that_you_copied_in_1> (It'll be something like this only or similar format)
Once you delete the constraint then you can delete 1 or more columns by using conventional method i.e Alter table <YourTableName> Drop column column1, column2 etc
When you alter column datatype you need to change constraint key for every database
alter table CompanyTransactions drop constraint [df__CompanyTr__Creat__0cdae408];
You need to do a few things:
You first need to check if the constrain exits in the information schema
then you need to query by joining the sys.default_constraints and sys.columns
if the columns and default_constraints have the same object ids
When you join in step 2, you would get the constraint name from default_constraints. You drop that constraint. Here is an example of one such drops I did.
-- 1. Remove constraint and drop column
IF EXISTS(SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = N'TABLE_NAME'
AND COLUMN_NAME = N'LOWER_LIMIT')
BEGIN
DECLARE #sql NVARCHAR(MAX)
WHILE 1=1
BEGIN
SELECT TOP 1 #sql = N'alter table [TABLE_NAME] drop constraint ['+dc.name+N']'
FROM sys.default_constraints dc
JOIN sys.columns c
ON c.default_object_id = dc.object_id
WHERE dc.parent_object_id = OBJECT_ID('[TABLE_NAME]') AND c.name = N'LOWER_LIMIT'
IF ##ROWCOUNT = 0
BEGIN
PRINT 'DELETED Constraint on column LOWER_LIMIT'
BREAK
END
EXEC (#sql)
END;
ALTER TABLE TABLE_NAME DROP COLUMN LOWER_LIMIT;
PRINT 'DELETED column LOWER_LIMIT'
END
ELSE
PRINT 'Column LOWER_LIMIT does not exist'
GO
In addition to accepted answer, if you're using Entity Migrations for updating database, you should add this line at the beggining of the Up() function in your migration file:
Sql("alter table dbo.CompanyTransactions drop constraint [df__CompanyTr__Creat__0cdae408];");
You can find the constraint name in the error at nuget packet manager console which starts with FK_dbo.
I had the same problem and this was the script that worked for me with a table with a two part name separated by a period ".".
USE [DATABASENAME]
GO
ALTER TABLE [TableNamePart1].[TableNamePart2] DROP CONSTRAINT [DF__ TableNamePart1D__ColumnName__5AEE82B9]
GO
ALTER TABLE [TableNamePart1].[ TableNamePart1] DROP COLUMN [ColumnName]
GO
I needed to replace an INT primary key with a Guid. After a few failed attempts, the EF code below worked for me. If you hyst set the defaultValue... you end up with a single Guid a the key for existing records.
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropUniqueConstraint("PK_Payments", "Payments");
migrationBuilder.DropColumn(
name: "PaymentId",
table: "Payments");
migrationBuilder.AddColumn<Guid>(
name: "PaymentId",
table: "Payments",
type: "uniqueidentifier",
defaultValueSql: "NewId()",
nullable: false);
}
Copy the default constraint name from the error message and type it in the same way as the column you want to delete.
I had the same problem, I could not remove migrations, it would show error that something is already applied, so i changed my DB name in appsettings, removed all migrations, and then added new migration and it worked. Dont understand issue completely, but it worked
I fixed by Adding Dropping constraint inside migration.
migrationBuilder.DropForeignKey(
name: "FK_XX",
table: "TableX").
and below recreates constraint.
migrationBuilder.AddForeignKey(
name: "FK_XX",
table: "TableX",
column: "ColumnX",
onDelete: ReferentialAction.Restrict);
I have a view with a typo:
CREATE OR REPLACE VIEW "USER"."VW_X" AS (
SELECT id,
name,
decode(WRONG_COLUMN, 1, 'T', 0, 'F') AS problem
FROM "USER"."TEST");
For some reason using
CREATE OR REPLACE VIEW "USER"."VW_X" AS (
SELECT id,
name,
decode(RIGHT_COLUMN, 1, 'T', 0, 'F') AS problem
FROM "USER"."TEST");
results in the following message:
Error starting at line : 5 in command -
CREATE OR REPLACE VIEW "USER"."VW_X" AS (
SELECT id,
name,
decode(RIGHT_COLUMN, 1, 'T', 0, 'F') AS problem
FROM "USER"."TEST")
Error report -
SQL Error: ORA-02449: unique/primary keys in table referenced by foreign keys
02449. 00000 - "unique/primary keys in table referenced by foreign keys"
*Cause: An attempt was made to drop a table with unique or
primary keys referenced by foreign keys in another table.
*Action: Before performing the above operations the table, drop the
foreign key constraints in other tables. You can see what
constraints are referencing a table by issuing the following
command:
SELECT * FROM USER_CONSTRAINTS WHERE TABLE_NAME = "tabnam";
I didn't even know that a view was a valid target for a reference. So here's the problem:
SELECT * FROM USER_CONSTRAINTS WHERE TABLE_NAME = "USER"."VW_X";
returns nothing, this:
SELECT a.table_name,
a.column_name,
a.constraint_name,
c.owner,
c.r_owner,
c_pk.table_name r_table_name,
c_pk.constraint_name r_pk,
c.status
FROM all_cons_columns a
JOIN all_constraints c
ON a.owner = c.owner AND a.constraint_name = c.constraint_name
JOIN all_constraints c_pk
ON c.r_owner = c_pk.owner AND c.r_constraint_name = c_pk.constraint_name
WHERE c_pk.table_name = 'VW_X' or c.table_name = 'VW_X';
(a variant on the top answer to this post)
returns four constraints all of which with a status of 'DISABLED'.
I have looked into ALTER VIEW (the name sounded pretty promising), but it does not appear to be what I'm looking for.
Any suggestions?
NOTE: It is possible probable that there are some syntax errors in the provided sample code. These are mockups, in the interest of simplicity and out of professional paranoia, about a dozen irrelevant columns have been removed and names have been altered.
EDIT:
this is Oracle11g
EDIT:
The solution I found was
-- drop view.
DROP VIEW "USER"."VW_X" CASCADE CONSTRAINTS;
commit;
-- create view.
CREATE OR REPLACE VIEW "USER"."VW_X" AS (
SELECT id,
name,
decode(RIGHT_COLUMN, 1, 'T', 0, 'F') AS problem
FROM "USER"."TEST");
commit;
CASCADE CONSTRAINTS appears to be the missing link. I am pretty sure the constraints are lost, but I don't particularly care.
ALTER VIEW
AS
SELECT
[new column name] = wrongcolumn
Here is a solution that would drop the FK, create the view, then recreate the FK
-- create view with unique constraint
create or replace view v_foo
(id unique disable novalidate, val)
as
select id, val from foo;
-- create second view
create or replace view v_bar
(id, val)
as
(select id, val from bar);
-- add FK to second view
alter view v_bar
add constraint v_bar_ref
foreign key (id) references v_foo(id)
disable novalidate;
-- add a column, this fails b/c of FK constraint
create or replace view v_foo
(id unique disable novalidate, val, dummy)
as
select id, val, 1 from foo;
-- remove constraint
alter view v_bar
drop constraint v_bar_ref;
-- make changes to view
create or replace view v_foo
(id unique disable novalidate, val, dummy)
as
select id, val, 1 from foo;
-- recreate FK constraint
alter view v_bar
add constraint v_bar_ref
foreign key (id) references v_foo(id)
disable novalidate;
I am getting following error when deleting a column with constraint in SQL Server 2005.
The object 'DF__PlantRecon__Test' is dependent on column 'Test'.
The column is not part of any key. But it has a default constraint and the constraint has a pre-defined name.
Though I have written code to delete constraint first, it is not working.
Why doesn't it work?
What need to be done to make it working?
Note: I need to check whether the constraint exist first.
REFERENCES
Named CONSTRAINT benefits
How to drop column with constraint?
How to drop SQL default constraint without knowing its name?
CODE
IF OBJECT_ID('DF__PlantRecon__Test', 'C') IS NOT NULL
BEGIN
SELECT 'EXIST'
ALTER TABLE [dbo].[PlantReconciliationOptions] drop constraint DF__PlantRecon__Test
END
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME ='DF__PlantRecon__Test')
BEGIN
SELECT 'EXIST'
--drop constraint
ALTER TABLE [dbo].[PlantReconciliationOptions] drop constraint DF__PlantRecon__Test
END
IF EXISTS ( SELECT * FROM sys.columns WHERE object_id = OBJECT_ID(N'[dbo].[PlantReconciliationOptions]') AND name = 'Test')
BEGIN
--drop column
ALTER TABLE [dbo].[PlantReconciliationOptions] DROP COLUMN Test
END
ALTER TABLE PlantReconciliationOptions
ADD Test INT NOT NULL
CONSTRAINT DF__PlantRecon__Test DEFAULT 30
try
IF OBJECT_ID('DF__PlantRecon__Test') IS NOT NULL
BEGIN
SELECT 'EXIST'
ALTER TABLE [dbo].[PlantReconciliationOptions] drop constraint DF__PlantRecon__Test
END
In your example, you were looking for a 'C' Check Constraint, which the DEFAULT was not. You could have changed the 'C' for a 'D' or omit the parameter all together.
If you are consistent with your naming, as it appears you are, (e.g. DF__xxx) then dropping the second parameter is an acceptable choice to be sure that the hard coded constraint name is dropped.
Here is a list of the OBJECT_ID() Object Types you can pass:
AF = Aggregate function (CLR)
C = CHECK constraint
D = DEFAULT (constraint or stand-alone)
F = FOREIGN KEY constraint
PK = PRIMARY KEY constraint
P = SQL stored procedure
PC = Assembly (CLR) stored procedure
FN = SQL scalar function
FS = Assembly (CLR) scalar function
FT = Assembly (CLR) table-valued function
R = Rule (old-style, stand-alone)
RF = Replication-filter-procedure
S = System base table
SN = Synonym
SQ = Service queue
TA = Assembly (CLR) DML trigger
TR = SQL DML trigger
IF = SQL inline table-valued function
TF = SQL table-valued-function
U = Table (user-defined)
UQ = UNIQUE constraint
V = View
X = Extended stored procedure
IT = Internal table
(This list was found on Beyond Relational: Using TSQL Function: OBJECT_ID())
Steps to solve your problem.
Open SSMS.
Edit the table to remove the default. Do not press save
Script the output to "new window".
Read the script.
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;