Cannot define PRIMARY KEY constraint on nullable column in table 'tp_ladder' - sql

I'm trying to run the following SQL statement
--dropping customer TABLE--
DROP TABLE tp_ladder;
--creating ladder TABLE
CREATE TABLE tp_ladder (
ladder_id INTEGER,
ladder_type VARCHAR(50),
ladder_name VARCHAR(50) NOT NULL,
ladder_discount DECIMAL(3,2),
ladder_price DECIMAL(8,2) NOT NULL,
ladder_weight DECIMAL(5,2),
ladder_height DECIMAL(5,2),
ladder_rating DECIMAL(10,2),
warehouse_id INTEGER
);
--creating primary key for ladder table
ALTER TABLE tp_ladder
ADD CONSTRAINT tp_ladder_ladder_id
PRIMARY KEY(ladder_id);
However I receive the error message:
Cannot define PRIMARY KEY constraint on nullable column in table 'tp_ladder'
Any advice?

The error is quite clear, but why it is an error is not obvious.
Other databases (such as MySQL and Postgres), do allow you to do what you want -- adding a primary key on a column that is not explicitly declared as NOT NULL. After all, PRIMARY KEY imposes a NOT NULL constraint as well. This is surprising, especially on an empty table. So, the error is not obvious.
Further, SQL Server stores the null flags for all columns, even those that are declared NOT NULL. So, even if there were data, then the data would not need to change (assuming there are no NULL values). Not all databases store NULL flags the same way.
If you have defined the table, you can modify the column using:
ALTER TABLE tp_ladder ALTER COLUMN ladder_id INT NOT NULL
This will allow you then add the primary key constraint.
But, I recommend doing it in-line when you create the table:
ladder_id INT PRIMARY KEY
Note that when defined in the CREATE TABLE, the NOT NULL is not needed (it is actually redundant).

Related

Use CONSTRAINT keyword when creating a table

A question on using the CONSTRAINT keyword when creating a new table. I saw some code like this below:
CREATE TABLE dbo.T1
(
keycol INT NOT NULL IDENTITY(1, 1)
CONSTRAINT PK_T1 PRIMARY KEY,
datacol NVARCHAR(40) NOT NULL
);
My question is, isn't NOT NULL also a CONSTRAINT the same as PRIMARY KEY, so why do we place CONSTRAINT keyword for PRIMARY KEY, but not for NOT NULL?
The NOT NULL constraint can be modified using an ALTER TABLE ALTER COLUMN statement. Therefore, an explicit name for a NOT NULL constraint is useless. The name of a NOT NULL constraint will not be stored in the database's metadata.
Other constraints (primary key, foreign key, unique, check, and default) can be removed using an ALTER TABLE DROP CONSTRAINT statement. For such statements, a constraint name has to be specified. So technically a constraint name is always required for such constraints.
But constraint names are always optional in the SQL syntax, so you can always omit CONSTRAINT [constraintname] when creating a constraint. So this is valid SQL too:
CREATE TABLE dbo.T1
(
keycol INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
datacol NVARCHAR(40) NOT NULL
);
However, for constraints that actually will require a constraint name for removal, the DBMS will automatically generate a constraint name if one is not supplied explicitly. In the above CREATE TABLE statement, the primary key will get a name like PK__T1__98D78B44D915DA1F.
Explicitly naming your primary keys, foreign keys, unique constraints, check constraints and default constraints will ease future maintenance of your database tables. If you explicitly name your constraints, you always know exactly how the constraints are named. If you want to remove a "nameless" constraint, you have to look up its generated name in the database's metadata first (which I consider to be quite ugly and complex).
As documented in CREATE TABLE
CONSTRAINT Is an optional keyword that indicates the start of the
definition of a PRIMARY KEY, NOT NULL, UNIQUE, FOREIGN KEY, or CHECK
constraint.
so you can use the CONSTRAINT keyword there if you want
CREATE TABLE dbo.T1
(
keycol INT NOT NULL IDENTITY(1, 1)
CONSTRAINT PK_T1 PRIMARY KEY,
datacol NVARCHAR(40) CONSTRAINT Foo NOT NULL
);
This is pointless though as the constraint keyword is only ever required for constraints when specifying a name. And when used with NOT NULL this does not actually create a constraint object in sys.constraints, so the name is not stored anywhere. It is just a property of the column whether or not it is nullable.

Is my query correct when I set primary key for 3 columns in a table?

In my case, I have only 1 candidate may go with 1 job at the time so they are must be 2 primary key.
Then, a column is as JobApplicationId use for the table CandidateDetail as a foreign key.
Is that correct when I decide to set these 3 columns above as primary key or there are other ways to address my problem here?
CREATE TABLE Candidate(
CandidateId int identity primary key,
FullName nvarchar(50)
)
CREATE TABLE Job(
JobId int identity primary key,
JobTitle nvarchar(50)
)
CREATE TABLE JobApplication(
JobApplicationId int identity,
JobId int,
CandidateId int,
CreatedDate datetime,
primary key(JobApplicationId, JobId, CandidateId)
)
CREATE TABLE CandidateDetail(
CandidateDetailId int identity primary key,
JobApplicationId int,
[Description] nvarchar(300)
)
ALTER TABLE JobApplication ADD CONSTRAINT fk_JobApplication_Job FOREIGN KEY (JobId) REFERENCES Job(JobId)
ALTER TABLE JobApplication ADD CONSTRAINT fk_JobApplication_Candidate FOREIGN KEY (CandidateId) REFERENCES Candidate(CandidateId)
ALTER TABLE CandidateDetail ADD CONSTRAINT fk_CandidateDetail_JobApplication FOREIGN KEY (JobApplicationId) REFERENCES JobApplication(JobApplicationId)
Instead of a primary key with three columns you could just have JobApplicationId as the primary key and a unique constraint on JobId, CandidateId.
Otherwise, two rows with JobApplicationId=1, JobId=1, CandidateId=1 and JobApplicationId=2, JobId=1, CandidateId=1 would still be valid in terms of your current primary key approach, but would be invalid in terms of the business case.
From both a performance and usability perspective, a compound primary key can be a hassle and can create performance issues. Personally, I would choose JobApplicationId as the primary key (because this is an identity column and will be unique for each record). Then, if you need to constrain the table so that JobId and CandidateId are always unique (not allowing more than 1 record for any given candidate and the job they've applied for) then I would use a compound Unique Constraint.
However, I would suggest that you evaluate those requirements more closely because what if a candidate applies for the same position in a different time frame? It might stand to reason that having the same candidate applied to the same job more than once in that table might be valid data.

ADD CONSTRAINT "CHECK ([TYPE] IN (...) Gan I get the constraint values from other table?

I'm having a problem building some constraints in my MSSQL database. This database will be used for a small electronics store. For the moment I have this to create my database:
CREATE TABLE [dbo].[PRODUCT] (
[ID] INT NOT NULL PRIMARY KEY IDENTITY(1,1),
[ID_SUBCAT] INT NOT NULL,
[KORTING] FLOAT NULL,
[PRIJS] FLOAT NULL,
[TYPE] VARCHAR(5) NOT NULL )
And now I want to add a constraint that the [TYPE] column can only hold certain values. So I came up with this constraint
GO ALTER TABLE [dbo].[PRODUCT] ADD CONSTRAINT [ProperTypeEntered] CHECK ([TYPE] IN ('Camera', 'Lens'))
But when I have a new type that I want to add I always have to edit this constraint because the values are hardcoded in the constraint. So I was hoping that I could make a second table with all the types in like so:
CREATE TABLE [dbo].[TYPES] (
[ID] INT NOT NULL PRIMARY KEY IDENTITY(1,1),
[NAAM] VARCHAR(5) NOT NULL )
And just have a constraint that will allow only that are inserted in the TYPES.NAAM column.
Is that in anyway possible or am I just overlooking something? My knowledge of SQL is limited so any help would be great! :)
Your not able to make a constraint that does a query. But you could do it based on a trigger for insert/update, that would query your second table, if the "type" isn't found you could throw an expection which would cause the insert/update to fail.
The best solution is to create another table, like you're suggesting, only call it ProductTypes. Add a new INT Column called TypeID to dbo.Products. Create a Foreign Key from dbo.Products.TypeID to dbo.ProductTypes.ID. Make sure you have all of the types added into your dbo.ProductTypes table. Also, add a column "IsActive" BIT so that you don't have to delete product types later. If you have any products that aren't in the types table, after you have the foreign key, insert NULL.

Can I change a varchar constraint in SQL Server 2005 after I have defined my PK's and FK's?

Can I change a varchar constraint in SQL Server 2005, after I have defined my PK's and FK's?
varchar(10) ----> varchar (50)
If the column in question is part of a foreign key constraint, then obviously not - the data types on both sides of the constraint must match exactly, and an ALTER TABLE statement can only affect a single table at a time.
If this is just another column in a table that has a foreign key constraint, then yes, it can be altered.
If the column is just part of a primary key or unique constraint, and is not referenced by a foreign key, it can be altered. It took me ~30 seconds to write this:
create table T1 (
ID varchar(10) not null PRIMARY KEY,
Val1 varchar(10) not null UNIQUE
)
go
insert into T1 (ID,Val1) values ('abc','def')
go
alter table T1 alter column Val1 varchar(50) not null
go
alter table T1 alter column ID varchar(50) not null
It runs without errors.
Where the column is involved in a foreign key, you will need to drop the FK constraint, change the data type, then recreated the foreign key. Very trivial, actually, especially if, before dropping constraints, you script them out using SSMS because changing the data type does not affect the FK constraint's definition; the issue is just that you can't change the data type while the constraint is in place.

SQL Server 2008 R2. Incorrect syntax near 'AUTO_INCREMENT'

Why do i get the following error
Incorrect syntax near 'AUTO_INCREMENT'.
while trying to execute
CREATE TABLE Person
(
P_Id int NOT NULL AUTO_INCREMENT,
Name varchar(255),
PRIMARY KEY (P_Id)
)
What is the correct syntax?
CREATE TABLE Person(
P_Id int NOT NULL IDENTITY(1,1) PRIMARY KEY,
Name varchar(255))
You should explicitly state whether NAME is NULL or NOT NULL so you are not dependant upon the current connection settings that happen to be in effect.
create table Person
(
PersonId int identity(1,1)
constraint PK_Person primary key,
Name varchar(255) not null
)
Some comments:
It is not needed to specify not null for identity column as identity column cannot be nullable. ANSI_NULL_DFLT_ON option does not affect 'nullability' of identity column.
On other hand it is important to specify 'not null / null' for Name column, as it will be affected by ANSI_NULL_DFLT_ON value.
It is always a good idea to explicitly specify names for constraints. Because if you don't, name constraint name will be generated. If you need to delete the constraint later, you will have to find out the auto-generated name.