SQL Server UNIQUE constraint with duplicate NULLs [duplicate] - sql-server

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How do I create unique constraint that also allows nulls in sql server
I have a table where I need to force a column to have unique values.
This column must be nullable and by business logic multiple NULL values should be permitted, whereas other duplicate values are not.
SQL Server UNIQUE constraint is no good in this situation because it considers NULL as regular values, so it will reject duplicate NULLs.
Currently, value uniqueness is granted by the BLL so I'm not looking for a dirty hack to make it work.
I just would like to know if there is a clean solution to enforce this constraint in the DB.
And yeah, I know I can write a trigger to do that: is a trigger the only solution? (or the best solution anyway?)

If you're using SQL Server 2008 (won't work for earlier version) there is the concept of a filtered index. You can create the index on a filtered subset of the table.
CREATE UNIQUE INDEX indexName ON tableName(columns) INCLUDE includeColumns
WHERE columnName IS NOT NULL

Duplicate of this question?
The calculated column trick is widely known as a "nullbuster"; my notes credit Steve Kass:
CREATE TABLE dupNulls (
pk int identity(1,1) primary key,
X int NULL,
nullbuster as (case when X is null then pk else 0 end),
CONSTRAINT dupNulls_uqX UNIQUE (X,nullbuster)
)
Works on SQL Server 2000. You may need ARITHABORT on e.g.
ALTER DATABASE MyDatabase SET ARITHABORT ON

If you're using SQL Server 2008, have a look into Filtered Indexes to achieve what you want.
For older version of SQL Server, a possible alternative to a trigger involves a computed column:
Create a computed column which uses the value of your "unique" column if it's not NULL, otherwise it uses the value of the row's Primary Key column (or any column which will be unique).
Apply a UNIQUE constraint to the computed column.

http://www.sqlmag.com/article/articleid/98678/sql_server_blog_98678.html
will work only in Microsoft SQL Server 2008

You can create a view in which you select only not null values and create an index on it.
Here is the source - Creating Indexed Views

You should use UNIQUEIDENTIFIER in that column, can be NULL and also is unique by definition.
Hope that helps.

Related

Access to SQL link table showing Allow Zero Length as 'Yes'

I have made multiple attempts at creating a SQL Server table to link to an Access front-end with 'disallow zero length value' constraints on the table but when I link the table up to my front-end the design of the table shows Allow Zero Length = Yes
Now I have tried various methods of trying to change this to No (I need it to be No for a migration project I am working on). I am not sure what needs to be done on the SQL Server to ensure that upon linking this table to my access front-end, this constraint is a No.
This is the Create script for my table:
Create Table Riku(
ID int NOT NULL PRIMARY KEY,
testtext varchar(255),
CONSTRAINT DissalowNulls
CHECK (testtext <> ''),
CONSTRAINT DissalowNull2
CHECK (LEN(testtext) = 0)
);
Neither of these two constraints work. I have tried using Nvarchar, Varchar, and Text as SQL Data Type all of which yielded this same result (Yes).
Any ideas?
You must indicate to the column that does not allow null
Create Table Riku(
ID int NOT NULL PRIMARY KEY,
testtext varchar(255) NOT NULL,
CONSTRAINT DissalowNulls
CHECK (testtext <> '')
);
I am interpreting your question as:
"Why is it when I create a constraint in SQL Server to 'DisalowNulls'
does it not appear that way when viewing the table properties in
Access?"
My answer to that questions is, "they are not syntax equivalent features". When Access interprets the design of the linked table it is not perceiving these as the same property. The constraint you created in SQL Server is more equivalent to an Access Validation Rule although that will also not appear in the Access table designer.
It would be nice if Access would disable properties that aren't relevant to the database type of the linked table. Other properties like Format, Input Mask, and Caption could also be in that category.

Microsoft SQL Server 2014 sequence

A brief description, I am building a VB.NET program from scratch including database. Therefore I am required to set the unique transaction ID for each table for example header_id, detail_id, order_number, and lots more that require any running increment number. I am upgrading from SQL Server 2005 to SQL Server 2014 so that I can have a built-in SEQUENCE for the running number job.
My current situation (SQL Server 2005, VB.NET) is I am using a table to store all the running number and a stored procedure to execute the running numbers from my VB.NET program. For example in Sales Order, I will pass a hard-coded parameter to the stored procedure to find the value in the table and then increase the number by 1 and then insert it into the Sales Order table.
Before I start migrating the database and redesign the table structure, I would like to know if I am on the correct start, which means for each table I have to assign a specific sequence for it? Please guide.
Usually you do not need a SEQUENCE to generate unique, increasing identity values for single tables. Even with SQL Server 2005, you have two simpler options for that:
Define an IDENTITY column. For example:
CREATE TABLE Orders
(
OrderId INT IDENTITY(1,1) NOT NULL,
… -- ^^^^^^^^^^^^^
); -- very much like an unnamed sequence that START WITH 1 INCREMENT BY 1
When INSERT-ing into this table, you do not need to specify a value for OrderId, it will be chosen for you by the RDBMS. The resulting IDs will be unique (but there is the possibility of gaps).
Instead of using integer number IDs, use GUIDs:
CREATE TABLE Orders
(
OrderId UNIQUEIDENTIFIER ROWGUIDCOL NOT NULL DEFAULT (NEWSEQUENTIALID()),
…
);
The DEFAULT constraint means you don't have to explicitly choose a value for OrderId when INSERT-ing; the RDBMS will generate a value for you.
P.S.: NEWSEQUENTIALID() ensures that the generated GUIDs are steadily increasing. This is important if the GUID column is used for clustering (i.e. when you have a PRIMARY KEY CLUSTERED (OrderId ASC) constraint), as mentioned in a comment below. If the column is not used for clustering and it's only important that GUIDs are unique, but not necessarily increasing, then you can also use NEWID() instead.
Of course you can also use a SEQUENCE, but such a one has no added benefit over the above two (simpler) solutions. This changes when you have to create unique IDs across several tables, for example:
CREATE SEQUENCE OrderIds START WITH 1 INCREMENT BY 1;
CREATE TABLE FlowerOrders
(
OrderId INT NOT NULL DEFAULT (NEXT VALUE FOR OrderIds),
…
);
CREATE TABLE FlowerPotOrders
(
OrderId INT NOT NULL DEFAULT (NEXT VALUE FOR OrderIds)
…
);
This way it should be impossible that FlowerOrders and FlowerPotOrders contain overlapping OrderIds.

Is there a built in way to limit a column in sql server to a list of explicit values in table design view?

I have a table named myTable on SQL Server 2008 R2 Express.
I would like to have a (marital) Status column with the only explicit values: 'Single', 'Married', 'Divorced', 'Widower'.
The default should be 'Married'.
Is there a way to limit the field to the above values ON THE SQL Server without additional tables?
You can do that with a CHECK() constraint.
create table whatever (
...
Status varchar(12) not null default 'Married'
check (Status in ('Single', 'Married', 'Divorced', 'Widower')),
...
);
The problem with using a CHECK constraint like this is that it's harder for the user interface to present a list of valid choices to the user for selection. If these four were stored in a table of marital statuses, you could just select status from marital_statuses order by status;. If they were stored in a table, you could still use 'Married' as the default.
If I were going to store these in a table, it might look like this.
create table marital_statuses (
status_code char(1) primary key,
status_text varchar(12) not null unique
);
insert into marital_statuses values
('s', 'Single'),
('m', 'Married'),
('d', 'Divorced'),
('w', 'Widower');
Using human-readable codes means you usually won't need an additional join. (If you use ID numbers, you always need an additional join.) If I did that, I'd use a foreign key in the "whatever" table, and change the default to 'm'.
CHECK column constraints might fit your requirements - I don't know how well they work with character strings. See MSDN reference

PostgreSQL No Auto Increment function?

I have a test application coded in Java for creating an indexed and non indexed table in a MySQL, PostgreSQL, Oracle and Firebird database (Amongst other things).
Is it simply a case that PostgreSQL doesnt allow the auto increment feature? If not, what is the normal procedure for having an indexed coloumn?
Thanks in advance
You may use SERIAL in PostgreSQL to generate auto increment field,
For eg:-
CREATE TABLE user (
userid SERIAL PRIMARY KEY,
username VARCHAR(16) UNIQUE NOT NULL
)
This will create userid as auto-increment primary key indexed.
If you don't want this as primary key, just remove PRIMARY KEY.
Use a column of type SERIAL. It works the same way as AUTOINCREMEMT on some other DBs. (Check the docs for other features you can use with it.)
With current Postgres, you can just use SERIAL for the column type.
With older versions of Postgres, you can implement this using SEQUENCE; the relevant procedure is:
CREATE SEQUENCE mytable_myid_seq;
ALTER TABLE mytable ALTER COLUMN myid SET DEFAULT NEXTVAL('mytable_myid_seq');
A good article on this is MySQL versus PostgreSQL: Adding an Auto-Increment Column to a Table

any idea why running alter column causes column to go from “not null” to “null”?

I am mass updating a SQL Server database. I am changing all our numeric(38,0) columns to int (yes, SQL Server scripts were created from Oracle scripts).
Using SMO and C# (I am a sw engineer), I managed to generate really nice scripts like SQL Server Management Studio would.
It all works very nicely except for one particular issue:
For a handful of tables, when I call
ALTER TABLE [myTable] ALTER COLUMN [columnA] INT
it decides to also change the column from NOT NULL to NULL. That, of course is a huge issue since I need to regenerate primary keys for most of those tables on those particular columns.
Obviously, I have plenty of options using SMO to find out which columns are primary keys and force them to be NOT NULL after or while I am updating the data type, but I am really curious as to what can be causing this.
Regards,
Eric.
Because in the absense of NOT NULL, the default is NULL.
ALTER TABLE [myTable]
ALTER COLUMN [columnA] INT NOT NULL
from ALTER TABLE (Transact-SQL)
When you create or alter a table with
the CREATE TABLE or ALTER TABLE
statements, the database and session
settings influence and possibly
override the nullability of the data
type that is used in a column
definition. We recommend that you
always explicitly define a column as
NULL or NOT NULL for noncomputed
columns.

Resources