ALTER TABLE query for foreign key constraint does not work - sql

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.

Related

Create table with foreign key to an other table created below in sql file

My problem is that i have two tables with each table having a foreign key to the other table.
Each time , i execute the SQL file containing the creation of the two tables, it gives me an error that he doesn't find the other table. I'm working with sqlplus to execute the sql file.
Here's an example of SQL file i tried with :
create table A(
Age number(3),
name number(3) constraint A_FK references B(name))
/
create table B(
Age number(3) constraint B_FK references A(Age),
name number(3))
And even if i reverse the order, it gives the same error.
Thanks for help.
This is a problem of cycles in foreign keys. One method is to add all foreign keys after table creation (as I think the other answers propose).
You can also just do that for the first table:
create table A (
Age number(3) primary key,
name number(3)
);
create table B (
name number(3) primary key,
Age number(3),
constraint B_FK foreign key (age) references A(Age)
);
alter table B add constraint A_FK foreign key (name) references B(name);
Here is a db<>fiddle.
Notes:
Foreign keys should reference primary keys, so I added that declaration as well.
I recommend making the primary key the first column in the table.
You can also define the constraint inline for one of the tables (i.e. age number(3) constraint b_fk references a(age)).
The table column(s) that is referred by a foreign key must exist at the time when the constraint is created. Since you have some kind of cyclic reference between the tables, you need to do this in three steps:
first create one table without the foreign key
create the second table (with its foreign key)
finally add the foreign key to the first table with an alter table statement
You also need the referred column to have a unique or primary key constraint set up, otherwise you would get error ORA-02270: no matching unique or primary key for this column-list.
create table A(
age number(3) primary key,
name number(3)
);
create table B(
age number(3) constraint B_FK references A(Age),
name number(3) primary key
);
alter table A add constraint A_FK foreign key (name) references B(name);
Demo on DB Fiddle
Side note: I am quite suspicious about your sample structure, but this could be because your oversimplified it in the question.
It fails because the reference table doesn't exist yet.
Create the tables without the key first. Then drop one and recreated it with the reference. Then drop the 2nd and recreate it with the reference.
Create table first and then ADD the CONSTRAINT
ALTER TABLE A
ADD FOREIGN KEY (name) REFERENCES B(name);
ALTER TABLE B
ADD FOREIGN KEY (age) REFERENCES A(age);

How to add foreign key to an existing column in SQL Server 2012

I am trying to add foreign key to my existing column using below query
ALTER TABLE Sub_Category_Master
ADD FOREIGN KEY (Category_ID) REFERENCES Category_Master(Category_ID)
but I'm getting an error
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK__Sub_Categ__Categ__5812160E". The conflict occurred in database "shaadikarbefikar_new", table "shaadikarbefikar.Category_Master", column 'Category_ID'.
Well, the error clearly tells you that Category_ID in your Sub_Category_Master table contains some values that are not present in Category_Master (column Category_ID). But that's exactly the point of having a foreign key constraint - making sure your child table (Sub_Category_Master) only uses defined values from its parent table.
Therefore, you must fix those "voodoo" values first, before you're able to establish this foreign key relationship. I would also strongly recommend to explicitly name that constraint yourself, to avoid those system-generated, but not really very useful constraint names like FK__Sub_Categ__Categ__5812160E:
ALTER TABLE Sub_Category_Master
ADD CONSTRAINT FK_SubCategoryMaster_CategoryMaster
FOREIGN KEY (Category_ID) REFERENCES Category_Master(Category_ID)
ALTER TABLE Sub_Category_Master
ADD CONSTRAINT FKSub_Category_Master_Category_ID FOREIGN KEY (Category_ID)
REFERENCES Category_Master(Category_ID);
CREATE TABLE Orders
(
OrderID int NOT NULL,
OrderNumber int NOT NULL,
PersonID int,
PRIMARY KEY (OrderID),
CONSTRAINT FK_PersonOrder
FOREIGN KEY (PersonID) REFERENCES Persons(PersonID)
);

Difference between using or not using CONSTRAINT keyword on SQL Server

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.

create foreign key in oracle

is there anyone who can help me to create a foreign key for my Status table. I need to PLACE a foreign key constraint on the code in the status table, referring to the id in the Building table.
TABLE building
(
build_name VARCHAR2(50,0) NOT NULL,
id NUMBER (38,0) NOT NULL,
mapid NUMBER (10,0) NOT NULL
);
TABLE STATUS
(
code VARCHAR(2 BYTE) NOT NULL,
status_name VARCHAR2(40 BYTE) NOT NULL,
);
Bulding table has constraint building_gmidx with id as primary key.
Here is a quick syntax for your current requirement, however I recommend you to go through the oracle documentation for a proper understanding of what this means.
ALTER TABLE STATUS ADD (
CONSTRAINT status_fk_building FOREIGN KEY (code)
REFERENCES building (id)
ENABLE VALIDATE);
Did you leave out CREATE TABLE *name* to save time when writing the question? The first thing I see is that your Foreign key has to have the same data type and size as your Primary key. If the Tables already exist the code would be:
ALTER TABLE status MODIFY (code NUMBER(38));
From there you would need to
ALTER TABLE status ADD FOREIGN KEY (code) REFERENCES (building_gmidx)
Why is the constraint for building Primary key named building_gmidx and the column plain id?? All Normalized table attributes should be Unique. Wouldn't it be better if you just named the column "id" building_gmidx instead. Just in case there are other types of id's added later you do not have to think about which table "id" pertains to. Let me know if this works.

There are no PK in the referenced table. Why?

I have the following T-SQL to create 3 SQL tables:
create table dbo.Posts
(
Id int identity not null
constraint PK_Posts_Id primary key clustered (Id),
Active bit not null
constraint DF_Posts_Active default (0)
);
create table dbo.PostsLocalized
(
Id int not null,
Culture int not null
constraint CK_PostsLocalized_Culture check ([Culture] in ('1', '2', '3')),
[Text] nvarchar (200) not null,
constraint PK_PostsLocalized_Id_Culture primary key clustered (Id, Culture)
);
create table dbo.Tags
(
Id int identity not null
constraint PK_Tags_Id primary key clustered (Id),
Name nvarchar not null
);
create table dbo.PostsLocalized_Tags
(
PostLocalizedId int not null,
TagId int not null,
constraint PK_PostsLocalized_Tags_Post_PostLocalizedId_TagId primary key clustered (PostLocalizedId, TagId)
);
Then I have added the following constraints:
alter table dbo.PostsLocalized
add constraint FK_PostsLocalized_Id foreign key (Id) references dbo.Posts(Id) on delete cascade on update cascade;
alter table dbo.PostsLocalized_Tags
add constraint FK_PostsLocalized_Tags_PostLocalizedId foreign key (PostLocalizedId) references PostsLocalized(Id) on delete cascade on update cascade,
constraint FK_PostsLocalized_Tags_TagId foreign key (TagId) references Tags(Id) on delete cascade on update cascade;
But I get the following error:
There are no primary or candidate keys in the referenced table 'PostsLocalized' that match the referencing column list in the foreign key 'FK_PostsLocalized_Tags_PostLocalizedId'.
How can I solve this?
Thank You,
Miguel
SQL Server mandates that foreign key references be to a primary key or unique key. The foreign key reference has to be to all the columns that constitute the primary/unique key. The documentation says:
In a foreign key reference, a link is created between two tables when
the column or columns that hold the primary key value for one table
are referenced by the column or columns in another table. This column
becomes a foreign key in the second table.
A FOREIGN KEY constraint does not have to be linked only to a PRIMARY
KEY constraint in another table; it can also be defined to reference
the columns of a UNIQUE constraint in another table. A FOREIGN KEY
constraint can contain null values; however, if any column of a
composite FOREIGN KEY constraint contains null values, verification of
all values that make up the FOREIGN KEY constraint is skipped. To make
sure that all values of a composite FOREIGN KEY constraint are
verified, specify NOT NULL on all the participating columns.
The primary key in PostsLocalized contains the culture column, so you need to add it into the foreign key reference.
Your PK on PostsLocalized table is complex consisting of two columns - id and culture and you are trying to create FK on only one of those columns which is not possible.
You'll have to either add Culture column on PostsLocalized_Tags and use them both in foreign key or remove Culture from your PK on PostLocalized