SQL Server unique constraint (but only sometimes) - sql-server

Imagine I have a table with 3 columns:
ID (unique ID)
Description (varchar 2000)
IsDeleted (boolean)
I want to add a unique constraint so that all descriptions are unique. BUT only for active records i.e. IsDelete = false. If a user flags a record as deleted, they can re-add a record with the same description as a deleted record, but not the same as a active record.
So, I only want the constraint to effect record where IsDeleted = false.
Tim

In SQL 2008 you can do this using unique index with a filter:
CREATE UNIQUE NONCLUSTERED INDEX ix_table_UNC ON table(Description) WHERE IsDeleted = 0
Pre-SQL 2008, you'd need to create the unique index on a view of the table selecting only the non-deleted records:
CREATE VIEW dbo.vw_ActiveDescriptions WITH SCHEMABINDING
AS
SELECT Id, Description
FROM Table
WHERE IsDeleted= 0
GO
CREATE UNIQUE CLUSTERED INDEX ix_vw_ActiveDescriptions_UC ON dbo.vw_ActiveDescriptions(Description);

Create a new table for the deleted rows. Then enforce uniqueness with a UNIQUE constraint. You would have to make Description smaller because the maximum key size in SQL Server is 900 bytes.

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.

Sql condition with two foriegn key columns

I'm new to sql and
have a table dbo.Student
**column** **datatype**
Student Id Primary Key int not null
ClassId Foriegn Key int not null
BaseId Foriegn Key int not null
ClassId can have multiple base Id but not duplicates
I'm looking to write a condition If any ClassId have duplicate rows with same BaseId's
Example for good data
a b c
1 2 1
2 2 2
Example for bad data
a b c
1 2 1
2 2 1
Thanks
You can use below query to check if you have any duplicate rows in the table
select ClassId,baseid, COUNT(*) NumberOfDuplicate
from student
group by ClassId,baseid
having count(*) >1
There are "unique" constraints in SQL server. You can add one to that column and it will prevent the entry of a row in which that column value is not unique. Unique constraints are allowed on columns that are not keys.
This SO answer has both the gui solution and script solution:
stackoverflow.com/questions/5181877/
Gist of linked answer:
ALTER TABLE TableName ADD CONSTRAINT ConstraintName UNIQUE(ColumnName1, ColumnName2)
This will put a unique constraint on the combination of Column1 and Column2.
In SSMS object Explorer if you expand the table and look under "Keys" to see your constraint.
GUI steps:
Open SQL Server Management Studio.
Expand the Tables folder of the database where you want to create the
constraint.
Right-click the table where you want to add the constraint and click Design.
In the Table Designer menu, click Indexes/Keys.
In the Indexes/Keys dialog box, click Add.
Choose Unique Key in the Type drop-down list.

How to add another primary key in SQL Server

I have a SQL Server table that has primary keys
CompanyID
ClientID
ReportName
I need to add a column that is an additional key and an incremented ID.
alter table Exports
add id int identity(1,1)
How do I write the statement to make this a key as well?
You can have only 1 primary key or identity column in each table in SQL Server.
If you want to have one more column as primary key, then you may use the combination of the columns as the primary key.
Or you can set the constraints UNIQUE and NOT NULL to the columns so that they will act same as a primary key (but these columns can't be referred as foreign keys)
In case of auto incremental columns (identity), you can only have 1 identity column per table. It can also be set as a primary key. Otherwise, if you need multiple columns as auto-increment, then probably you can use a calculated column, a trigger or a sequence object from which you may fetch the values for each record

Indexing ID after we created a new table with primary key ID

Since the table will have primary key id, Microsoft SQL Server will automatically make it as the clustered index upon creation.
Does it mean that it's already optimized right from the start whenever we do queries like Select * from tableX where id = 1 ?

How to create primary key by using two columns in SQL Server

I need to create table with two columns. These columns have to be created with primary key. For example Column 1 name ID and column 2 name Name. ID is auto incremented. When data is inserted into the table, all names has to be different. How can I do that? Please help me.
To create the primary key:
ALTER TABLE dbo.YourTableNameHere
ADD CONSTRAINT PK_YourTable
PRIMARY KEY(ID, Name)
and to make sure the Name is unique:
ALTER TABLE dbo.YourTableNameHere
ADD CONSTRAINT UNIQUE_Name UNIQUE(Name)

Resources