SQL Server 2008 select constraints order by primary key - sql

I have the following SQL statement to retrieve drop constraint statements.
SELECT DISTINCT 'ALTER TABLE '+TABLE_NAME+' DROP CONSTRAINT '+CONSTRAINT_NAME AS 'DropConstraintStatement'
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE
WHERE TABLE_NAME = 'USER';
The result of this query is:
ALTER TABLE UNITS DROP CONSTRAINT FK_USER_TASK_ID
ALTER TABLE UNITS DROP CONSTRAINT PK_USER
ALTER TABLE UNITS DROP CONSTRAINT UQ_USER_NAME_VERSION
I want to execute these statements within a Java application, hence I need these statements ordered such that the drop primary key constraint is at the last position like:
ALTER TABLE UNITS DROP CONSTRAINT FK_USER_TASK_ID
ALTER TABLE UNITS DROP CONSTRAINT UQ_USER_NAME_VERSION
ALTER TABLE UNITS DROP CONSTRAINT PK_USER
Is there any nice possibility to do this with native SQL?

INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE does not hold the necessary information to distinguish between PK and other constraints. If you are sure your PK names start with PK
you could try adding ORDER BY like this:
ORDER BY CASE WHEN CONSTRAINT_NAME LIKE 'PK%' THEN 1 ELSE 0 END
However, I would suggest switching to SQL Server system views for more precise data. sys.key_constraints holds info about primary keys and unique constraints, and sys.foreign_keys about foreign keys.
WITH CTE AS
(
SELECT OBJECT_NAME(parent_object_id) AS TABLE_NAME
, name AS CONSTRAINT_NAME, Type
FROM sys.key_constraints
WHERE parent_object_id = object_id('YourTable')
UNION
SELECT OBJECT_NAME(parent_object_id) AS TABLE_NAME
, name AS CONSTRAINT_NAME, Type
FROM sys.foreign_keys
WHERE parent_object_id = object_id('YourTable')
)
SELECT 'ALTER TABLE '+TABLE_NAME+' DROP CONSTRAINT '+CONSTRAINT_NAME AS 'DropConstraintStatement'
FROM CTE
ORDER BY CASE WHEN Type = 'PK' THEN 1 ELSE 0 END

Related

How to name the constraint when add NOT NULL on ALTER TABLE

ALTER TABLE ACTOR MODIFY FIRST_NAME VARCHAR2(45) NOT NULL;
I know have to set FIST_NAME to NOT NULL, but I don not know how to name this constraint.
The name of this constraint should be "CK_Fanme"
You can use
ALTER TABLE actor MODIFY ( first_name CONSTRAINT not_null_first_name NOT NULL );
and query to see the result through use of user_constraints data dictionary view such as
SELECT constraint_name
FROM user_constraints
WHERE table_name = 'ACTOR'
Demo

How to set a primary key?

SELECT TOP 1000 [LicensePlate]
,[Manufacturer]
,[Model]
,[Colour]
,[Year]
,[EngineSize]
,[Value]
FROM [Cars2].[dbo].[Cartable1]
Above is my layout for a cars table. I am completely new to SQL and was wondering how I would set 'Licence Plate' as the primary key?
First find any duplicates by that column.
SELECT
C.LicensePlate,
AmountDuplicates = COUNT(*)
FROM
Cars2.dbo.Cartable1 AS C
GROUP BY
C.LicensePlate
HAVING
COUNT(*) > 1
If any record shows up, you need to either delete all the duplicates or update their license plates so they don't repeat anymore.
You will also need to check for NULL values and update or delete them (primary key can't be null).
SELECT
C.*
FROM
Cars2.dbo.Cartable1 AS C
WHERE
C.LicensePlate IS NULL
Then you can add the PRIMARY KEY constraint with:
ALTER TABLE Cars2.dbo.Cartable1
ADD CONSTRAINT PK_Cartable1 -- Name of the constraint
PRIMARY KEY (LicensePlate)
You might get an error if LicensePlate can hold NULL values. You can change it with an ALTER TABLE:
ALTER TABLE Cars2.dbo.Cartable1 ALTER COLUMN LicensePlate VARCHAR(20) NOT NULL -- The proper data type
If you already have a primary key defined on that table you will have to drop it and then create your new one (one table can only have 1 primary key constraint at a time). You can check which one is it with the following query:
USE Cars2; -- The database name here
DECLARE #TableName VARCHAR(100) = 'Cartable1'
DECLARE #SchemaName VARCHAR(100) = 'dbo'
SELECT
ColumnName = Col.Column_Name,
ConstraintName = tab.CONSTRAINT_NAME
FROM
INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS Tab
INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE AS Col ON
Col.Constraint_Name = Tab.Constraint_Name AND
Col.Table_Name = Tab.Table_Name
WHERE
Constraint_Type = 'PRIMARY KEY' AND
Col.Table_Name = #TableName AND
Col.TABLE_SCHEMA = #SchemaName
Once you see the result, you can drop the current primary key with another ALTER TABLE:
ALTER TABLE Cars2.dbo.Cartable1 DROP CONSTRAINT ConstraintNameFromThePreviousQuery
CREATE TABLE Cartable1(
LicensePlate int NOT NULL PRIMARY KEY,
Manufacturer varchar(255) NOT NULL,
Model varchar(255),
Colour varchar(255),
Model varchar(255),
Year int,
EngineSize int,
Value float
);
You do this when you create a table or through an alter table statement:
create table [Cars2].[dbo].[Cartable1] (
LicensePlace varchar(?) primary key,
. . .
);
I recommend adding the primary key when you create the table and before you add any data into it.
If You already have table with data try this ,
ALTER TABLE [Cars2].[dbo].[Cartable1]
ADD CONSTRAINT PRIMARY_KEY_LicensePlate PRIMARY KEY(LicensePlate)

If Foreign Key Not Exist Then Add Foreign Key Constraint(Or Drop a Foreign Key Constraint If Exist) without using Name?

I am finding difficulties to creating a a query. Let say I have a Products and Brands table. I can add a foreign key using this command,
ALTER TABLE Products
ADD FOREIGN KEY (BrandID)
REFERENCES Brands(ID)
But I need to only run this command if Foreign Key does not exist.
A similar thing I need is that drop a Foreign Key Constraint If Exist without using name.
Try this:
IF NOT EXISTS (SELECT * FROM sys.objects o WHERE o.object_id = object_id(N'[dbo].[FK_Products_Brands]') AND OBJECTPROPERTY(o.object_id, N'IsForeignKey') = 1)
BEGIN
ALTER TABLE [dbo].[Products] WITH CHECK ADD CONSTRAINT [FK_Products_Brands] FOREIGN KEY([BrandID]) REFERENCES [dbo].[Brands] ([Id])
END
First of all, you should always name your FKs and all other constraints in order to save yourself trouble like this.
But, if you don't know the name of FK you can check it using multiple system views:
IF NOT EXISTS
(
SELECT * FROM sys.foreign_key_columns fk
INNER JOIN sys.columns pc ON pc.object_id = fk.parent_object_id AND pc.column_id = fk.parent_column_id
INNER JOIN sys.columns rc ON rc.object_id = fk.referenced_object_id AND rc.column_id = fk.referenced_column_id
WHERE fk.parent_object_id = object_id('Products') AND pc.name = 'BrandID'
AND fk.referenced_object_id = object_id('Brands') AND rc.NAME = 'ID'
)
ALTER TABLE Products
ADD CONSTRAINT Your_New_FK_NAME FOREIGN KEY (BrandID)
REFERENCES Brands(ID)
You can use this as well.
IF(OBJECT_ID('FK_Products_Brands', 'F') IS NULL)
ALTER TABLE [dbo].[Products] WITH CHECK ADD CONSTRAINT [FK_Products_Brands] FOREIGN KEY([BrandID]) REFERENCES [dbo].[Brands] ([Id])
To do this without knowing the constraint's name and without inner joins, you can do:
IF NOT EXISTS(SELECT NULL FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE WHERE [TABLE_NAME] = 'Products' AND [COLUMN_NAME] = 'BrandID')
BEGIN
ALTER TABLE Products
ADD FOREIGN KEY (BrandID)
REFERENCES Brands(ID)
END
If you wanted to, you could get the name of the contraint from this table, then do a drop/add.
This worked smoothly for me in Azure sql server.
IF NOT EXISTS (
SELECT NULL
FROM information_schema.TABLE_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'dbo' AND
CONSTRAINT_NAME = 'FK_company_id' AND
CONSTRAINT_TYPE = 'FOREIGN KEY'
) ALTER TABLE dbo.table_main
ADD CONSTRAINT FK_company_id
FOREIGN KEY (company_id)
REFERENCES dbo.table_company(id);

Drop a column from table problem (SQL Server 2008)

Unable to delete [U_Family] column from table below :
Table CREATE script:
CREATE TABLE [dbo].[Users](
[U_Id] [int] IDENTITY(101,1) NOT NULL,
[U_Name] [nvarchar](50) NULL,
[U_Family] [nvarchar](50) NULL,
CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED
(
[U_Id] ASC
),
CONSTRAINT [IX_UserIdUnique] UNIQUE NONCLUSTERED
(
[U_UserId] ASC
)
) ON [PRIMARY]
GO
CREATE UNIQUE NONCLUSTERED INDEX [IX_Users(UserId)] ON [dbo].[Users]
(
[U_Id] ASC
)
INCLUDE ( [U_Name],
[U_Family]) ) ON [PRIMARY]
GO
error message :
'Users' table
- Unable to modify table. The index 'IX_Users(UserId)' is dependent on
column 'U_Family'. ALTER TABLE DROP
COLUMN U_Family failed because one or
more objects access this column.
I know that the problem is because of this index :
CREATE UNIQUE NONCLUSTERED INDEX [IX_Users(UserId)] ON [dbo].[Users]
(
[U_Id] ASC
)
INCLUDE ( [U_Name],
[U_Family])) ON [PRIMARY]
GO
but I never found a syntax to edit this index and remove [U_Family] from included columns.
I cannot delete this index because it is used by a foreign key constraint that I should not remove it.
any solution ????
thanks in advance.
In SQL Server 2008, you should be able to "re-create" your index and drop the existing one in a single command - try this:
CREATE UNIQUE NONCLUSTERED INDEX [IX_Users(UserId)]
ON [dbo].[Users]([U_Id] ASC)
WITH DROP_EXISTING
The WITH DROP_EXISTING should drop the "old" index with the included columns. Once that command has been run, you should be able to drop your column from the table.
You will have to drop the index IX_Users and create a new one without U_Family.
I used sys.indexes to delete the index and then drop the column:
DECLARE #sql VARCHAR(max)
SELECT #sql = 'DROP INDEX ' + idx.NAME + ' ON tblName'
FROM sys.indexes idx
INNER JOIN sys.tables tbl ON idx.object_id = tbl.object_id
INNER JOIN sys.index_columns idxCol ON idx.index_id = idxCol.index_id
INNER JOIN sys.columns col ON idxCol.column_id = col.column_id
WHERE idx.type <> 0
AND tbl.NAME = 'tblName'
AND col.NAME = 'colName'
EXEC sp_executeSql #sql
GO
ALTER TABLE tblName
DROP COLUMN colName
I found this solution and worked for me:
DECLARE #ConstraintName nvarchar(200)
SELECT #ConstraintName = Name FROM SYS.DEFAULT_CONSTRAINTS WHERE
PARENT_OBJECT_ID = OBJECT_ID('__TableName__') AND PARENT_COLUMN_ID = (SELECT
column_id FROM sys.columns WHERE NAME = N'__ColumnName__' AND object_id =
OBJECT_ID(N'__TableName__'))
IF #ConstraintName IS NOT NULL
EXEC('ALTER TABLE __TableName__ DROP CONSTRAINT ' + #ConstraintName)
IF EXISTS (SELECT * FROM syscolumns WHERE id=object_id('__TableName__') AND
name='__ColumnName__')
EXEC('ALTER TABLE __TableName__ DROP COLUMN __ColumnName__')
Just replace __TableName__ and __ColumnName__.

SQL Server Drop Table

If you drop a table in SQL Server that has Keys, Indexes, Contraints, etc on it will it drop those as well? I was just wondering when I am building my scripts if I need to create drop scripts for all of those as well or if I can simply drop the tables?
Thanks,
S
Yes, although you can't drop a table that is referenced by a foreign key in another table.
Here's a procedure for dropping a table with foreign keys that reference it in SQL Server 2008:
create table TA ( AID int identity(1, 1), OtherId int, Name varchar(512), constraint PK_TA primary key (AID))
create table TB ( BID int identity(1, 1), OtherId int, Name varchar(512), constraint PK_TB primary key (BID))
alter table TA add constraint FK_TA_TB foreign key (OtherId) references TB (BID)
alter table TB add constraint FK_TB_TA foreign key (OtherId) references TA (AID)
drop table ta -- doesn't work
drop table tb -- doesn't work
create procedure my_DropTable #tableName varchar(512) as
begin
if OBJECT_ID(#tableName) is null begin print 'OBJECT DOES NOT EXIST' return end
declare #sql nvarchar(max)
while exists (select * from sys.foreign_keys where referenced_object_id = object_id(#tableName))
begin
select #sql = 'ALTER TABLE ' + OBJECT_NAME(parent_object_id) + ' DROP CONSTRAINT ' + OBJECT_NAME(object_id)
from sys.foreign_keys where referenced_object_id = object_id(#tableName)
exec sp_executesql #sql
end
set #sql = 'DROP TABLE ' + #tableName
exec sp_executesql #sql
end
exec my_DropTable 'TA'
exec my_DropTable 'TB'