Alter Sql table (Change foreign key to Second primary of the table) - sql

I've a sql table with a primary key(Auto Incremented) and a foreign key.Now I need to modify the table by modifying the foreign key to second primary key so that its values are not allowed to duplicate.
How do i alter my table without affecting the data? Need the sql code.
Regards,
Vix

If I understand your request, you want to force the foreign key to be unique within the given table so your schema looks like:
Create Table Table1
(
Id int not null primary key clustered
, ForeignId not null
, ...
, Constraint FK_Table1_Table2
Foreign Key ( ForeignId )
References Table2( Id )
)
And you now want to force ForeignId to be unique in this table, correct? You would do the following:
Alter Table Table1
Add Constraint UC_Table1_ForeignId Unique Nonclustered ( ForeignId )

Related

SQl foreign key disabling

Is there a way i can declare a disabled foreign key in the table creation in SQL
i don't want to do it by altering the table if possible.
From the CONSTRAINT documentation, use the DISABLE keyword:
CREATE TABLE table1 (
ID NUMBER PRIMARY KEY
)
CREATE TABLE table2 (
OTHER_ID CONSTRAINT table2__other_id__fk REFERENCES table1 (id) DISABLE
);
fiddle

PostgreSQL Partition and Unique Conflict

I am attempting to set up a database with partitions, however I am running into an error when creating the activity table. The 3 Table CREATEs (without the actual data) are as follows:
CREATE TABLE collection (
id SERIAL PRIMARY KEY
);
CREATE TABLE asset (
id SERIAL,
collection_id INT,
CONSTRAINT fk_collection
FOREIGN KEY(collection_id)
REFERENCES collection(id),
CONSTRAINT asset_pkey PRIMARY KEY(id, collection_id)
)PARTITION BY LIST(collection_id);
CREATE TABLE activity(
id SERIAL,
collection_id INT,
CONSTRAINT fk_collection
FOREIGN KEY(collection_id)
REFERENCES collection(id),
CONSTRAINT activity_pkey PRIMARY KEY(id, collection_id),
asset_id INT,
CONSTRAINT fk_asset
FOREIGN KEY(asset_id)
REFERENCES asset(id)
) PARTITION BY LIST(collection_id);
ERROR: there is no unique constraint matching given keys for referenced table "asset"
SQL state: 42830
My understanding of the error is that foreign keys must be unique. Because I must add collection_id as a primary key to partition item, I cannot also designate id as unique. When I attempt to make id unique, this is what happens:
ALTER TABLE asset
ADD CONSTRAINT u_id UNIQUE (id);
ERROR: unique constraint on partitioned table must include all partitioning columns
DETAIL: UNIQUE constraint on table "asset" lacks column "collection_id" which is part of the partition key.
SQL state: 0A000
Even if I successfully add the UNIQUE constraint on id and collection_id, it continues to throw me SQL state: 42830. Do I have to restructure my data or is there a better way to go about this that I'm not thinking of?
Would it be enough to merge the foreign keys on asset into one composite key, or does that violate some other constraint of your data?
CREATE TABLE activity(
id SERIAL,
collection_id INT,
asset_id INT,
CONSTRAINT activity_pkey PRIMARY KEY(id, collection_id),
CONSTRAINT fk_asset_collection
FOREIGN KEY(asset_id, collection_id)
REFERENCES asset(id, collection_id)
) PARTITION BY LIST(collection_id);

Check if data exists in another table on insert?

Table A
(
Table_A_ID int
)
Table B
(
Table_B_ID int
Value int
)
Say I want to insert data into Table B, where 'Value' would be the same as a Table_A_ID.
How would I make a constraint or check that the data actually exists in the table on insertion?
You probably need to enforce data integrity not only on INSERT into Table B, but also on UPDATE and DELETE in both tables.
Anyway options are:
FOREIGN KEY CONSTRAINT on Table B
TRIGGERs on both tables
As a last resort if for some reason 1 and 2 is not an option STORED PROCEDUREs for all insert, delete update operations for both tables
The preferred way to go in most cases is FOREIGN KEY CONSTRAINT.
Yap, I agree with #peterm.
Cause, if your both Table_A_ID and Table_B_Id are primary keys for both tables, then you don't even need two tables to store the value. Since, your two tables are seems to be on 'one-to-one' relationship. It's one of the database integrity issues.
I think you didn't do proper normalisation for this database.
Just suggesting a good idea!
I found this example which demonstrates how to setup a foreign key constraint.
Create employee table
CREATE TABLE employee (
id smallint(5) unsigned NOT NULL,
firstname varchar(30),
lastname varchar(30),
birthdate date,
PRIMARY KEY (id),
KEY idx_lastname (lastname)
) ENGINE=InnoDB;
Create borrowed table
CREATE TABLE borrowed (
ref int(10) unsigned NOT NULL auto_increment,
employeeid smallint(5) unsigned NOT NULL,
book varchar(50),
PRIMARY KEY (ref)
) ENGINE=InnoDB;
Add a constraint to borrowed table
ALTER TABLE borrowed
ADD CONSTRAINT FK_borrowed
FOREIGN KEY (employeeid) REFERENCES employee(id)
ON UPDATE CASCADE
ON DELETE CASCADE;
NOTE: This tells MySQL that we want to alter the borrowed table by adding a constraint called ‘FK_borrowed’. The employeeid column will reference the id column in the employee table – in other words, an employee must exist before they can borrow a book.
The final two lines are perhaps the most interesting. They state that if an employee ID is updated or an employee is deleted, the changes should be applied to the borrowed table.
NOTE: See the above URL for more details, this is just an excerpt from that article!
Create a foreign key constraint on the column 'Value' on table B that references the 'Table_A_ID' column.
Doing this will only allow values that exist in table A to be added into the 'Value' field of table B.
To accomplish this you first need to make Table_A_ID column the primary key for table A, or it at least has to have some sort of unique constraint applied to it to be a foreign key candidate.
BEGIN TRANSACTION -- REMOVE TRANSACTION AND ROLLBACK AFTER DONE TESTING
--PUT A PRIMARY KEY ON TABLE A
CREATE TABLE A
( Table_A_ID int CONSTRAINT PK_A_Table_A_ID PRIMARY KEY)
--ON VALUE ADD A FOREIGN KEY CONSTRAINT THAT REFERENCEs TABLE A
CREATE TABLE B
( Table_B_ID int,
[Value] int CONSTRAINT FK_B_Value_A REFERENCES A(Table_A_ID)
)
-- TEST VALID INSERT
INSERT A (Table_A_ID) VALUES (1)
INSERT B (Table_B_ID, [Value]) VALUES (1,1)
--NOT ALLOW TO INSERT A VALUE THAT DOES NOT EXIST IN A
--THIS WILL THROW A FOREIGN KEY CONSTRAINT ERROR
INSERT B (Table_B_ID, [Value]) VALUES (1,2) -- 2 DNE in table A
ROLLBACK
Note: there is no magic to 'FK_B_Value_A' or 'PK_A_Table_A_ID' it simply a naming convention and be called anything. The syntax on the foreign key and primary key lines work like this:
column-definition CONSTRAINT give-the-constraint-a-name REFERENCES table-name ( table-column )
column-definition CONSTRAINT give-the-constraint-a-name PRIMARY KEY

How to create composite primary key in SQL Server 2008

I want to create tables in SQL Server 2008, but I don't know how to create composite primary key. How can I achieve this?
create table my_table (
column_a integer not null,
column_b integer not null,
column_c varchar(50),
primary key (column_a, column_b)
);
CREATE TABLE UserGroup
(
[User_Id] INT NOT NULL,
[Group_Id] INT NOT NULL
CONSTRAINT PK_UserGroup PRIMARY KEY NONCLUSTERED ([User_Id], [Group_Id])
)
Via Enterprise Manager (SSMS)...
Right Click on the Table you wish to create the composite key on and select Design.
Highlight the columns you wish to form as a composite key
Right Click over those columns and Set Primary Key
To see the SQL you can then right click on the Table > Script Table As > Create To
I know I'm late to this party, but for an existing table, try:
ALTER table TABLE_NAME
ADD CONSTRAINT [name of your PK, e.g. PK_TableName] PRIMARY KEY CLUSTERED (column1, column2, etc.)
For MSSQL Server 2012
CREATE TABLE usrgroup(
usr_id int FOREIGN KEY REFERENCES users(id),
grp_id int FOREIGN KEY REFERENCES groups(id),
PRIMARY KEY (usr_id, grp_id)
)
UPDATE
I should add !
If you want to add foreign / primary keys altering, firstly you should create the keys with constraints or you can not make changes. Like this below:
CREATE TABLE usrgroup(
usr_id int,
grp_id int,
CONSTRAINT FK_usrgroup_usrid FOREIGN KEY (usr_id) REFERENCES users(id),
CONSTRAINT FK_usrgroup_groupid FOREIGN KEY (grp_id) REFERENCES groups(id),
CONSTRAINT PK_usrgroup PRIMARY KEY (usr_id,grp_id)
)
Actually last way is healthier and serial. You can look the FK/PK Constraint names (dbo.dbname > Keys > ..) but if you do not use a constraint, MSSQL auto-creates random FK/PK names. You will need to look at every change (alter table) you need.
I recommend that you set a standard for yourself; the constraint should be defined according to the your standard. You will not have to memorize and you will not have to think too long. In short, you work faster.
First create the database and table, manually adding the columns. In which column to be primary key. You should right click this column and set primary key and set the seed value of the primary key.
To create a composite unique key on table
ALTER TABLE [TableName] ADD UNIQUE ([Column1], [Column2], [column3]);
CREATE TABLE UserGroup
(
[User_Id] INT Foreign Key,
[Group_Id] INT foreign key,
PRIMARY KEY ([User_Id], [Group_Id])
)

How can I get around this foreign key constraint having to have a unique name?

I'm not sure why these have to be unique, but from reading the MySQL forums it appears that they do. However, I think it has something more to do with the INDEX name. I have two tables that have foreign key constraints referencing the same primary key on a third table. If it helps, I'm using MySQL workbench to design the schema.
I usually name my foreign key on each table the same name as the primary key it references. I guess this isn't possible. It will create the first table with the foreign key constraint, but when it tries to create the second table it throws an error. Here is the second table it throws the error on:
CREATE TABLE IF NOT EXISTS `joe`.`products_to_categories` (
`product_to_category_id` INT NOT NULL AUTO_INCREMENT ,
`category_id` INT NOT NULL ,
`product_id` INT NOT NULL ,
PRIMARY KEY (`product_to_category_id`) ,
INDEX `category_id` (`category_id` ASC) ,
INDEX `product_id` (`product_id` ASC) ,
CONSTRAINT `category_id`
FOREIGN KEY (`category_id` )
REFERENCES `joe`.`categories` (`category_id` )
ON DELETE CASCADE
ON UPDATE NO ACTION,
CONSTRAINT `product_id`
FOREIGN KEY (`product_id` )
REFERENCES `joe`.`products` (`product_id` )
ON DELETE CASCADE
ON UPDATE NO ACTION)
ENGINE = InnoDB;
I want the foreign key names to be the same as the primary key in both of the other tables. What should I remove here so that I can use these names. What is the best practice here.
It is not possible because you would have a conflict in the filename for the file that is used for the index IIRC. I probably would name the key < tablename >_< column_name > or something like that.
You are creating an index (constraint) by the name of product_id via:
INDEX product_id
Then you are going and creating another constraint (for the foreign key) with the same name:
CONSTRAINT product_id
What you need to do is allow the server to provide a default, unique constraint name by removing the
CONSTRAINT product_id
See this URL: http://dev.mysql.com/doc/refman/5.1/en/innodb-foreign-key-constraints.html
"If the CONSTRAINT symbol clause is given, the symbol value must be unique in the database. If the clause is not given, InnoDB creates the name automatically."
In PostgreSQL, the default for naming indexes is to append "_pkey" and "_fkey" to the name of the primary and foreign key, respectively. So your case would look like:
INDEX `product_id_fkey` (`product_id` ASC) ,
UPDATE: I just tried this and it worked. See if that's what you had in mind.
use test;
create table if not exists test.product
(
product_id int not null auto_increment,
name varchar(80) not null,
primary key(product_id)
);
create table if not exists test.category
(
category_id int not null auto_increment,
name varchar(80) not null,
primary key(category_id)
);
create table if not exists test.product_category
(
product_id int,
category_id int,
primary key(product_id, category_id),
constraint product_id_fkey
foreign key(product_id) references product(product_id)
on delete cascade
on update no action,
constraint category_id_fkey
foreign key(category_id) references category(category_id)
on delete cascade
on update no action
);
insert into test.product(name) values('teddy bear');
insert into test.category(name) values('toy');
insert into test.product_category
select p.product_id, c.category_id from product as p, category as c
where p.name = 'teddy bear' and c.name = 'toy';