Can't delete primary key on table with FULLTEXT index - sql-server

I have a table with a primary key that is an int data type. I want to drop this column (as it is unused, and I fear this column may reach the maximum limit of the int data type, so we may as well drop it.).
First, I could not drop I tried to first drop the constraint with:
ALTER TABLE dbo.MyTable DROP CONSTRAINT PK_MyTableID
I'm getting the error:
Cannot drop index 'PK_MyTableID' because it enforces the full-text key for table or indexed view 'MyTable'.
I don't understand this error, because the primary key is an int, and I don't think this table has a FULLTEXT index, but if it does, I don't need it.
EDIT:
I was able to drop the column after deleting the FULLTEXT index:
DROP FULLTEXT INDEX ON dbo.MyTable

I believe there is a full text index on the table. A full text index requires you to have unique key:
From MSDN: KEY INDEX index_name
Is the name of the unique key index on table_name. The KEY INDEX must be a unique, single-key, non-nullable column. Select the smallest unique key index for the full-text unique key. For the best performance, we recommend an integer data type for the full-text key.
You can check for a tables full text indexes using:
SELECT object_id, property_list_id, stoplist_id FROM sys.fulltext_indexes
where object_id = object_id('myTable');

Related

Unique constraint and index

I have a table in SQL Server containing some user related info where the primary key is id (auto increment by 1) and has a column named userId. Each user can only has one record in the table, so I have added a unique constraint on column userId. As per SQL Server docs, SQL Server will automatically create an index for the unique constraint column.
For the usage on the table, there can be many update and insert operations, as well as select operations, and that's where my questions arise.
I see that the index that got created automatically by SQL Server on the unique constraint column is a non-clustered index, where it is good for update and insert operations, but for select operation, it is not as fast as the clustered index. (ref. differences-between-a-clustered-and-a-non-clustered-index)
For this table, there can be many select by userId operations. From the performance perspective, should a clustered index on userId be created, given that clustered index is the fastest for read operations ?
If yes, but a non-clustered index has already been automatically created on column userId, could a clustered index still be created on the userId column? (I have found some similar question, from the answers, it seem like if doing so, it will first search through the non-clustered index, then it will points to the clustered index and continue that search non-clustered-index-and-clustered-index-on-the-same-column)
Assuming your table was created in the following manner:
CREATE TABLE dbo.users
(
id int identity(1,1),
userId int,
userName varchar(100),
emailAddress varchar(100),
constraint PK_dbo_users primary key (Id)
);
alter table dbo.users
add constraint UNQ_dbo_users_userId UNIQUE(userId);
... then you already have a clustered index on "id" column by default.
A table can only have one clustered index, as Jonathon Willcock mentioned in the comments. So you cannot add another clustered index to userId column.
You also cannot recreate the clustered index to switch it to the userId column, as the constraints must much the existing constraint. Also, assuming there are foreign key references involved from other tables, you would have to drop the foreign keys before you can drop the users table.
Another option is to create a nonclustered covering index with an INCLUDE clause that contains all the columns needed for your query. This will avoid key lookups in the query plan.
For example:
create nonclustered index IX_dbo_users
on dbo.users (userId) include (id, userName, emailAddress);
Whether the PK and/or clustered index should be on userId or Id column depends on your users queries. If more queries, or more important queries, rely on "id" having clustered index, then keep it. Etc.
But if your table does not already have a clustered index, then yes, add it on userId column.

how to define full text searching on table with two keys?

I have a table with 2 columns as primary key like below.
create table table1(key1 int NOT NULL,key2 int NOT NULL,content NVARCHAR(MAX), primary key(key1,key2))
I have created index on table with this query
CREATE unique INDEX index1 ON table1 (key1,key2);
and with this query, I create full-text searching
create fulltext index on table1 (content ) key index index1;
but I get this error because index must be single-column
'index1' is not a valid index to enforce a full-text search key. A full-text search key must be a unique, non-nullable, single-column index which is not offline, is not defined on a non-deterministic or imprecise nonpersisted computed column, does not have a filter, and has maximum size of 900 bytes. Choose another index for the full-text key.
and with single Column indexing, when I insert a new row I get a duplicate error.
what should I do?
I am using SQL Server and EF orm
Update
i solve this problem by creating a computed column that return unique data
ALTER TABLE Table1 ADD indexKey AS cast(key1 as float) + cast((cast(key2 as float)/power(10,len(key2))) as float) PERSISTED not null
and i create my index on this column and it work pretty fine.

Is Unique key Clustered or Non-Clustered Index in SQL Server?

I am new to SQL Server and while learning about clustered index, I got confused!
Is unique key clustered or a non-clustered index? Unique key holds only unique values in the column including null, so according to this concept, unique key should be a clustered index, right? But when I went through this article I got confused MSDN
When you create a UNIQUE constraint, a unique nonclustered index is
created to enforce a UNIQUE constraint by default. You can specify a
unique clustered index if a clustered index on the table does not
already exist.
Please help me to understand the concept in a better manner, Thank you.
There are three ways of enforcing uniqueness in SQL Server indexes.
Primary Key constraint
Unique constraint
Unique index (not constraint based)
Whether they are clustered or non clustered is orthogonal to whether or not the indexes are declared as unique using any of these methods.
All three methods can create a clustered or non clustered index.
By default the unique constraint and Unique index will create a non clustered index if you don't specify any different (and the PK will by default be created as CLUSTERED if no conflicting clustered index exists) but you can explicitly specify CLUSTERED/NONCLUSTERED for any of them.
Example syntax is
CREATE TABLE T
(
X INT NOT NULL,
Y INT NOT NULL,
Z INT NOT NULL
);
ALTER TABLE T ADD PRIMARY KEY NONCLUSTERED(X);
--Unique constraint NONCLUSTERED would be the default anyway
ALTER TABLE T ADD UNIQUE NONCLUSTERED(Y);
CREATE UNIQUE CLUSTERED INDEX ix ON T(Z);
DROP TABLE T;
For indexes that are not specified as unique SQL Server will silently make them unique any way. For clustered indexes this is done by appending a uniquefier to duplicate keys. For non clustered indexes the row identifier (logical or physical) is added to the key to guarantee uniqueness.
Unique index can be both clustered or non-clustered.
But if you have nullable column the NULL value should be unique (only 1 row where column is null).
If you want to store more then 1 NULLs you can create the index with filter "where columnName is not null".
well all the answers provided was very helpful, but still i would like to add some detailed answer so that i would be helpful for some others as well
A table can contain only one clustered index and a primary key can
be a clustered / non-clustered index.
Unique Key can be a clustered/non-clustered index as well,
below are some of the examples
Scenario 1 : Primary Key will default to Clustered Index
In this case we will create only Primary Key and when we check the kind of index created on the table we will notice that it has created clustered index automatically over it.
USE TempDB
GO
-- Create table
CREATE TABLE TestTable
(ID INT NOT NULL PRIMARY KEY,
Col1 INT NOT NULL)
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
Scenario 2: Primary Key is defined as a Non-clustered Index
In this case we will explicitly defined Primary Key as a non-clustered index and it will create it as a non-clustered index. It proves that Primary Key can be non-clustered index.
USE TempDB
GO
-- Create table
CREATE TABLE TestTable
(ID INT NOT NULL PRIMARY KEY NONCLUSTERED,
Col1 INT NOT NULL)
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
Scenario 3: Primary Key defaults to Non-Clustered Index with another column defined as a Clustered Index
In this case we will create clustered index on another column, SQL Server will automatically create a Primary Key as a non-clustered index as clustered index is specified on another column.
-- Case 3 Primary Key Defaults to Non-clustered Index
USE TempDB
GO
-- Create table
CREATE TABLE TestTable
(ID INT NOT NULL PRIMARY KEY,
Col1 INT NOT NULL UNIQUE CLUSTERED)
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
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
reference:the above details is been refrenced from this article

SQL Server: Alter a clustered primary index to an non-clustered

How do I alter a primary clustered index to become a non-clustured index. (Being a "secondary" table I want to use the clustured index for the foreign key column of the "header" table.)
This doen't work for me (error seems reasonable :)
DROP INDEX ClientUsers.PK_ClientUsers
CREATE UNIQUE CLUSTERED INDEX IDX_ClientUsers_Id ON ClientUsers(Id)
Msg 3723, Level 16, State 4, Line 7
An explicit DROP INDEX is not allowed on index 'ClientUsers.PK_ClientUsers'.
It is being used for PRIMARY KEY constraint enforcement.
I think you will have to:
Drop the FK
Drop the PK
Drop the clustered index
Recreate the PK
Recreate the FK
Recreate the clustered index on the FK column
and then optionally create a secondry index on the PK column
Have you tried dropping the PRIMARY KEY constraint on the table as well - then dropping the index - then re-adding both?
ALTER TABLE table_name DROP primary key

Alter a column length

I need to alter the length of a column column_length in say more than 500 tables and the tables might have no of records ranging from 10 records to 3 or 4 million records.
The column may just be a normal column
CREATE TABLE test(column_length varchar(10))
The column might contain non-clustered index on it.
CREATE TABLE test(column_length varchar(10))
CREATE UNIQUE NONCLUSTERED INDEX column_length_ind ON test (column_length)
The column might contain PRIMARY KEY clustered index on it
CREATE TABLE test(column_length varchar(10))
ALTER TABLE test ADD PRIMARY KEY CLUSTERED INDEX ON column_length
The column might be a composite primary key
The column might have a foreign key reference
In short the column column_length might be anything.
All I need is to create scripts to alter the length of the column_length from varchar(10) to varchar(50). Should I drop the indexes before altering and then recreate them? What about the primary key and foreign key?
Through my research and testing I figured out that I can just alter the column's length without dropping the primary key or any indexes but have to drop and recreate the foreign key alone.
Is this assumption right?
Yes you should be able to just modify the columns. From my experience it is faster to leave the index and primary key in place.
Likely you will need to do alter column on the foreign key tables as well to increase the size. SO first you drop the fk constraint, then fix the forign kkey fields, then fix the primary key field then put the constraints back on.

Resources