two columns primary key, auto-increment and foreign key - mysql

The following query was successful but when I enter null values into order id and different values(those which do not exist in the column) for item id, the order id is still getting incremented. How to retain the same order id? Is there a problem with the way the foreign key has been stated?
CREATE TABLE orders(
orderid int not null auto_increment,
itemid int not null,
quantity int not null,
tot_price int not null,
cid int not null,
code varchar(10),
order_time time,
order_date date ,
constraint order_pk primary key (orderid, itemid),
foreign key (itemid) references items(itemid),
foreign key (cid) references customer(cid),
foreign key (code) references coupon(code)
);

The problem stems from trying to do a one-to-many (order to items) relationship in a single table. This will end badly. You need two. One for the order, one for the items in the order. For good or bad, this is how relational databases do lists.
CREATE TABLE orders (
orderid int not null primary key auto_increment,
cid int not null references customer(cid),
code varchar(10) references coupon(code),
when_ordered datetime,
INDEX(when_ordered)
);
CREATE TABLE items_in_an_order (
orderid int not null references orders(id),
itemid int not null references items(id),
quantity int not null,
price_paid int not null
);
quantity moves to items_in_an_order. I changed total_price to the more descriptive price_paid which is likely more descriptive of what you want to be storing. This will let you produce receipts.
order_date and order_time were unnecessarily split into two columns. This makes comparison and sorting awkward. Putting them together into one DATETIME column and indexing it will let you do sorting by date/time and check if an order is inside a date/time range.
To get all the items in an order, do a join.
SELECT items.itemid
FROM items
JOIN items_in_an_order io ON io.itemid = items.id
WHERE io.orderid = ?
To find all the orders an item is in, also do a join.
SELECT orders.id
FROM orders
JOIN items_in_an_order io ON io.orderid = orders.id
WHERE io.itemid = ?

Related

Foreign key and referential integrity

I've been facing an issue while I'm using MySQL, here is the issue, I've been created two tables named Persons and Orders, the Orders table references the Persons table as the following query shown, I inserted values in the Persons table, however, I when I check the Orders table, I spot that the value of PersonID column of the Persons table doesn't include in the PersonID column of the Orders table
CREATE TABLE Persons
(
PersonID INT NOT NULL UNIQUE PRIMARY KEY,
LastName VARCHAR(60) NOT NULL,
FirstName VARCHAR(60) NOT NULL,
AGE INT NOT NULL,
);
CREATE TABLE Orders
(
OrderID int NOT NULL,
OrderNumber int NOT NULL,
PersonID int,
PRIMARY KEY (OrderID),
FOREIGN KEY (PersonID) REFERENCES Persons(PersonID)
);
In foreign key relationship it's possible to have a value in master table but not in the foreign key column. But it's not possible to have a value in foreign key column of a detail table and not having it in master table.
If a PersonId is in the Persons table but not in Orders table then foreign key constraint won't raise any concern. But it will raise an error if you try to insert a PersonId into Orders table which is not available in PersonId column of Persons table.
Hope above discussions will help you to get your answer. Otherwise please share some sample data to clarify more.

Best way to relate foreign key to parent

I don't dabble much in SQL design at all, so this might be a trivial question.
I have a players table:
CREATE TABLE players(
p_id INT NOT NULL PRIMARY KEY,
p_name VARCHAR(150) NOT NULL
)
I have a results table:
CREATE TABLE results(
f_id INT NOT NULL PRIMARY KEY,
f_datetime DATETIME NOT NULL,
p1_id INT NULL,
p2_id INT NULL,
FOREIGN KEY (p1_id) REFERENCES players(p_id) ON DELETE SET NULL ON UPDATE SET NULL,
FOREIGN KEY (p2_id) REFERENCES players(p_id) ON DELETE SET NULL ON UPDATE SET NULL
)
When I add an INSERT into the results table, I am adding the p1_id and p2_id. For this to work, I need to already have these id's defined in the players table, with the accompanying string name for this id. Programmatically, what should I do with my data before adding to the results table?
Check if p_id exists (from my p1_id and p2_id values), if not, INSERT them with the accompanying string.
Add my data into the results table as a normal insert
Or is there a more conventional way to do these things? Maybe some SQL quirk i'm not aware of?

Issue in mysql table creation

I need to create a table called benificiaries where I have three columns
customerid
accountno
bank
The condition should be one customerid can have only one unique accountno. But another customerid can have the same accountno and same unique (only once). So I cant give primary key to accountno. Even for customerid I can't give primary key, since one customerid can have multiple records with unique accountno.
How can we create table in this case? Any ideas?
You can use multiple-column unique index.
CREATE TABLE YOUR_TABLE (
id INT NOT NULL AUTO_INCREMENT,
customerid INT NOT NULL,
accountno INT NOT NULL,
bank INT NOT NULL,
PRIMARY KEY (id),
UNIQUE INDEX name (customerid,accountno)
);
Documentation here.
https://dev.mysql.com/doc/refman/5.7/en/multiple-column-indexes.html
If one customerid can have only 1 unique account number then how can you expect duplicates in terms of customer id in that table?
You can simply set a primary key to another column and make the customerid unique. I think this is what you want to have. Now every customerid is unique, but many costomerids can have the same accountno.
CREATE TABLE benificiaries(
id INT PRIMARY KEY,
customerid INT NOT NULL UNIQUE,
accountno INT NOT NULL,
bank INT NOT NULL
);
database can't manage all the business constraints within the data model. For the case, you might address elementary constraints with indexes (multiple column index for customerid, accountno and simple column index for accountno to perform search on the other way), add an auto-increment id and deal the business constraints in your code.
Just set your customer_id as a primary key then regarding the concept that a only two customer_id can have same account number once, will depend on the process of your App or System.
CREATE TABLE `tmpr_map`.`tbl_example`
(`customer_id` INT(11) NOT NULL AUTO_INCREMENT,
`account_number` VARCHAR NOT NULL , `bank_amount` DECIMAL(11,2) NOT NULL ,
PRIMARY KEY (`customer_id`)) ENGINE = InnoDB;

Toxi mysql performance, tagging. Help understanding

I am using the Toxi scheme for tagging items on my website. Being quite new to mysql let alone tagging, I'm just doing a sanity check. Here is my table initialization script.
CREATE TABLE IF NOT EXISTS Items (
item_id INT UNSIGNED NOT NULL AUTO_INCREMENT ,
item_name VARCHAR(45) NULL ,
media_type VARCHAR(20) NULL ,
file VARCHAR(45) NULL ,
description VARCHAR(500) NULL ,
PRIMARY KEY (item_id)
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS Tags (
tag_id INT UNSIGNED NOT NULL AUTO_INCREMENT ,
tag_text VARCHAR(25) NOT NULL ,
PRIMARY KEY (tag_id) ,
UNIQUE INDEX (tag_text)
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS Item2Tag (
item_id INT UNSIGNED NOT NULL ,
tag_id INT UNSIGNED NOT NULL ,
PRIMARY KEY (item_id, tag_id) ,
INDEX (tag_id) ,
FOREIGN KEY fk_Item (item_id) REFERENCES Items (item_id) ,
FOREIGN KEY fk_Tag (tag_id) REFERENCES Tags (tag_id)
) ENGINE=InnoDB;
http://forge.mysql.com/wiki/TagSchema
Question 1
Is my understanding correct that there is an entry in the "Item2Tag" table for every "item_id" to "tag_id"? It just seems like that is going to be a huge table when I have ~3000 items and each item could have ~5 tags. Is that not a concern/not really a big table?
Question 2
Could someone help me understand importance of having Foreign Keys/References? Why do I need those and what do they do?
Question 1: Yes, that's correct.
Question 2: You don't really need them for Toxi schema as far as I know. But they help you avoid having entries in the reference table while not in the item table. It's more of a constrain to prevent headaches than a need. ie. You delete item number x, the entry associated to item number x also gets deleted.

MySQL Categories and Subcategories Table Structure

I am having a little bit of a problem with setting up a mysql table that will hold a list of categories and subcategories. I am not to sure how to setup the table. Does it need to be 2 separate tables? 1 for the main categories and 1 for the subcategories or can it be all in 1 table? Would something like this work?
Create Table categories (
category_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
sub_id INT UNSIGNED NOT NULL,
name VARCHAR(100) NOT NULL,
PRIMARY KEY (category_id)
)
CREATE TABLE items (
item_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
description VARCHAR(100) NOT NULL,
PRIMARY KEY (item_id),
FOREIGN KEY (category_id) REFERENCES categories (category_id),
FOREIGN KEY (sub_id) REFERENCES categories (sub_id)
)
Will this work or is this completely wrong? Thanks in advance for the help!
If you are 100% sure that you'll only have two levels of categories (main and sub), you can do a few different things. None of them are your proposed solution:
CREATE TABLE categories (
id int not null primary key,
main varchar(64)
sub varchar(64)
);
CREATE TABLE objects (
id int not null primary key,
category_id int,
name varchar(64),
FOREIGN KEY (category_id) REFERENCES categories (id)
);
Want all vehicles?
SELECT *
FROM objects AS o
INNER JOIN categories AS c ON o.category_id = c.id
WHERE c.main = 'vehicles';
Want all roflcopters?
SELECT *
FROM objects AS o
INNER JOIN categories AS c ON o.category_id = c.id
WHERE c.main = 'vehicles' and c.sub='Roflcopters';
If you want something in the "vehicle" category, but not in any of the subcategories of verhicles, just have a category record where main='vehicles' with sub NULL.
Of course, this is not particularly flexible. You're stuck with just two levels of categorization, and there's not a lot of business logic embedded in your category model. But it might be sufficient for your needs.
Two other good, proven, models are the adjacency list model, and the nested set model, both of which are described, with lots of nice example mysql code, over here
It depends.
Are categories and subcategories really two different things? This means categories have no parent, while subcategories are always in a parent category and have no further subs of themselves. Then two tables is ok.
If it's like a tree though, where there are just categories, which can both be children and have children, you should use one table (Google "nested set").
(Or maybe you don't mean category/subcategory but primary category/secondary category, where the secondary category is not fixed to a certain primary category. Electronics + Cycling instead of Cycling->Speedometers. Then you could use one table if it could also be Cycling + Electronics)
It is obviously work. But you may use separate tables.
create table categories
(
categoryId int not null,
categoryName varchar(20) not null,
primary key(categoryId)
);
create table subcategories
(
subcategoryId int not null,
subcategoryName varchar(20) not null,
parentId int not null,
primary key(subcategoryId),
foreign key(categoryId) references categories(categoryId)
);
create tables items
(
item_id int unsigned not null auto_increment,
name varchar(255) not null,
description varchar(100) not null,
primary key(item_id),
foreign key(categoryId) references categories(categoryId),
foreign key(subcategoryId) references subcategories(subcategoryId)
)