Primary Key in DB in SQL - mysql

guys i was asked to make the design for product table like this
product_code (PK)----------varchar2(5)
product_name---------------varchar2(15)
product_type---------------varchar2(1)
but i want to make an ID auto increment column to be primary key as well to be accessed within any CRUD operations .. can i do this with the existence of primary key product_code ?... or the ID column is useless here ??

Make the product_id the primary key as an auto_increment column.
You can then define product_code as unique and not null.
Foreign key relationships should use the product_id column.

If you've been given requirements that state your primary key should be a varchar2(5) called product_code. I would recommend following the requirements, I see no practical reason to object.
Do you know how many records will exist in this table, do you have reason to believe the requirements provided will introduce an issue? If so document your concerns and ask for clarification, but you appear to be a contractor and I would defer to the customer.

Only the primary key can be auto-generated in MySQL.
Create the table with a new ID column that is auto-generated and make your existing PRODUCT_CODE column unique, as in:
create table product (
id int primary key not null auto_increment,
product_code varchar(5) not null,
product_name varchar(15) not null,
product_type varchar(1),
constraint uq_code unique (product_code)
);

Related

Unable to establish multiple foreign keys on mysql, specifically tested on mariaDB and w3schools online mysql

I was about to create two tables (1st table: fooditem_tbl & 2nd table: orderitem_tbl). I was planning to create 2 foreign keys (ITEM_NAME,UNIT_PRICE) on the 2nd table. I wasn't able to run the query of the 2nd table(orderitem_tbl), due to an error which is near at "INDEX". I kept looking at my query, and I still don't know what's the cause of the error.
My first table , this one works
CREATE TABLE FOODITEM_TBL
(ITEM_ID INT AUTO_INCREMENT,
ITEM_NAME VARCHAR(50) UNIQUE,
UNIT_PRICE DOUBLE UNSIGNED,
ITEM_QUANTITY INT UNSIGNED,
IN_STOCK BOOLEAN,
PRIMARY KEY (ITEM_ID, ITEM_NAME, UNIT_PRICE));
The 2nd table, which is below fails to create
CREATE TABLE ORDERITEM_TBL(
ORDER_ID INT AUTO_INCREMENT,
ITEM_NAME VARCHAR(50) UNIQUE,
UNIT_PRICE DOUBLE UNSIGNED,
ITEM_QUANTITY INT UNSIGNED,
CUSTOMER_NAME VARCHAR(50),
ADDRESS VARCHAR(50),
CONTACT_NUMBER VARCHAR(50),
PRIMARY KEY (ORDER_ID),
INDEX (ITEM_NAME,UNIT_PRICE),
FOREIGN KEY (ITEM_NAME,UNIT_PRICE) REFERENCES
FOODITEM_TBL(ITEM_NAME,UNIT_PRICE)
) ENGINE = InnoDB;
P.S Please help
Q: What is causing the error? How can I fix it?
For InnoDB, there must be an index on the target table, on the target column(s). Datatypes of the referencing foreign key column(s) must match the datatypes of the target column(s).
Before creating the foreign key constraint, make sure a suitable index exists on the target table, e.g.
CREATE UNIQUE INDEX `FOODITEM_TBL_UX3` ON `FOODITEM_TBL` (`ITEM_NAME`, `UNIT_PRICE`) ;
Given that ITEM_NAME is unique in the target table, we know that the combination of ITEM_NAME and UNIT_PRICE will also be unique. I'm not sure why we wouldn't just define a foreign key constraint on just ITEM_NAME, but that doesn't really address the question that was asked.
Personally, I would avoid floating point datatypes (e.g. DOUBLE) for columns involved in foreign key constraints.

Auto increment with composite primary key

I am not entirely sure what to search so I apologize if this is in fact a duplicate.
I have a table (or at least would like to) as follows:
ID
Company Name
SomeOtherInfo
The primary key would be ID and Company name (composite primary key). What I would like is so that the ID auto increments on each company.
Ex:
1-google
2-google
3-google
1-yahoo
4-google
2-yahoo
This way they are always unique, but each one increments for each company individually.
Is this possible from simple SQL create commands, would rather not have 2 tables and join them using a secondary ID.
Let me know, thanks.
If I follow the question. Create a single table with an identity on the ID column. Then create a unique index on the Company Name.
MySql Version
CREATE TABLE Company (
CompanyID int NOT NULL AUTO_INCREMENT,
CompanyName varchar(255) NOT NULL,
OtherData varchar(255),
PRIMARY KEY (CompanyID)
);
CREATE UNIQUE INDEX CompanyUniqueComposite
ON Company (CompanyID , CompanyName );

How to setup must exist in database

i need help. As you can see in my tables i have to setup primary and forign keys and i need help on this cascade updates.
For example i have a task like this:
If the value for Category_Name is changed in CATEGORY, the change should be reflected here as well.
But this doesent work :
If an OrderID in ORDERED is changed, then the change should be reflected here as well.
If an ORDERED is deleted, then any LINE_ITEM(s)associated with that order should also be deleted.
If the Item_Number of an ITEM is changed, then the change should be reflected here as well.
I dont know how to setup this correctly and i need help to better understand this.
CREATE DATABASE TEST1;
USE TEST1;
CREATE TABLE CATEGORY (
CategoryName VARCHAR(35) NOT NULL,
ShippingPerPound CHAR(4),
OffersAlowed ENUM('y', 'n'),
CONSTRAINT CATEGORY_PK PRIMARY KEY (CategoryName)
) ENGINE=INNODB;
CREATE TABLE ITEM(
ItemNumber INT UNSIGNED AUTO_INCREMENT,
Item_Name VARCHAR(35) NOT NULL,
Description VARCHAR(255),
Model VARCHAR(50) NOT NULL,
Price CHAR(8) NOT NULL,
parent_ItemNumber INT,
CategoryName VARCHAR(35),
CONSTRAINT ITEM_PK PRIMARY KEY (ItemNumber),
CONSTRAINT ITEM_CategoryName_fk FOREIGN KEY (CategoryName) REFERENCES
CATEGORY(CategoryName) ON UPDATE CASCADE)
ENGINE=INNODB;
CREATE table LINE_ITEM(
Quantitiy INT(255),
Shipping_amounth DECIMAL(4,2),
ItemNumber INT UNSIGNED,
OrderID INT UNSIGNED,
CONSTRAINT LINE_ITEM_PK PRIMARY KEY(ItemNumber),
CONSTRAINT LINE_ITEM_PK PRIMARY KEY(OrderID),
CONSTRAINT LINE_ITEM_OrderID FOREIGN KEY (OrderID) REFERENCES ORDERED(OrderID) ON UPDATE CASCADE),
CONSTRAINT LINE_ITEM_OrderID FOREIGN KEY (OrderID) REFERENCES ORDERED(OrderID) ON UPDATE DELETE),
CONSTRAINT LINE_ITEM_ItemNumber_fk FOREIGN KEY (ItemNumber) REFERENCES ITEM(ItemNumber) ON UPDATE CASCADE)
ENGINE=INNODB;
CREATE TABLE OFFER(
OfferCode varchar(15),
Discount_Amt varchar(35) NOT NULL,
MinAmount DECIMAL(2,2) NOT NULL,
ExpirationDate DATE NOT NULL,
CONSTRAINT OFFER_OfferCode PRIMARY KEY(OfferCode)
)
ENGINE=INNODB;
CREATE TABLE ORDERED(
OrderID INT UNSIGNED AUTO_INCREMENT,
total_cost DECIMAL(8,2),
CONSTRAINT ORDERED_PK PRIMARY KEY (OrderID),
CONSTRAINT OFFER_OfferCode FOREIGN KEY (OrderID) REFERENCES OFFER(OfferCode) ON UPDATE CASCADE),
CONSTRAINT CUSTOMER_CustomerID FOREIGN KEY (CustomerID) REFERENCES CUSTOMER(CustomerID) ON UPDATE CASCADE)
)
ENGINE=INNODB;
If the value for Category_Name is changed in CATEGORY, the change should be reflected [in the tables which reference Category] as well.
You have an XY Problem. You've already chosen a solution to your problem (using cascading updates) and asked about that. It's not a good solution, it just papers over the real. Instead, you should ask about the real problem.
The real problem is you have duplicate data, CategoryName is stored in two places. The question is how one deals with that? The answer is to redesign the schema to eliminate the duplication.
Looking at the Category table reveals the real real problem, CategoryName is the primary key, so it will be referenced in other tables. But if CategoryName can change it's a poor choice for a primary key. Instead, use a simple auto incrementing integer as the primary key and the problem goes away.
create table Category (
ID integer auto_increment primary key,
Name varchar(255) not null,
ShippingPerPound CHAR(4),
OffersAlowed ENUM('y', 'n'),
);
Now categories can be referenced using CategoryID integer references category(id). Category names can change as much as they like. Any query needing to know the category name will have to do a join Category on Category.id = CategoryID; simple joins like that are cheap.
If the Item_Number of an ITEM is changed, then the change should be reflected [in the tables which reference Item] as well.
Same problem: if the primary key can change, it's not a good primary key. Since Item_Number is auto incremented it should never change, so you might be worrying about a problem that doesn't exist.
If Item_Number can change, then you need two columns. One for the immutable primary key, just call it id, and one for the mutable Item_Number. They can be the same thing for most columns, that's fine, it just adds 4 bytes to each column.
Note that I increased the name constraint to 255. It's a bad practice to put business rules, like size limits on names, into the database schema. The database should not be limiting design choices, and there's no technical reason to limit it: 30 characters in a varchar(255) takes up as much space as 30 characters in varchar(30).
I'd also question why ShippingPerPound is a char(4). It seems it should be a number, probably a numeric(9,2) for money. numeric will store exact values and does not suffer from floating point error, it's a good choice for money.
Finally, I'd caution against using an unsigned integer as a primary key. Yes, it doubles your keyspace, but I can guarantee people referencing that key will forget and use a plain, signed integer. If you hit 2 billion rows it's likely you're growing so rapidly that you'll blow through the next 2 billion much faster than the first, so it isn't worth it. If you're really concerned about keyspace, use a bigint or UUID. But this isn't something you need to worry about now, tables can be altered later if it becomes an issue. But it's unlikely to be an issue for Items as it's unlikely you'll have 2 billion items. Keyspace exhaustion is something that happens to tables that are logging things, or tracking sales, things which grow exponentially as you get more users; not manually entered warehouse data.
Old database guides sometimes encourage bad practices like trying to use data as a primary key, or putting unnecessary limits on storage sizes. That might have made sense when disk and CPU was extremely limited, or when column sizes were fixed, but it makes little sense now. An auto incremented integer primary key is a good default choice.

Creating a parent and child table, does child need its own primary id column?

When we create parent-child tables, does the child table need its own primary key, or should the foreign key of the parent be used as the primary key?
Example:
I have a table that stores users, which is defined like:
CREATE TABLE users (
'id' bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
'username' varchar(32),
PRIMARY KEY ('id'))
I want to make a second table that stores some more information about a user, like their favorite animals. Should that table have its own 'id' column as well as a separate foreign key for the linked user?:
CREATE TABLE users_extra_info (
'id' bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
'fk_user_id' bigint(20) UNSIGNED NOT NULL,
'fav_mammal' varchar(32),
'fav_reptile' varchar(32),
...
PRIMARY KEY ('id'),
KEY 'fk_user_id' ('fk_user_id'))
or do you usually just drop the 'id' column since the foreign key has to be unique?:
CREATE TABLE users_extra_info (
'fk_user_id' bigint(20) UNSIGNED NOT NULL,
'fav_mammal' varchar(32),
'fav_reptile' varchar(32),
...
PRIMARY KEY ('fk_user_id'))
Thanks
As a matter of principle, not related to other tables, each table should have a PRIMARY KEY in order for you to be able to distinguish one row from another. While it's not always necessary to absolutely identify individual rows that is often a requirement.
In the event of a true one-to-one relationship (or a one-to-zero-or-one relationship, which also occurs), because the foreign key is necessarily unique it can also be used as the primary key of the subsidiary table. There is absolutely no reason at all to introduce a second unique column in that case.
However, one-to-one and one-to-zero-or-one relationships are less common than one-to-many relationships. In that more common case, you cannot use only the foreign key columns as the primary key since they are not unique in the child table. In this case you can choose either to introduce an additional integer key or created a composite primary key using the foreign key column(s) and one or more other columns that, together, are guaranteed to be unique.
You have to understand the normalization rules.
Here's the link http://www.studytonight.com/dbms/database-normalization.php.
If you want to put the additional columns to another table, I don't see a reason to have an extra id column. Below is what I would do. Another benefit from this approach is that you ensure 1 to 1 relationship. If you had a separate ID column, you would be able to have many rows in users_extra_info linked to one row in users.
CREATE TABLE users (
id int,
username varchar(32),
PRIMARY KEY (id));
CREATE TABLE users_extra_info (
fk_user_id int,
fav_mammal varchar(32),
fav_reptile varchar(32),
PRIMARY KEY (fk_user_id),
foreign key (fk_user_id) references users(id));
You can also think about cascading deletion.

many to many table - 1 seperate field primary key or 2 existed fileds primary key (Example inside)

I have 2 tables with many to many relation:
student
(
id int(11) NOT NULL,
name varchar(255),
primary key(id)
);
teacher
(
id int(11) NOT NULL,
name varchar(255),
primary key(id)
);
and I should do 3 table - student_has_teacher
option add id separate field primary key
student_has_teacher
(
id int(11) NOT NULL,
teacher_id int(11),
student_id int(11)
primary key(id)
);
option make 2 fields primary key
student_has_teacher
(
teacher_id int(11),
student_id int(11),
primary key(teacher_id,student_id),
foreign key(teacher_id) references teacher(id),
foreign key(student_id) references student(id)
);
What is better option and why?
Thanks
make 2 fields primary key
Because they fulfill the definition of what a primary key is. They allow to unambiguously indicate the row.
The two options are not equivalent. In option 1 there can be multiple pairings of each teacher and student. In option 2 only 1 row is permitted for each combination of teacher and student.
There is another difference as well. In 1 the student and teacher are nullable. In 2 they aren't.
On the information given I don't see why a teacher would need to be paired with the same student more than once. So as a guess I'd say that 2 was more appropriate, but it all depends on the business requirements and you haven't really given much information to say either way.
That depends. If you'll need to relate something to a row in student_has_teacher (weird table-name imo, I'd suggest student_teacher) an id field would be nice. If you're not, the two fields will do fine to.