how to drop an index key from a table - sql

I'm using sql server 2005/2008 and I have a table that it's PK (rec_index) is also indexed.
CREATE TABLE [dbo].[MyTable]
(
[rec_index] INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
file_desc nvarchar(50),
is_modified bit
)
However unfortunately I already have a table like this in my DB which O created without the index.
How can I ask if the table already is indexed do nothing, else add an index? I can't drop it and than re-create it since i will loose data.
I'm looking for something like "if not exists <index for rec_index> do <create index for rec_index>"

maybe something like:
IF NOT EXISTS ( select *
from sys.objects
where parent_object_id = object_id('MyTable')
and type = 'PK' )
do <create index for rec_index>

There are so many possibilities here, and I'm not sure which situation you're hitting, and what you want to do in each case:
USE [tempdb];
-- table with a clustered PK
CREATE TABLE dbo.TableA(rec_index INT IDENTITY(1,1) PRIMARY KEY CLUSTERED);
-- table with non-clustered PK
CREATE TABLE dbo.TableB(rec_index INT IDENTITY(1,1) PRIMARY KEY NONCLUSTERED);
-- table with no PK, no indexes
CREATE TABLE dbo.TableC(rec_index INT IDENTITY(1,1));
-- table with no PK, non-clustered non-unique index
CREATE TABLE dbo.TableD(rec_index INT IDENTITY(1,1));
CREATE INDEX d ON dbo.TableD(rec_index);
-- table with no PK, clustered non-unique index
CREATE TABLE dbo.TableE(rec_index INT IDENTITY(1,1));
CREATE CLUSTERED INDEX e ON dbo.TableE(rec_index);
-- table with no PK, non-clustered unique index
CREATE TABLE dbo.TableF(rec_index INT IDENTITY(1,1));
CREATE UNIQUE INDEX f ON dbo.TableF(rec_index);
-- table with no PK, clustered unique index
CREATE TABLE dbo.TableG(rec_index INT IDENTITY(1,1));
CREATE UNIQUE CLUSTERED INDEX g ON dbo.TableG(rec_index);
-- table with unique clustered index, but PK on different column
CREATE TABLE dbo.TableH(rec_index INT IDENTITY(1,1),
b INT PRIMARY KEY NONCLUSTERED);
CREATE UNIQUE CLUSTERED INDEX h ON dbo.TableH(rec_index);
GO
DROP TABLE dbo.TableA,dbo.TableB,dbo.TableC,dbo.TableD,
dbo.TableE,dbo.TableF,dbo.TableG,dbo.TableH;
GO
You can certainly perform checks for each of these scenarios from the system metadata, and react accordingly. But you need to help us narrow down what you mean by "without the index."

Related

Specifying existing non clustered unique index when defining a primary key constraint

I have a heap table - no clustered index defined - (call it table A), with a unique non clustered index on a non nullable column (call the column ID and the index IX).
I would like to use index IX when defining the primary key constraint on column ID for table A.
The documentation somewhere says this:
The Database Engine automatically creates a unique index to enforce the uniqueness requirement of the PRIMARY KEY constraint. If a clustered index does
not already exist on the table or a nonclustered index is not explicitly specified, a unique, clustered index is created to enforce the PRIMARY KEY constraint.
I've read through the entire ALTER TABLE documentation but there seems to be no syntax for "nonclustered index is ... explicitly specified, ".
Have tried defining the nonclustered index IX and specifying primary key, and have also tried various combinations of the alter table ... add constraint ... primary key statement to no avail.
It makes sense that my index IX is equivalent to the nonclustered index that SQL Server creates when I simply specify the ID column in the alter table .... add constraint .... primary key (ID) statement, but I would prefer not having this redundant index which SQL Server creates for me, and rather make it use the index IX which also consists of a include list of columns.
If I drop the index that SQL Server creates then the primary key constraint also vanishes.
If it were possible to alter the index that SQL Server creates my problem would be solved, but the alteration I would like to do to it requires a drop and recreate.
There is no way to create a constraint and associate it with an existing index that already guarantees the constraint.
This functionality does exist in other RDBMS. It would be particularly useful for the supertype/subtype pattern as this requires creating unique indexes on both Id and (Id, Type) even though the latter one (required for the FK) is logically ensured by the first.
It is possible to replace the Unique index with a Unique constraint as a metadata only change using ALTER TABLE ... SWITCH but attempting to do the same with a nonclustered PK constraint fails with
ALTER TABLE SWITCH statement failed. There is no identical index in
source table 'A' for the index 'IX' in target table 'B'.
The code that performs this for a unique constraint is
Initial Position
CREATE TABLE dbo.A(ID INT NOT NULL, OtherCols VARCHAR(200));
CREATE UNIQUE NONCLUSTERED INDEX IX ON dbo.A(ID);
INSERT INTO dbo.A VALUES (1,'A'),(2,'B');
Replace unique index with unique constraint
SET XACT_ABORT ON;
BEGIN TRAN;
CREATE TABLE dbo.B
(
ID INT NOT NULL CONSTRAINT IX UNIQUE NONCLUSTERED,
OtherCols VARCHAR(200)
);
ALTER TABLE dbo.A
SWITCH TO dbo.B;
DROP TABLE dbo.A;
EXECUTE sp_rename
N'dbo.B',
N'A',
'OBJECT';
COMMIT;

Does SQL Server creates Non clustered index by default

Ya, it is a duplicate of this. But I just needs a clarification on this article by Pinal Dave, which says the following:
Scenario 4: Primary Key defaults to Clustered Index with other index
defaults to Non-clustered index
In this case we will create two indexes on the both the tables but we
will not specify the type of the index on the columns. When we check
the results we will notice that Primary Key is automatically defaulted
to Clustered Index and another column as a Non-clustered index.
-- Case 4 Primary Key and Defaults
USE TempDB
GO
-- Create table
CREATE TABLE TestTable
(ID INT NOT NULL PRIMARY KEY,
Col1 INT NOT NULL UNIQUE)
GO
-- Check Indexes
SELECT OBJECT_NAME(OBJECT_ID) TableObject,
[name] IndexName,
[Type_Desc]
FROM sys.indexes
WHERE OBJECT_NAME(OBJECT_ID) = 'TestTable'
GO
-- Clean up
DROP TABLE TestTable
GO
The only indexes that get created automatically:
the clustered index on your primary key (unless you specify otherwise - if you define your primary key to be nonclustered, then a nonclustered index will be created)
a unique nonclustered index when you apply a UNIQUE CONSTRAINT to a column (or set of columns)
Just to spell it out - the Result of Pinal Dave's example are indexes similar to the following:
TestTable PK__TestTabl__3214EC2703317E3D CLUSTERED
TestTable UQ__TestTabl__A259EE55060DEAE8 NONCLUSTERED
Which can be explained as follows:
PK Clustered
If a table is created with a primary key, then it is a Clustered Table, and the Clustered Index is defaulted to the Primary Key unless you specify otherwise.
(Tables without a Clustered Index are Heaps)
UQ Nonclustered
SQL does not usually create any non-clustered indexes on a table by default.
However, as Marc has pointed out, because the table has a column with a UNIQUE constraint, (Col1 INT NOT NULL UNIQUE), MS SQL implements the constraint as a unique, non-clustered index on that column.
See also: Is the Sql Server Unique Key also an Index?

Clustered index on temp table

I'm trying to optimize a procedure that has code like the following:
CREATE TABLE #t1 (c1 int, c2 varchar(20), c3(varchar(50)...)
CREATE CLUSTERED INDEX ix_t1 ON #t1(c3) ON [PRIMARY]
I wanted to improve that by moving the CLUSTERED index into the table declaration (more caching friendly), but c3 is not unique so this doesn't work:
CREATE TABLE #t1 (c1 int, c2 varchar(20), c3 varchar(50)..., UNIQUE CLUSTERED (c3))
Is there a way to declare a clustered that is not unique in the temp table declaration?
Yes, it is possible in SQL Server 2014 and above, Create table on MSDN.
From 2014 you can specify the indexes inline with the create table statement.
if object_id('tempdb..#t1') is not null drop table #t1;
CREATE TABLE #t1 (
c1 int,
c2 varchar(20),
c3 varchar(50),
index [CIX_c3] CLUSTERED (c3),
index [IX_c1] nonclustered (c1)
)
insert #t1(c3) values ('a'), ('a'), ('a')
select * from #t1
No there is not...the existence of the ability to define clustered as an option in table creation is to support declaring primary key and unique column constraints, which themselves create indexes. In other words, CLUSTERED in the CREATE TABLE statement is specifying whether or not the index created by the UNIQUE constraint should be clustered or nonclustered, which is important because a table can only have one clustered index.
This can be done by adding an identity column, such as:
CREATE TABLE #t1 (rowID int not null identity(1,1),
c1 int, c2 varchar(20), c3 varchar(50),
UNIQUE CLUSTERED (c3,rowID)
)
Including the rowID in the index will insure that it is unique, even if c3 is not.
You verify the index created with:
EXEC tempdb.dbo.sp_helpindex '#t1'

primary key and index concept

I create a column as primary key , does this create indexes automatically ? or do i need to create indexes explicitly. i was under assumption that primary key also maintains indexes
In SQL Server creating a Primary key will create a Unique Clustered Index on that Column.
or more specifically from here
Note PRIMARY KEY constraints create
clustered indexes automatically if no
clustered index already exists on the
table and a nonclustered index is not
specified when you create the PRIMARY
KEY constraint.
This should clear out some air.
--creating a table without any primary key
CREATE table understanding_indexes
(P_Id int,
LastName varchar(255),
FirstName varchar(255),
Address varchar(255),
City varchar(255)
)
--
--checking for indexes
sp_helpindex understanding_indexes
OUTPUT
The object 'understanding_indexes' does not have any indexes, or you do not have permissions.
--ADDING A NOT NULL CONSTRAINT
ALTER TABLE UNDERSTANDING_INDEXES
ALTER COLUMN P_Id INTEGER
NOT NULL
--ADDING A PRIMARY KEY Constraint, can only be done on column which are not null.
ALTER TABLE UNDERSTANDING_INDEXES
ADD PRIMARY KEY (P_Id)
sp_helpindex understanding_indexes
OUTPUT
PK__understa__A3420A5702084FDA clustered, unique, primary key located on PRIMARY P_Id
Overall, As soon as you add a primary key constraint on a table, it automatically adds clustered indexes on the table.
This illustration is on SQL Server 2008 R2.

how to enforce multiple unique fields in database table

i have a table called Cars and the primary key of the table is 'id'. I also have a field called 'name'. I would like to make sure no one enters the same name twice even though it wont break my db integrity.
what is the best way of doing this?
create unique index cars_unique_name on cars(name)
Just create a UNIQUE index on the name field. In SQL it would be something like this:
CREATE UNIQUE INDEX IX_Cars_name
ON Cars(name);
Another possibility is to create a unique constraint, like this:
ALTER TABLE Cars
ADD CONSTRAINT Uqc_Cars_name
UNIQUE (name)
Both will do essentially the same thing.
you can specify the unique index constraint both in CREATE TABLE command or ALTER TABLE command.
Its like
CREATE TABLE CARS (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) UNIQUE KEY
);
or just create the above table
CREATE TABLE CARS (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100)
);
and later add the unqiue key index using alter table
As mentioned, you will probably want a unique index, but it is also possible to use a unique constraint, with no index which might be desirable in some situations...
CREATE TABLE cars
(
ID INT NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED,
NAME NVARCHAR(100) UNIQUE NOT NULL
)
or
ALTER TABLE cars
ADD CONSTRAINT UniqueConstraintName UNIQUE (name)