how to add this condition in table? - sql-server

i want to create a table which store USERNAME and DOMAIN(both are col. name of same table).
One User can only belong to one domain.
and the The Domain values can be stored in the another table, lets call it "LIST".

Set in your users table domain_id (as relation with domain), then use constraints for two columns (username and domain_id).
MySql example:
ALTER TABLE users ADD UNIQUE unique_index (username, domain_id);
P.S. Look for analog in SQL server. (see example in comments)

I suggest this kind of script to create your tables and put on them determined conditions:
--Create table that will store domains
CREATE TABLE DICT_DOMAINS (
DomainID int IDENTITY(1,1),
DomainName nvarchar(255),
CONSTRAINT [PK_DICT_DOMAINS] PRIMARY KEY CLUSTERED (DomainID ASC)
)
--DomainNames must be unique so we add non clustered index
CREATE UNIQUE NONCLUSTERED INDEX [UX_DICT_DOMAINS_DomainName] ON DICT_DOMAINS (DomainName ASC)
--Create table to store users and there domains
CREATE TABLE USERS_DOMAINS (
DomainID int,
UserName nvarchar(255)
)
--Add foreign key to DICT_DOMAINS table
ALTER TABLE USERS_DOMAINS WITH CHECK ADD CONSTRAINT [FK_USERS_DOMAINS_DICT_DOMAINS] FOREIGN KEY (DomainID)
REFERENCES DICT_DOMAINS (DomainID)
--Usernames must be uniq, no need to add DomainsId to this index
--This is sufficient to provide condition that
--One User can only belong to one domain.
CREATE UNIQUE NONCLUSTERED INDEX [UX_USERS_DOMAINS_UserName] ON USERS_DOMAINS (UserName ASC)

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 Server : optimize constraint for perform a query bases on 2 columns

I am creating a table Brands with the following schema :
UserId
CarId
Brand
The UserId references the id of an user in the user table
The CarId references the id of a car in the car table
The only query that I will use is a search bases on these 2 columns, to get the corresponding brand.
So my question was about the constraint part, as I am a beginner, I would like to know which type of constraint to use (index, primary key, clustered or non clustered, on each field or on the 2 fields together) to have my query the more optimized possible.
This is my script right now :
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[Brands]') AND type in (N'U'))
BEGIN
CREATE TABLE [Brands]
(
UserId BIGINT NOT NULL
CONSTRAINT [FK_Brands_Users]
FOREIGN KEY REFERENCES [Users] (UserId),
CarId BIGINT NOT NULL
CONSTRAINT [FK_Brands_Cars]
FOREIGN KEY REFERENCES [Cars] (CarId),
Brand nvarchar(15),
);
END
GO
ALTER TABLE [Brands]
ADD CONSTRAINT [Unique_UserId_BrandId] UNIQUE(UserId, BrandId);
GO
I would create a primary key including both fields. When you define a primary key it automatically create a clustered index. Also your primary key has a unique constraint build in. Your table is now a heap the way you wrote it here above which is not good. You can additionally create an extra non-clustered index on CarId. Having an additional non-clustered index on UserId is not usefull I think. The column UserId can use the clustered index because it's the first field in the clustered index but I'm not sure about that.

SQL Server: Create Nonclustered Index without giving a name to it

I use SQL Server 2008.
I am trying to create a nonclustered index on my table. I want to check if there exists a way to create this without giving a name to the index.
For e.g.
CREATE TABLE #mytable (Date_ datetime NOT NULL, ID_ varchar(10) NOT NULL, Value_)
When I add a PK to this table, I do not specify the name of that key. For e.g.
ALTER TABLE #mytable ADD PRIMARY KEY CLUSTERED (Date_ ASC, ID_ ASC)
Is it possible to do something similar to create a nonclustered index without specifying a name?
For e.g.
ALTER TABLE #mytable ADD NONCLUSTERED INDEX (Date_, Value_) -- FAILS!!!
The only command I know is
CREATE NONCLUSTERED INDEX *keyname* ON #mytable (Date_, Value_)
After create temp table execute dynamic sequel with guid as index name
DECLARE #NewId VARCHAR(64) = REPLACE(NEWID(),'-','');
EXEC('CREATE INDEX IX_'+#NewId+' ON #Table (ColA,ColB) INCLUDE (ColZ)');
No, it is not possible to create a non-clustered index without a name, the syntax is quite clear:
CREATE [ UNIQUE ] [ CLUSTERED | NONCLUSTERED ] INDEX index_name
index_name
Is the name of the index. Index names must be unique within a table or
view but do not have to be unique within a database. Index names must
follow the rules of identifiers.
CREATE INDEX (Transact-SQL)
The database object name is referred to as its identifier. Everything
in Microsoft SQL Server can have an identifier. Servers, databases,
and database objects, such as tables, views, columns, indexes,
triggers, procedures, constraints, and rules, can have identifiers.
Identifiers are required for most objects, but are optional for some
objects such as constraints.
Database Identifiers

How do I modify this SQL schema to constrain data in tables?

Newbie in need of help.
I'm creating a small database.
I want to constrain data in a couple of tables - Lender and Pingtree. The ProviderType table contains lookup data and contains either 'Lender' or 'Pingtree'. How can I modify this structure so that the Lender table only can contain Lender types and Pingtree, Pingtree types?
Guessing that ProviderTypeID is the column in the Provider table that distinguishes between the two types, then you must add this same column to both the Lender and Pingtree tables, add a suitable key (if it doesn't already exist) in Provider on ID, ProviderTypeId, and then add a composite FOREIGN KEY constraint to the Lender and Pingtree tables that include these columns.
While this may sound like a drag, it is a known pattern called supertyping/subtyping. When the supertype (Provider) can be multiple subtypes, you don't need the TypeId column. But when the subtypes are mutually exclusive, this is what you must do.
It might look something like this:
ALTER TABLE dbo.Lender ADD ProviderTypeId tinyint NOT NULL
CONSTRAINT DF_Lender_ProviderTypeID DEFAULT (1)
CONSTRAINT CK_Lender_ProviderTypeID_Is_Lender CHECK (ProviderTypeID = 1);
ALTER TABLE dbo.Pingtree ADD ProviderTypeId tinyint NOT NULL
CONSTRAINT DF_Pingtree_ProviderTypeID DEFAULT (2)
CONSTRAINT CK_Pingtree_ProviderTypeID_Is_Pingtree CHECK (ProviderTypeID = 2);
-- Any of a PK, UNIQUE constraint, or unique index will do
ALTER TABLE dbo.Provider ADD CONSTRAINT UQ_Provider_ID_ProviderTypeID
UNIQUE (ID, ProviderTypeID);
ALTER TABLE dbo.Lender DROP CONSTRAINT FK_Lender_ProviderId;
ALTER TABLE dbo.Lender ADD CONSTRAINT FK_Lender_ProviderId_ProviderTypeId
FOREIGN KEY (ID, ProviderTypeID) REFERENCES dbo.Provider (ID, ProviderTypeID);
ALTER TABLE dbo.PingTree DROP CONSTRAINT FK_PingTree_ProviderId;
ALTER TABLE dbo.PingTree ADD CONSTRAINT FK_PingTree_ProviderId_ProviderTypeId
FOREIGN KEY (ID, ProviderTypeID) REFERENCES dbo.Provider (ID, ProviderTypeID);
If written correctly (specifying the column list on INSERT) your stored procedures and application SQL code should not have to change.

sql server 2000 TSQL: creating index on table variable

Is the following possible? I am unable to do so. Do I have to have a permanent table to create index?
declare #Beatles table
(
LastName varchar(20) ,
FirstName varchar(20)
)
CREATE CLUSTERED INDEX Index_Name_Clstd ON #Beatles(LastName)
Not on a table variable, but on a temp table see this http://www.sqlteam.com/article/optimizing-performance-indexes-on-temp-tables
No, you cannot create indices on a table variable - see this article here and this posting here comparing local, global temporary tables to table variables.
Restrictions
You cannot create a non-clustered
index on a table variable, unless the
index is a side effect of a PRIMARY
KEY or UNIQUE constraint on the table
(SQL Server enforces any UNIQUE or
PRIMARY KEY constraints using an
index).
According to this post - YES you can.
The following declaration will generate 2 indexes:
DECLARE #Users TABLE
(
UserID INT PRIMARY KEY,
UserName VARCHAR(50),
FirstName VARCHAR(50),
UNIQUE (UserName,UserID)
)
The first index will be clustered, and will include the primary key.
The second index will be non clustered and will include the the columns listed in the unique constraint.
Here is another post, showing how to force the query optimizer to use the indexes generated dynamically, because it will tend to ignore them (the indexes will be generated after the execution plan is evaluated)

Resources