What is the difference between Unique Key and Index with IsUnique=Yes? - sql-server

I have a table with a primary key, but I want two other columns to be constrained so the combination of the two is guaranteed always to be unique.
(a dumb example: In a BOOKS table, the IBAN column is the primary key, but the combination of the Title and Author columns should also always be unique.)
In the SQL Server Management Studio it's possible to either create a new Index and set IsUnique to Yes, or I can create a new Unique Key.
What is the difference between the two approaches, and which one suits best for which purposes?

Creating a UNIQUE constraint is a clearer statement of the rule. The IsUnique attribute of the index is an implementation detail - how the rule is implemented, not what the rule is. The effect is the same though.

There is a clear difference between the 2.
A unique constraint defines what combination of columns has to be unique.
A unique index is just a way of making sure the above is always valid.
But it's possible to have a non-unique index supporting a unique constraint.
(if the constraint is deferable = Only has to be valid at commit time but is allowed to be broken in the middle of a transaction)

Just so that you know, when you create a unique constraint SQL Server will create an index behind the scenes

One thing I just found out the hard way is that in SSMS scripting of unique keys was set to true by default but the scripting of indices was set to False. When I used the Script Table As context menu from SSMS I didn't get my unique indices.
Also if the type is set to Unique Key, you can't change the "Ignore Duplicate Key" setting. First you have change the type from Unique Key to Index then you can set Ignore Duplicate Keys to true.

unique indexes are unique keys.

I do not think there is any difference between them but using unique index , we can have two benefits , as the column is already unique and also had the index on it so i gonna be more faster to search . So using unique index is more benefit.

Related

Creating a Unique SQL Table Constraint with Primary Key

We are trying to enforce a unique table constraint on certain datatables in SQL Server, which I have working but I am running into a few issues. I want it to be ordered by Primary Key, but if I include that in the Index Keys, it no longer enforces uniqueness because it obviously will always have a unique ID since its a primary key.
If I remove the ID from the indexed keys, it works as it is supposed to but it no longer sorts by Primary Key anymore, which is what I want. It sorts by another one of the columns.
How do I include the primary key in the constraint so I can use it for sorting, but have it be ignored when checking the table constraint for uniqueness(ie, it should still not allow a new record to be written if all other info is the same other than ID)?
UPDATE: How do I handle a situation where a table has more columns than can be put into an index? Can I not enforce no duplicate entries in these?
A Relational database is built based on Set theory and Predicate logic. And according to Set theory There is no difference between sets like A {1,2,3} & B {2,3,1}.
So this is the reason there is no guarantee in any RDBMS where results will come in particular order.
But you will get them in your order when you provide an ORDER BY in the SELECT statement explicitely.
So better you do it in front end or by adding an Order By clause to your query.

Why does my unique constraint show up under indexes rather then under constraints?

I created a constraint on my tsql table like this:
alter table disabledqualities
add constraint uc_uIdQualCode
unique (userId, qualitycode)
In MSSMStudio the constraint shows up under indexes rather then under constraints.
Why?
--EDIT--
I understand that it creates an index to enforce the constraint, but then why is there a node called "constraints"?
SQL Server creates an index behind the scene to enforce the constraint
here is another way of writing that by adding nonclustered telling sql server to use a nonclustered index, you can also create a clustered on providing that you don't have a PK that is clustered (the default) or another clustered index already
alter table disabledqualities
add constraint uc_uIdQualCode
unique nonclustered (userId, qualitycode)
[edit]
that node is to add check constraint, unique constraints are added under indexes
either way stay away from wizards
Check constraints and default constraints are shown under the constraints node.
SQL uses indexes to enforce unique constraints.
I understand that it creates an index to enforce the constraint, but then why is there a node called "constraints"?
This node is to display CHECK constraints.
The true answer is "because Microsoft said so. If you want the answer, you'll have to ask them".
Because UNIQUE constraints can be found in sysindexes system view
select * from sysindexes where name = 'uc_uIdQualCode'
It is simply logical
To add new Unique constaint from Studio you need to click Manage Index and Keys button. So if you are adding it from Indexes, you have to see it in Indexes :)
I'm thinking perhaps you don't understand what might show up in constraints becasue you don't know what a check constraint is. A check constraint will check the data on insert or update to see if it meets some sort of business rule. It is used for ensuring data integrity. For instance if you have an integer field that should only contain the values of 1,4 or 5 then you would set up a check constraint to make sure that 9 isn't ever added to the field. A check constraint on date field might specify that it must be later than the current date and time for a field that is the PlannedCompletionDate or that CompletionDate must be later than StartDate. These are the kind of things that show up under constraints.

SQL Server String column as a unique key

I am using a SQL server table to keep related information with a URL . So there is a Column as "URL" and its type is VARCHAR . In the application we have to use this URL as a unique key to query for information (We are using something like SELECT * FROM Table WHERE URL = "www.google.com\ig")
Is there any disadvantages or known drawbacks in using a URL as a unique key?
Usually it is a better idea to have a numeric value rather than a string as a table key. See a discussion about this subject here: Database Primary Key C# mapping - String or int.
As for using a URL, it should not pose you any problem provided that you have some basic rules to avoid inserting the same (equivalent) URL twice. That is, the database will interpret "www.google.com" and "http://www.google.com" as different strings, so you should have a rule like "URLs will never have the protocol identifier" or "URLs will never end with a slash", or whatever makes sense for your design.
As the others have said - I would definitely not use a long string like an URL as the primary/clustering key on a SQL Server table - but of course, you should feel free to put a unique constraint on that column, to make sure you don't get any duplicates!
You can either do a UNIQUE CONSTRAINT or a UNIQUE INDEX - the end result is pretty much the same (the unique constraint will also be using an index behind the scenes). The plus side for a UNIQUE INDEX is that you can reference it as a foreign key in a separate table, so I almost always use that approach:
CREATE UNIQUE NONCLUSTERED INDEX UIX_YourTable_URL ON dbo.YourTable(urlField)
If you should ever try to insert a value that's already in the table, that insert statement will be rejected with a SQL error and nothing bad can happen.
I would still create a clustered column key on the table e.g. An Auto number and then create a Unique Index on the URL column.
However I cant see why a URL is not unique and all should work as is.
You may benefit from numeric primary key if paging is needed. But still you can add numeric indexer in future. So there's no obstacle to make URL a PK.

When having an identity column is not a good idea?

In tables where you need only 1 column as the key, and values in that column can be integers, when you shouldn't use an identity field?
To the contrary, in the same table and column, when would you generate manually its values and you wouldn't use an autogenerated value for each record?
I guess that it would be the case when there are lots of inserts and deletes to the table. Am I right? What other situations could be?
If you already settled on the surrogate side of the Great Primary Key Debacle then I can't find a single reason not use use identity keys. The usual alternatives are guids (they have many disadvatages, primarily from size and randomness) and application layer generated keys. But creating a surrogate key in the application layer is a little bit harder than it seems and also does not cover non-application related data access (ie. batch loads, imports, other apps etc). The one special case is distributed applications when guids and even sequential guids may offer a better alternative to site id + identity keys..
I suppose if you are creating a many-to-many linking table, where both fields are foreign keys, you don't need an identity field.
Nowadays I imagine that most ORMs expect there to be an identity field in every table. In general, it is a good practice to provide one.
I'm not sure I understand enough about your context, but I interpret your question to be:
"If I need the database to create a unique column (for whatever reason), when shouldn't it be a monotonically increasing integer (identity) column?"
In those cases, there's no reason to use anything other than the facility provided by the DBMS for the purpose; in your case (SQL Server?) that's an identity.
Except:
If you'll ever need to merge the table with data from another source, use a GUID, which will prevent duplicate keys from colliding.
If you need to merge databases it's a lot easier if you don't have to regenerate keys.
One case of not wanting an identity field would be in a one to one relationship. The secondary table would have as its primary key the same value as the primary table. The only reason to have an identity field in that situation would seem to be to satisfy an ORM.
You cannot (normally) specify values when inserting into identity columns, so for example if the column "id" was specified as an identify the following SQL would fail:
INSERT INTO MyTable (id, name) VALUES (1, 'Smith')
In order to perform this sort of insert you need to have IDENTITY_INSERT on for that table - this is not intended to be on normally and can only be on for a maximum of 1 tables in the database at any point in time.
If I need a surrogate, I would either use an IDENTITY column or a GUID column depending on the need for global uniqueness.
If there is a natural primary key, or the primary key is defined as a unique combination of other foreign keys, then I typically do not have an IDENTITY, nor do I use it as the primary key.
There is an exception, which is snapshot configuration tables which I am tracking with an audit trigger. In this case, there is usually a logical "primary key" (usually date of the snapshot and natural key of the row - like a cost center or gl account number for which the row is a configuration record), but instead of using the natural "primary key" as the primary key, I add an IDENTITY and make that the primary key and make a unique index or constraint on the date and natural key. Although theoretically the date and natural key shouldn't change, in these tables, if a user does that instead of adding a new row and deleting the old row, I want the audit (which reflects a change to a row identified by its primary key) to really reflect a change in the row - not the disappearance of a key and the appearance of a new one.
I recently implemented a Suffix Trie in C# that could index novels, and then allow searches to be done extremely fast, linear to the size of the search string. Part of the requirements (this was a homework assignment) was to use offline storage, so I used MS SQL, and needed a structure to represent a Node in a table.
I ended up with the following structure : NodeID Character ParentID, etc, where the NodeID was a primary key.
I didn't want this to be done as an autoincrementing identity for two main reasons.
How do I get the value of a NodeID after I add it to the database/data table?
I wanted more control when it came to generating my own IDs.

primary key on very small table

I am having a very small tables with at most 5 records that holds some labels. I am using Postgres.
The structure is as follows:
id - smallint
label - varchar(100)
The table will be used mainly to reference the rows from other tables. The question is if it's really necessary to have a primary key on id or to have just an index on the id or have them both?
I did read about indexes and primary keys and I understand that this depends quite a lot on what's the table going to be used for:
Tables with no Primary Key
Edit: I was going to ask about having a primary key or an index or have them both. I edited the question.
It is always good practice to have a primary key column. The typical scenario it is needed is when you want to update or delete a row, having a PK makes it much easier and safer.
Yes, a primary key is not only good practice -- it's crucial. A table that lacks a unique key fails to be in First Normal Form.
You must declare a PRIMARY KEY or UNIQUE constraint if you want other tables to reference this one with a foreign key.
In most RDBMS brands, both PRIMARY KEY and UNIQUE constraints implicitly create an index on the column(s). If it doesn't do this implicitly, you may be required to define the index yourself before you can declare the constraint.
Yes, you will need a primary key on the id field, since you do not want two labels that share the same id.
You also want an index, to speed up the search/lookup process in this table (although for small tables there is less performance gain). The sequence will just help you fill in the next ID; it does not prevent you from changing a previous value into one that already exists.
There are very little reasons for creating an index instead of a primary key. AS Bill Karwin said, you won't save resources at all. And, as you may have already guessed, there is no need at all to create a new index if you have the primary key.
In some cases it may be hard to find a key candidate. But it doesn't seems to be the case and it clearly goes against some good practices.
By the way. As your table is so small most queries will rather use a full table scan even if there is an index. Don't worry you see a full table scan.
From the developer's point of view, PRIMARY KEY is just a combination of NOT NULL and UNIQUE INDEX on one of the columns.
A UNIQUE INDEX is good if:
You need to enforce uniqueness. Using index is the most efficient way to do that.
You need to perform a SELECT, UPDATE or DELETE with a WHERE condition that is selective on the indexed field, that is number of rows affected by the query is much less that total number of the rows (say, 10 rows of 2,000,000).
A UNIQUE INDEX is bad if:
You don't need uniqueness on this field, of course :) But you'll better have one unique index in the table, for each record to be identifiable.
You need fast INSERTS
You need fast UPDATE's and DELETE's of the indexed value with a WHERE condition that is not selective on the indexed field, that is number of rows affected by the query is comparable to the total number of the rows (say, 1,500,000 rows of 2,000,000).
Given that you are going to have a little table, I'd advice you to create a PRIMARY KEY on it.

Resources