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.
Related
Say I have a bunch of people with multiple phone numbers. In a MySQL database I'd have a Person table and a Phone Number table with a many to one relationship.
Now I want to make one of those numbers the primary phone number and only allow one primary number per person. How would I model this?
Try the schema below. It will prevent entries that try to assign more than one primary number per person.
CREATE TABLE person (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`first_name` VARCHAR(50) NOT NULL,
`last_name` VARCHAR(50) NOT NULL,
PRIMARY KEY(`id`)
);
CREATE TABLE phonenumber (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`phonenumber` VARCHAR(10) NOT NULL,
`person_id` INT(11) UNSIGNED NOT NULL,
`is_primary` ENUM('1'),
PRIMARY KEY(`id`),
UNIQUE KEY idx_person_primary (`person_id`, `is_primary`),
UNIQUE KEY idx_person_phone (`phonenumber`, `person_id`)
);
INSERT INTO person (first_name, last_name) VALUES ('Michael', 'Jones');
INSERT INTO phonenumber (phonenumber, person_id, is_primary) VALUES ('9876543210', 1, 1);
INSERT INTO phonenumber (phonenumber, person_id, is_primary) VALUES ('1234567890', 1, NULL);
INSERT INTO phonenumber (phonenumber, person_id, is_primary) VALUES ('1234567891', 1, NULL);
This will allow the DB to police a single primary phone number for each person. For example if you try to assign another primary phone number to Michael Jones:
INSERT INTO phonenumber (phonenumber, person_id, is_primary) VALUES ('0123211234', 1, 1);
You will get a "Duplicate entry '1-1' for key 'idx_person_primary'" error.
http://sqlfiddle.com/#!9/dbb3c7/1
The "exactly one primary phone number" is tricky. One way uses triggers. Other databases offer expression-based indexes. This is tricky because:
The constraint spans two tables.
Guaranteeing exact "one-ness" across updates is tricky.
But one method in MySQL that comes close and doesn't use triggers:
create table persons (
personId int auto_increment primary key,
primary_personPhonesId int,
. . .
);
create table personPhones (
personPhonesId int auto_increment primary key,
personId int,
. . .
foreign key (personId) references persons (personId),
unique (personId, personPhonesId) -- seems redundant but needed
);
alter table persons
add foreign key (personId, primary_personPhonesId) on personPhones(personId, personPhonesId);
It is tempting to declare primary_personPhonesId as not null. However, that makes it difficult to insert rows into the two tables.
An alternative method uses computed columns:
create table persons (
personId int auto_increment primary key,
. . .
);
create table personPhones (
personPhonesId int auto_increment primary key,
personId int,
isPrimary boolean,
. . .
foreign key (personId) references persons (personId),
primaryId as (case when isPrimary then personPhonesId end),
unique(primaryId)
);
Similar to the previous solution, this does not guarantee that isPrimary is always set.
You can try the below mentioned design:
Person (Id (PK),name,....)
TelephoneNumber (Id(PK), telNo, PersonId(FK))
PrimaryTelNo (PersonId(FK), TelId(FK))
You can create a table showing mapping of TelId and PersonId and declare the combination of TelId and PersonId as composite primary key
The simplest way is to make the 'first' one primary, but this becomes tricky when you want to change which one is primary. In that case, I believe you can do this...
CREATE TABLE my_table
(person_id INT NOT NULL
,phone VARCHAR(12) not null
,is_primary enum('1') null
,primary key(person_id,phone)
, unique (person_id,is_primary)
);
INSERT INTO my_table VALUES
(1,'123',1),
(1,'234',null),
(1,'345',null),
(2,'456',null),
(2,'567',1),
(2,'678',null);
So, the enum allows values of 1 and null, but while there can be several nulls, there can only be one '1' per person. However, this solution doesn't preclude the possibility that none of the numbers are primary!
You should create a third table person_primary_number with only two fields:
person_id
phone_number_id
In this table you should insert the ids of the person and his primary number. The primary key of this table is on these two columns.
Another way is to add primary_number_id directly to the person table. This is probably the simplest solution.
Then you should have:
person
—————-
id (primary key int autoincrement)
primary_number_id (foreign key for phone_number.id)
name
...
phone_number
———————————-
id (primary key int autoincrement)
person_id (foreign key for person.id)
phone_number
The only problem with this solution is that you can assign as primary phone the number of somebody else.
This violates a strong principle of schema design -- don't pack a list into a cell. But...
If you only need to display the phone number to some human who will be doing a call, and
If that human possibly needs to see non-primary numbers, then
Consider having a VARCHAR(100) column that has a commalist that starts with the 'primary' phone number and continues with alternative numbers.
Note that the application would be responsible for putting the list together, and dealing with updates. Or you could push this back onto the user by providing a UI that asks for "phone number(s), starting with the preferred one to call you with; please separate with commas."
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;
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.
I have two tables (A and B) and I want each record in these tables to have an unique ID (id_C). How do I do that?
TABLE_A:
id_A | id_C
1 1
2 3
TABLE_B:
id_B | id_C
1 2
2 4
PS. I was thinking about something like this:
create table c(
id_c int not null auto_increment,
PRIMARY KEY(id_c)
);
create table a(
id_a int not null auto_increment,
a_c int not null,
PRIMARY KEY(id_a),
FOREIGN KEY (a_c) REFERENCES c(id_c)
);
create table b(
id_b int not null auto_increment,
b_c int not null,
PRIMARY KEY(id_b),
FOREIGN KEY (b_c) REFERENCES c(id_c)
);
Create a table which contains your IDs and make it an auto-incrementing primary key. Use this table to generate unique ids and reference them with foreign key constraints from the other tables. I think this is what you suggested in your question.
Another alternative is to use a GUID.
In mysql can I set a condition that a combination of two fields can never be the same???
Example:
id-1
name-abc
grade-A
Now, another entry with name='abc' and grade='A' can not be added into that table ????
You can create a composite primary key from those two columns, but that makes little sense as the table already has an ID field, and surely two people of the same name can have the same grade? e.g.:
CREATE TABLE student_grades (
id int unsigned not null,
name varchar not null,
grade varchar not null,
PRIMARY KEY(name, grade));
You can also add a secondary UNIQUE constraint:
CREATE TABLE student_grades (
id int unsigned not null,
name varchar(10) not null,
grade varchar(10) not null,
PRIMARY KEY(id),
UNIQUE KEY(name, grade)
);