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.
Related
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).
I'm a beginner and creating my own simple blockchain app for fun. The blockchain itself is fully functional. Now I'm trying to implement a database to store the data of the blockchain (right now I'm writing it to a .txt file). So I want to create the following database schema in sqlite:
CREATE TABLE `Blockchain`
(
`previous_hash` string NOT NULL ,
`timestamp` float NOT NULL ,
`signature_of_transactions` string NOT NULL ,
`index` bigint NOT NULL ,
PRIMARY KEY (`previous_hash`)
);
CREATE TABLE `Wallet`
(
`public_key` string NOT NULL ,
PRIMARY KEY (`public_key`)
);
CREATE TABLE `Transactions`
(
`signature` string NOT NULL ,
`sender` string NOT NULL ,
`recipient` string NOT NULL ,
`amount` float NOT NULL ,
PRIMARY KEY (`signature`)
);
CREATE TABLE `Peer_nodes`
(
`id` string NOT NULL ,
`public_key` string NOT NULL ,
PRIMARY KEY (`id`)
);
ALTER TABLE `Wallet`
ADD CONSTRAINT `fk_Wallet_public_key`
FOREIGN KEY(`public_key`) REFERENCES `Peer_nodes` (`public_key`);
ALTER TABLE `Transactions`
ADD CONSTRAINT `fk_Transactions_signature`
FOREIGN KEY(`signature`) REFERENCES `Blockchain` (`signature_of_transactions`);
ALTER TABLE `Transactions`
ADD CONSTRAINT `fk_Transactions_sender`
FOREIGN KEY(`sender`) REFERENCES `Wallet` (`public_key`);
ALTER TABLE `Transactions`
ADD CONSTRAINT `fk_Transactions_recipient`
FOREIGN KEY(`recipient`) REFERENCES `Wallet` (`public_key`);
Creating the tables with the columns etc. works fine with the script above. The ALTER TABLE queries do not work somehow. This is the following error message I receive:
ALTER TABLE Wallet ADD CONSTRAINT fk_Wallet_public_key FOREIGN KEY(public_key) REFERENCES Peer_nodes (public_key)
ERROR:
As you can see, it has no real error message. I haven't found a possible error in the queries themselves after searching a lot on the internet. What am I doing wrong? I try to do this via phpLitedmin, so maybe the problem is there?
SQLite's ALTER TABLE does not support adding constraints.
You have to include the constraints into the CREATE TABLE statements.
And as already noted by Gordon, foreign key constraints require the target to be a primary or candidate key.
Your foreign key reference is to the wrong column. It should be to the primary key, although it can be to a unique key.
As explained in the documentation:
Usually, the parent key of a foreign key constraint is the primary key
of the parent table. If they are not the primary key, then the parent
key columns must be collectively subject to a UNIQUE constraint or
have a UNIQUE index. If the parent key columns have a UNIQUE index,
then that index must use the collation sequences that are specified in
the CREATE TABLE statement for the parent table.
You should fix the table definition and add the foreign key to use the primary key.
What is the difference between using or not using the CONSTRAINT keyword when working with Foreign Keys on SQL Server?
I noticed that apparently both worked the same in this specific case, without CONSTRAINT:
CREATE TABLE ClientsPhones
(
ClientPhone varchar(10) NOT NULL,
ClientID smallint NOT NULL,
PRIMARY KEY (ClientPhone),
FOREIGN KEY (ClientID) REFERENCES Clients(ClientID)
);
And with CONSTRAINT:
CREATE TABLE ClientsPhones
(
ClientPhone varchar(10) NOT NULL,
ClientID smallint NOT NULL,
PRIMARY KEY (ClientPhone),
CONSTRAINT fk_ClientID
FOREIGN KEY (ClientID) REFERENCES Clients(ClientID)
);
Both didn't let me add records to the table unless the ClientID already existed on the Clients table, and the same ClientID and ClientPhone weren't already on the ClientsPhones table.
Is there any real difference between the two besides the fact that I'm able to name the constraint?
If you don't create constraint.it will automatically create own constraint name
the foreign key index name is generated using the name of the referencing foreign key column Automatically.
So there is no way to see difference of using and not using Constraint keyword. by default constraint name will be defined.
I did some research and don't believe Hell Boy's answer was as clear as it could be and had some misinformation.
Every constraint you add to a database has a name set by default. This includes PRIMARY KEY, FOREIGN KEY, DEFAULT, NOT NULL. It isn't necessarily the name of the column(s) used.
You can imagine that when you don't use the CONSTRAINT keyword SQL Server puts it there as well as generates a name for you.
If you want to remove or change a constrain you would either have to delete the entire table and recreate it with the correct constraints or you can reference the constraint by name and then alter it somewhat like a column using the ALTER keyword. This can be useful for when you need to delete a table with a foreign key. If you name the foreign key constraint you can delete it and then the table instead of having to delete the table the foreign key points to.
I have not seen any clear, concise examples of this anywhere online.
With an existing table, how do I add a foreign key which references this table? For example:
CREATE TABLE dbo.Projects(
ProjectsID INT IDENTITY(1,1) PRIMARY KEY,
Name varchar(50)
);
How would I write a command to add a foreign key which references the same table? Can I do this in a single SQL command?
I'll show you several equivalent ways of declaring such a foreign key constraint. (This answer is intentionally repetitive to help you recognise the simple patterns for declaring constraints.)
Example: This is what we would like to end up with:
Case 1: The column holding the foreign keys already exists, but the foreign key relationship has not been declared / is not enforced yet:
In that case, run this statement:
ALTER TABLE Employee
ADD FOREIGN KEY (ManagerId) REFERENCES Employee (Id);
Case 2: The table exists, but it does not yet have the foreign key column:
ALTER TABLE Employee
ADD ManagerId INT, -- add the column; everything else is the same as with case 1
FOREIGN KEY (ManagerId) REFERENCES Employee (Id);
or more succinctly:
ALTER TABLE Employee
ADD ManagerId INT REFERENCES Employee (Id);
Case 3: The table does not exist yet.
CREATE TABLE Employee -- create the table; everything else is the same as with case 1
(
Id INT NOT NULL PRIMARY KEY,
ManagerId INT
);
ALTER TABLE Employee
ADD FOREIGN KEY (ManagerId) REFERENCES Employee (Id);
or, declare the constraint inline, as part of the table creation:
CREATE TABLE Employee
(
Id INT NOT NULL PRIMARY KEY,
ManagerId INT,
FOREIGN KEY (ManagerId) REFERENCES Employee (Id)
);
or even more succinctly:
CREATE TABLE Employee
(
Id INT NOT NULL PRIMARY KEY,
ManagerId INT REFERENCES Employee (Id)
);
P.S. regarding constraint naming: Up until the previous revision of this answer, the more verbose SQL examples contained CONSTRAINT <ConstraintName> clauses for giving unique names to the foreign key constraints. After a comment by #ypercube I've decided to drop these clauses from the examples, for two reasons: Naming a constraint is an orthogonal issue to (i.e. independent from) putting the constraint in place. And having the naming out of the way allows us to focus on the the actual adding of the constraints.
In short, in order to name a constraint, precede any mention of e.g. PRIMARY KEY, REFERENCES, or FOREIGN KEY with CONSTRAINT <ConstraintName>. The way I name foreign key constraints is <TableName>_FK_<ColumnName>. I name primary key constraints in the same way, only with PK instead of FK. (Natural and other alternate keys would get the name prefix AK.)
You can add the column and constraint in one operation
ALTER TABLE dbo.Projects ADD
parentId INT NULL,
CONSTRAINT FK FOREIGN KEY(parentid) REFERENCES dbo.Projects
Optionally you could specify the PK column in brackets after the referenced table name but it is not needed here.
If the table already exists: Assuming you don't already have a column to store this data. If you do then skip this step.
ALTER TABLE [dbo].[project]
ADD [fkProjectsId] INT;
GO
ALTER TABLE [dbo].[projects]
ADD CONSTRAINT [FK_Projects_ProjectsId] FOREIGN KEY ([fkProjectsId]) REFERENCES [dbo].[Projects] ([ProjectsID])
GO
I mean for example I can create table like
create table XTable
(
idt int not null primary key,
value nvarchar(50),
idq int,
constraint fk_idq foreign key(idq) references YTable(idq)
)
and I can create it like this
create table XTable
(
idt int not null primary key,
value nvarchar(50),
idq int,
foreign key(idq) references YTable(idq)
)
I usually create table like in the second example but now I'm curious about the first example. What is the difference?
The first one assigns a user-defined name to the foreign key, the second one will assign a system-generated name to the foreign key.
User-defined foreign key names can be useful for subsequent statements like these:
ALTER TABLE XTable DROP CONSTRAINT fk_idq;
ALTER TABLE XTable ENABLE CONSTRAINT fk_idq;
ALTER TABLE XTable DISABLE CONSTRAINT fk_idq;
It's harder to alter constraints with system-generated names, as you have to discover those names first.
The first option is purely for naming the constraint.
From SQL FOREIGN KEY Constraint
To allow naming of a FOREIGN KEY constraint, and for defining a FOREIGN KEY constraint on multiple columns, use the following SQL syntax
CREATE TABLE Orders
(
O_Id int NOT NULL,
OrderNo int NOT NULL,
P_Id int,
PRIMARY KEY (O_Id),
CONSTRAINT fk_PerOrders FOREIGN KEY (P_Id)
REFERENCES Persons(P_Id)
)
Also, from CREATE TABLE (Transact-SQL) one can see that [ CONSTRAINT constraint_name ] is optional.
Apart from controlling the name, nothing really. SQL Server will supply a name if you omit it. FYI, you only need this syntax (SQL Fiddle):
create table XTable
(
idt int not null primary key,
value nvarchar(50),
idq int references YTable(idq)
)
Here's a fuller example.