SQL Server Drop Table - sql

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'

Related

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)

Creating a single table for two different entities

What is an appropriate way to structure the database table for the following scenario?
I'm trying to model an incident report, part of it will be recording whether (as part of the incident) an employee or customer had to receive medical attention. The same details are to be recorded for both. In the paper version of the form and in the interface, it is shown as a single table. The table headings would be:
Person (either employee or customer)
Injured
First aid administered
Hospitalised
Details
We already have separate employee and customer tables which old their personal details. The new table would include the ID, details on whether the person was injured, received first aid, hospitalised and any other additional details.
So I've been pondering on a few possibilities of how this could be structured:
Two separate tables for employee and customer incidents. The two tables will hold mostly the same fields with the exception of the foreign keys for EmployeeID or CustomerID.
A single table that includes all the incident related fields and additional fields for EmployeeID and CustomerID where these are nullable foreign keys to the primary keys of the Employee and Customer table respectively. A constraint to ensure that EmployeeID XOR CustomerID is not null.
Create 3 new tables: one to just hold the incidents, one to link customer ID with an incident and another to link employee ID with an incident - is this too normalised? (assuming I will never have more than customers or employees to record incident details for)
A single table that includes all the incident related fields with a single field to store either the employee ID or customer ID and a type field to specify whether it's employee or customer.
I'm leaning towards option 1, it seems to be the cleanest and should different fields need to be recorded for customers and employees, it's easy to update a single table without affecting the other. I've discounted option 4, I think this is bad design since I'm not able to add a FK constraint to the ID column.
Are there any reasons why I shouldn't go for option 1 or are there better alternatives I should also consider?
I would create "link" tables. And not repeat the DDL for the Incident.
then you have the ability to create a view which would bring together customers and employees with the incident data.
I agree with the previous answer to separate the incident details.
-- START TSQL
SET NOCOUNT ON
IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'vwIncidents' and TABLE_TYPE = N'VIEW' )
BEGIN
DROP VIEW [dbo].[vwIncidents]
END
GO
IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'CustomerToIncidentLink' and TABLE_TYPE = N'BASE TABLE' )
BEGIN
DROP TABLE [dbo].[CustomerToIncidentLink]
END
GO
IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'EmployeeToIncidentLink' and TABLE_TYPE = N'BASE TABLE' )
BEGIN
DROP TABLE [dbo].[EmployeeToIncidentLink]
END
GO
IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'Incident' and TABLE_TYPE = N'BASE TABLE' )
BEGIN
DROP TABLE [dbo].[Incident]
END
GO
IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'Employee' and TABLE_TYPE = N'BASE TABLE' )
BEGIN
DROP TABLE [dbo].[Employee]
END
IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'Customer' and TABLE_TYPE = N'BASE TABLE' )
BEGIN DROP TABLE [dbo].[Customer]
END
CREATE TABLE [dbo].[Employee] (
[EmployeeUUID] [uniqueidentifier] NOT NULL,
[TheVersionProperty] [timestamp] NOT NULL,
[SSN] [nvarchar](11) NOT NULL,
[LastName] [varchar](64) NOT NULL,
[FirstName] [varchar](64) NOT NULL,
[CreateDate] [datetime] NOT NULL,
[HireDate] [datetime] NOT NULL
)
GO
ALTER TABLE dbo.Employee ADD CONSTRAINT PK_Employee PRIMARY KEY NONCLUSTERED (EmployeeUUID)
GO
ALTER TABLE [dbo].[Employee] ADD CONSTRAINT CK_SSN_Unique UNIQUE (SSN)
GO
CREATE TABLE [dbo].[Customer] (
[CustomerUUID] [uniqueidentifier] NOT NULL,
[TheVersionProperty] [timestamp] NOT NULL,
[CustomerNumber] [nvarchar](11) NOT NULL,
[LastName] [varchar](64) NOT NULL,
[FirstName] [varchar](64) NOT NULL,
[CreateDate] [datetime] NOT NULL
)
GO
ALTER TABLE dbo.Customer ADD CONSTRAINT PK_Customer PRIMARY KEY NONCLUSTERED (CustomerUUID)
GO
ALTER TABLE [dbo].[Customer] ADD CONSTRAINT CK_CustomerNumber_Unique UNIQUE (CustomerNumber)
GO
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id(N'[dbo].[Incident]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
BEGIN DROP TABLE [dbo].[Incident]
END
GO
CREATE TABLE [dbo].[Incident]
(
IncidentUUID [UNIQUEIDENTIFIER] NOT NULL DEFAULT NEWSEQUENTIALID()
, IncidentName varchar(24) not null
, CreateDate smalldatetime not null
)
GO
ALTER TABLE dbo.Incident ADD CONSTRAINT PK_Incident PRIMARY KEY NONCLUSTERED (IncidentUUID)
GO
ALTER TABLE [dbo].[Incident] ADD CONSTRAINT CK_IncidentName_Unique UNIQUE (IncidentName)
GO
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id(N'[dbo].[EmployeeToIncidentLink]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
BEGIN DROP TABLE [dbo].[EmployeeToIncidentLink]
END
GO
CREATE TABLE [dbo].[EmployeeToIncidentLink] (
[LinkSurrogateUUID] [uniqueidentifier] NOT NULL,
[TheEmployeeUUID] [uniqueidentifier] NOT NULL,
[TheIncidentUUID] [uniqueidentifier] NOT NULL
)
GO
ALTER TABLE dbo.EmployeeToIncidentLink ADD CONSTRAINT PK_EmployeeToIncidentLink PRIMARY KEY NONCLUSTERED (LinkSurrogateUUID)
GO
ALTER TABLE [dbo].[EmployeeToIncidentLink] ADD CONSTRAINT FK_EmployeeToIncidentLinkToEmployee FOREIGN KEY (TheEmployeeUUID) REFERENCES dbo.Employee (EmployeeUUID)
GO
ALTER TABLE [dbo].[EmployeeToIncidentLink] ADD CONSTRAINT FK_EmployeeToIncidentLinkToIncident FOREIGN KEY (TheIncidentUUID) REFERENCES dbo.Incident (IncidentUUID)
GO
ALTER TABLE [dbo].[EmployeeToIncidentLink] ADD CONSTRAINT CONST_UNIQUE_EmpUUID_InciUUID UNIQUE (TheEmployeeUUID , TheIncidentUUID)
GO
IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = object_id(N'[dbo].[CustomerToIncidentLink]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
BEGIN DROP TABLE [dbo].[CustomerToIncidentLink]
END
GO
CREATE TABLE [dbo].[CustomerToIncidentLink] (
[LinkSurrogateUUID] [uniqueidentifier] NOT NULL,
[TheCustomerUUID] [uniqueidentifier] NOT NULL,
[TheIncidentUUID] [uniqueidentifier] NOT NULL
)
GO
ALTER TABLE dbo.CustomerToIncidentLink ADD CONSTRAINT PK_CustomerToIncidentLink PRIMARY KEY NONCLUSTERED (LinkSurrogateUUID)
GO
ALTER TABLE [dbo].[CustomerToIncidentLink] ADD CONSTRAINT FK_CustomerToIncidentLinkToCustomer FOREIGN KEY (TheCustomerUUID) REFERENCES dbo.Customer (CustomerUUID)
GO
ALTER TABLE [dbo].[CustomerToIncidentLink] ADD CONSTRAINT FK_CustomerToIncidentLinkToIncident FOREIGN KEY (TheIncidentUUID) REFERENCES dbo.Incident (IncidentUUID)
GO
ALTER TABLE [dbo].[CustomerToIncidentLink] ADD CONSTRAINT CONST_UNIQUE_CustomerUUID_InciUUID UNIQUE (TheCustomerUUID , TheIncidentUUID)
GO
CREATE VIEW dbo.vwIncidents
AS
/* combine what is in common with employees and customers for this view */
select e.LastName, e.FirstName, inc.IncidentName
from dbo.Employee e
join
dbo.EmployeeToIncidentLink link on e.EmployeeUUID = link.TheEmployeeUUID
join
dbo.Incident inc on inc.IncidentUUID = link.TheIncidentUUID
UNION ALL
select c.LastName, c.FirstName, inc.IncidentName
from dbo.Customer c
join
dbo.CustomerToIncidentLink link on c.CustomerUUID = link.TheCustomerUUID
join
dbo.Incident inc on inc.IncidentUUID = link.TheIncidentUUID
GO
There is another option (I think?)
Create a Person table, (this has info in common with customers and employees) and then create "sub class" tables for customer and employee that has unique to that entity data.
That's a topic unto itself.
See
How do we implement an IS-A Relationship?
"IS A"
or "how to subclass in a database" would be search tips.
I have this example that is close to yours, that does a "subclassing"
-- START TSQL
SET NOCOUNT ON
IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'vwPersonEmail' and TABLE_TYPE = N'VIEW' )
BEGIN
DROP VIEW [dbo].[vwPersonEmail]
END
GO
IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'PersonEmail' and TABLE_TYPE = N'BASE TABLE' )
BEGIN
DROP TABLE [dbo].[PersonEmail]
END
GO
IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'Customer' and TABLE_TYPE = N'BASE TABLE' )
BEGIN
DROP TABLE [dbo].[Customer]
END
GO
IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'Employee' and TABLE_TYPE = N'BASE TABLE' )
BEGIN
DROP TABLE [dbo].[Employee]
END
GO
IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'PersonSuperType' and TABLE_TYPE = N'BASE TABLE' )
BEGIN
DROP TABLE [dbo].[PersonSuperType]
END
GO
IF EXISTS ( SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = N'dbo' and TABLE_NAME = N'Department' and TABLE_TYPE = N'BASE TABLE' )
BEGIN
DROP TABLE [dbo].[Department]
END
GO
CREATE TABLE [dbo].[Department](
[DepartmentUUID] [uniqueidentifier] NOT NULL,
[TheVersionProperty] [timestamp] NOT NULL,
[DepartmentName] [nvarchar](80) NULL,
[CreateDate] [datetime] NOT NULL,
[MyTinyInt] tinyint not null
)
ALTER TABLE dbo.[Department] ADD CONSTRAINT PK_Department PRIMARY KEY NONCLUSTERED ([DepartmentUUID])
GO
ALTER TABLE [dbo].[Department] ADD CONSTRAINT CK_DepartmentName_Unique UNIQUE ([DepartmentName])
GO
CREATE TABLE [dbo].[PersonSuperType] (
[PersonSuperTypeUUID] [uniqueidentifier] not null default NEWSEQUENTIALID(),
[LastName] [varchar](64) NOT NULL,
[FirstName] [varchar](64) NOT NULL
)
GO
ALTER TABLE dbo.PersonSuperType ADD CONSTRAINT PK_PersonSuperTypeUUID PRIMARY KEY CLUSTERED (PersonSuperTypeUUID)
GO
CREATE TABLE [dbo].[Employee] (
[EmployeeUUID] [uniqueidentifier] NOT NULL,
[ParentDepartmentUUID] [uniqueidentifier] NOT NULL,
[TheVersionProperty] [timestamp] NOT NULL,
[SSN] [nvarchar](11) NOT NULL,
[CreateDate] [datetime] NOT NULL,
[HireDate] [datetime] NOT NULL
)
GO
ALTER TABLE dbo.Employee ADD CONSTRAINT PK_Employee PRIMARY KEY NONCLUSTERED (EmployeeUUID)
GO
ALTER TABLE [dbo].[Employee] ADD CONSTRAINT CK_SSN_Unique UNIQUE (SSN)
GO
ALTER TABLE [dbo].[Employee] ADD CONSTRAINT FK_EmployeeToDepartment FOREIGN KEY (ParentDepartmentUUID) REFERENCES dbo.Department (DepartmentUUID)
GO
ALTER TABLE [dbo].[Employee] ADD CONSTRAINT FK_EmployeeToPersonSuperType FOREIGN KEY (EmployeeUUID) REFERENCES dbo.PersonSuperType (PersonSuperTypeUUID)
GO
CREATE TABLE [dbo].[Customer] (
[CustomerUUID] [uniqueidentifier] NOT NULL,
[TheVersionProperty] [timestamp] NOT NULL,
[CustomerNumber] [nvarchar](11) NOT NULL,
[CreateDate] [datetime] NOT NULL,
)
GO
ALTER TABLE [dbo].[Customer] ADD CONSTRAINT PK_Customer PRIMARY KEY NONCLUSTERED (CustomerUUID)
GO
ALTER TABLE [dbo].[Customer] ADD CONSTRAINT CK_Customer_CustomerNumber_Unique UNIQUE (CustomerNumber)
GO
ALTER TABLE [dbo].[Customer] ADD CONSTRAINT FK_CustomerToPersonSuperType FOREIGN KEY (CustomerUUID) REFERENCES dbo.PersonSuperType (PersonSuperTypeUUID)
GO
CREATE TABLE [dbo].[PersonEmail] (
[PersonEmailUUID] [uniqueidentifier] NOT NULL,
[PersonSuperTypeUUID] [uniqueidentifier] NOT NULL,
[EmailAddress] [varchar](256) NOT NULL
)
GO
ALTER TABLE [dbo].[PersonEmail] ADD CONSTRAINT PK_PersonEmail PRIMARY KEY NONCLUSTERED (PersonEmailUUID)
GO
ALTER TABLE [dbo].[PersonEmail] ADD CONSTRAINT CK_PersonEmail_EmailAddress_Unique UNIQUE (EmailAddress)
GO
ALTER TABLE [dbo].[PersonEmail] ADD CONSTRAINT FK_PersonEmailToPersonSuperType FOREIGN KEY (PersonSuperTypeUUID) REFERENCES dbo.PersonSuperType (PersonSuperTypeUUID)
GO
CREATE VIEW dbo.vwPersonEmail
AS
/* combine what is in common with employees and customers for this view */
select per.LastName, per.FirstName, [UniqueIdentifier] = emp.SSN, pemail.EmailAddress
from dbo.PersonSuperType per
join
dbo.Employee emp on per.PersonSuperTypeUUID = emp.EmployeeUUID
join
dbo.PersonEmail pemail on per.PersonSuperTypeUUID = pemail.PersonSuperTypeUUID
UNION ALL
select per.LastName, per.FirstName, [UniqueIdentifier] = cust.CustomerNumber, pemail.EmailAddress
from dbo.PersonSuperType per
join
dbo.Customer cust on per.PersonSuperTypeUUID = cust.CustomerUUID
join
dbo.PersonEmail pemail on per.PersonSuperTypeUUID = pemail.PersonSuperTypeUUID
GO
So now that I think about it, I might lean toward the "subclassing" way..since your two types of people might have alot of common attributes, and a few distinct ones.
If you want only to show information about 2 diferent tables in only one, you could use a View. Here you have an example check it out.
https://www.w3schools.com/sql/sql_view.asp => tutorial
https://www.ibm.com/support/knowledgecenter/en/ssw_i5_54/rzatc/rzatcviewmultsql.htm => example
I'd formalize the distinction between the incident and the details.
INCIDENT_HEADER
Customer ID <nullable, fk into the customer table>
Employee ID <nullable, fk into the employee table, which already exsits>
Summary
Date
Status (?)
INCIDENT_DETAIL
DETAIL_TYPE_ID <fk into a type table, it's up next...>
DESCRIPTION
DETAIL_TYPE
ID
DESCRIPTION
DETAIL_TYPE will end up with things like "Injury", "Hospitalized", and "First Aid". You can add more to that table later without touching the details table.
This design lets you add more kinds of details without altering the header table.

Checking for table columns before adding them in SQL Server

I need to script out a table modification at work. Rather than do a simple "if exists then drop and create", they want it to check for the new columns I'm adding, and only then alter the table with them if they don't exist.
Could someone help me with the script? Assume a simple table that looks like this currently:
CREATE TABLE myTable (
[ID] [int] NOT NULL,
[FirstName] [varchar] (20) NOT NULL,
[LastName] [varchar] (20) NOT NULL
)
.. I'd like to add an Address field, varchar(50) let's say, but only if it doesn't already exist in the schema.
IF NOT EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'myTable' AND COLUMN_NAME = 'Address')
BEGIN
ALTER TABLE [dbo].[myTable] ADD
[Address] varchar(50) NOT NULL
END
Try this
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[myTable ]') AND type in (N'U'))
BEGIN
DROP TABLE [dbo].[myTable ]
END
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE myTable (
[ID] [int] NOT NULL,
[FirstName] [varchar] (20) NOT NULL,
[LastName] [varchar] (20) NOT NULL,
[Address] [varchar] (50) NOT NULL
)
OR
if not exists(select * from sys.columns
where Name = N'Address' and Object_ID = Object_ID(N'myTable'))
begin
alter table myTable
add Address varchar(50) NOT NULL
end
GO
Try this:
Here using it you can make check for multiple columns and get you table altered...
DECLARE #query VARCHAR(MAX)
IF EXISTS(SELECT * FROM sys.columns
WHERE Name = N'Address' AND OBJECT_ID = OBJECT_ID(N'<TableName>'))
BEGIN
SET
#query = 'ALTER TABLE <TableName> ADD Address varchar(50) GO'
END
--You can give multiple If conditions, example:
--IF EXISTS(SELECT * FROM sys.columns
--WHERE Name = N'<SomeOtherColumn>' AND OBJECT_ID = OBJECT_ID(N'<TableName>'))
--BEGIN
--SET
--#query = #query + 'ALTER TABLE <TableName> ADD <SomeOtherColumn> varchar(50) GO'
--END
EXEC sp_Executesql #query
IF 'col_name'
NOT IN
SELECT Name
FROM table_name.columns
ALTER TABLE table_name
ADD 'col_name' VARCHAR(65) NOT NULL
something like this?
EDIT: my friend believes this is much better
IF NOT EXISTS
(SELECT Name
FROM table_name.columns
Where Name='target_column_name')
ALTER TABLE table_name
ADD 'target_column_name' VARCHAR(65) NOTNULL

SQL Server 2008 select constraints order by primary key

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

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__.