I have two tables for one is category and another one is sub-category. that two table is assigned to FK for many table. In some situation we will move one record of sub-category to main category. so this time occur constraints error because that key associated with other table. so i would not create this schema.
so now i plan to create category and sub-category in same table and create relationship table to make relationship between them.
category table:
id(PK,AUTO Increment),
item===>((1,phone),(2.computer),(3,ios),(4,android),(5,software),(6,hardware)).
relationship table:
id,cate_id(FK),
parentid(refer from category table)===>((1,1,0),(2,2,0),(3,3,1),
(4,4,1),(5,5,2),(5,5,3)).
in my side wouldnot go hierarchy level more than three.
if we easily move to subcategory to main category ex:(4,4,1) to (4,4,0) without affect any other table. is this good procedure?
if we will maintain millions record, will we face any other problem in future?
have any another idea means let me know?
There might be a problem if you have multiple levels in the tree, and want to find all the subcategories of any category. This would require either multiple queries, or a recursive one.
You could instead look into the "Nested Sets" data-structure. It supports effective querying of any sub-tree. It does have a costly update, but updates probably won't happen very often. If need be, you could batch the updates and run them over night.
create table Category (
Id int not null primary key auto_increment,
LeftExtent int not null,
RightExtent int not null,
Name varchar(100) not null
);
create table PendingCategoryUpdate (
Id int not null primary key auto_increment,
ParentCategoryId int null references Category ( Id ),
ParentPendingId int null references PendingCategoryUpdate ( Id ),
Name varchar(100) not null
);
If you have a small number of categories, a normal parent reference should be enough. You could even read the categories into memory for processing.
create table Category (
Id int not null primary key auto_increment,
ParentId int null references Category ( Id ),
Name varchar(100) not null
);
-- Just an example
create table Record (
Id int not null primary key auto_increment,
CategoryId int not null references Category ( Id )
);
select *
from Record
where CategoryId in (1, 2, 3); -- All the categories in the chosen sub-tree
How about creating one table as following:
categories(
id int not null auto_increment primary key,
name char(10),
parent_id int not null default 0)
Where parent_id is a FK to the id, which is the PK of the table.
When parent_id is 0, then this category is a main one. When it is > 0, this is a sub category of this parent.
To find the parent of a category, you will do self-join.
Related
I have three tables: property, person, and company. One property can only belong to either a person or a company. A person or a company can have more than one property.
My current database design is to include two foreign keys - person_id and company_id in property table, always with one of them null and the other not null. I'm just wondering is there any better way to design the database in this scenario?
CREATE TABLE person(
person_id int NOT NULL PRIMARY KEY,
name varchar(255)
);
CREATE TABLE company(
company_id int NOT NULL PRIMARY KEY,
name varchar(255)
);
CREATE TABLE property(
property_id int NOT NULL PRIMARY KEY,
name varchar(255),
person_id REFERENCES person,
company_id REFERENCES company
);
Create additional table CHECK constraint:
CREATE TABLE property(
property_id int NOT NULL PRIMARY KEY,
name varchar(255),
person_id REFERENCES person,
company_id REFERENCES company,
CHECK (person_id IS NULL + company_id IS NULL = 1)
);
This will forbid wrong values (both NULL or both NOT NULL).
PS. Two references presence is legal and safe itself.
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;
Question:
Is there a way to make the foreign ID point to something more generic than one specific table?
Details:
Often I run into the situation where I have several tables which have nothing to do with each other, but still need a common table (in below examples engine is innodb)
CREATE TABLE IF NOT EXISTS movies
(
id INT NOT NULL auto_increment,
name VARCHAR(100) NOT NULL ,
PRIMARY KEY(id)
);
CREATE TABLE IF NOT EXISTS books
(
id INT NOT NULL auto_increment,
name VARCHAR(100) NOT NULL ,
PRIMARY KEY(id)
);
CREATE TABLE IF NOT EXISTS songs
(
id INT NOT NULL auto_increment,
name VARCHAR(100) NOT NULL ,
PRIMARY KEY(id)
);
CREATE TABLE IF NOT EXISTS news_papers
(
id INT NOT NULL auto_increment,
name VARCHAR(100) NOT NULL ,
PRIMARY KEY(id)
);
CREATE TABLE IF NOT EXISTS scrolls
(
id INT NOT NULL auto_increment,
name VARCHAR(100) NOT NULL ,
PRIMARY KEY(id)
);
CREATE TABLE IF NOT EXISTS sumarian_wheat_tablets
(
id INT NOT NULL auto_increment,
name VARCHAR(100) NOT NULL ,
PRIMARY KEY(id)
);
Now I want to keep a record of every time each is viewed like so
CREATE TABLE IF NOT EXISTS movie_history
(
id INT NOT NULL auto_increment,
foreign_id INT NOT NULL ,
view_date TIMESTAMP DEFAULT now(),
FOREIGN KEY (foreign_id) REFERENCES movies ( id ),
PRIMARY KEY(id)
);
CREATE TABLE IF NOT EXISTS book_history
(
id INT NOT NULL auto_increment,
foreign_id INT NOT NULL ,
view_date TIMESTAMP DEFAULT now(),
FOREIGN KEY (foreign_id) REFERENCES books ( id ),
PRIMARY KEY(id)
);
CREATE TABLE IF NOT EXISTS song_history
(
id INT NOT NULL auto_increment,
foreign_id INT NOT NULL ,
view_date TIMESTAMP DEFAULT now(),
FOREIGN KEY (foreign_id) REFERENCES songs ( id ),
PRIMARY KEY(id)
);
CREATE TABLE IF NOT EXISTS news_paper_history
(
id INT NOT NULL auto_increment,
foreign_id INT NOT NULL ,
view_date TIMESTAMP DEFAULT now(),
FOREIGN KEY (foreign_id) REFERENCES news_papers ( id ),
PRIMARY KEY(id)
);
CREATE TABLE IF NOT EXISTS scroll_history
(
id INT NOT NULL auto_increment,
foreign_id INT NOT NULL ,
view_date TIMESTAMP DEFAULT now(),
FOREIGN KEY (foreign_id) REFERENCES scrolls ( id ),
PRIMARY KEY(id)
);
CREATE TABLE IF NOT EXISTS sumarian_wheat_tablet_history
(
id INT NOT NULL auto_increment,
foreign_id INT NOT NULL ,
view_date TIMESTAMP DEFAULT now(),
FOREIGN KEY (foreign_id) REFERENCES sumarian_wheat_tablets ( id ),
PRIMARY KEY(id)
);
Is there a more correct way to handle such situations without making n new tables? I realize that I can make one history table and copy it over with CREATE TABLE...LIKE... but that still requires making n new tables, plus I have to go in and ALTER the foreign_id.
My first thought is just dump the fk reference and have one history table:
CREATE TABLE history(
base_table VARCHAR,
base_table_id INT,
view_date TIMESTAMP DEFAULT now()
);
But I assume you want the fk to maintain the integrity (question: is this really necessary, or can this be worked around?). I guess you could accomplish this by creating a table of "pks in use". For example:
create a table "keys" with columns id (autoincrement) and base_table_name
create a table "movies", where id is both pk and also a fk to "keys.id" (but not an autoincrement column)
add a "before insert" trigger to "movies" which inserts a record into "keys" returning the generated id to be used as the id for the "movie" record
create a history table with a fk to "keys"
create a "delete" trigger on "movies" which also removes the record from "keys" if you want the integrity maintained, or cascading deletes, etc
So the generated "id" is shared across many tables. There is a school of thought that suggests using a primary key unique across all relations within the database (an "enterprise key"), so it is not unprecedented. Instead of using sequences or autogenerated columns, sometimes a GUID or UUID is used.
This replaces extra history tables with triggers on each base table, which might not be a great thing, depending on your environment. I haven't done this myself, just throwing some thoughts out there, so take it for what its worth.
This depends on the record that you're keeping. If you just want to know hits, add one field to each table that is incremented each time your 'hit' criteria is met (ie, there is a read from a webpage). If you want to hold more information:
CREATE TABLE IF NOT EXISTS view_history
(
id INT NOT NULL,
table VARCHAR NOT NULL,
//other relevant stats to a given view, such as ip and so on.
)
The id and table form a composite key as to what table it refers to.
I don't think there is a way to specify more than one table on a single foreign key.
If you define a single history table, you cannot enforce referential integrity using a single foreign key. You could enforce it programmaticaly as explained here
This describes how to do it for other storage engines that do not support FKs, but could be used as a guide to implement what you need. It suggests creating triggers that will enforce same validations a foreign key would.
Other approach:
CREATE TABLE IF NOT EXISTS history
(
id INT NOT NULL auto_increment,
movie_id INT,
book_id INT,
song_id INT,
news_paper_id INT,
view_date TIMESTAMP DEFAULT now(),
FOREIGN KEY (movie_id) REFERENCES movie ( id ),
FOREIGN KEY (book_id) REFERENCES book ( id ),
FOREIGN KEY (song_id) REFERENCES song ( id ),
FOREIGN KEY (news_paper_id) REFERENCES news_paper ( id ),
PRIMARY KEY(id)
);
I have a table that holds a users favorite categories and I was wondering if My MYSQL tables structure is built correctly to hold the MySQL data provided correctly?
MySQL data.
userID catID
4 21
4 4
4 67
3 34
3 4
MySQL table .
CREATE TABLE ab (
userID INT UNSIGNED NOT NULL,
catID INT UNSIGNED NOT NULL,
PRIMARY KEY (userID),
UNIQUE KEY (catID)
);
Neither userID nor catID are by themselves unique. What you want is
CREATE TABLE ab (
userID INT UNSIGNED NOT NULL,
catID INT UNSIGNED NOT NULL,
PRIMARY KEY (userID, catID)
);
so that only the specific combinations of userID and catID taken together are required to be unique.
No it is not correct: userId is not unique, nor is catID, the couple(userID, cat ID) is. Either you add a third column to act as primary key, and you declare the couple (userId, catID) as unique, or you can even declare this very couple as primary key.
No, catID isn't unique because there are two fours.
I don't think you want catID to be unique, as you have it up there multiple times.
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)
)