I'm having trouble adding a foreign key field that references another table.
First I created the users table as so:
CREATE TABLE users (
user_id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
userName VARCHAR(256) NOT NULL,
userEmail VARCHAR (256) NOT NULL,
userPwd VARCHAR(256) NOT NULL,
);
then I'd like the quizzes table to have a foreign key that references the user_id from the first table
CREATE TABLE quizzes (
quizId INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
quizName VARCHAR(128) NOT NULL,
quizMax SMALLINT(6) NOT NULL,
FOREIGN KEY (user_id) REFERENCES users (user_id)
);
This is throwing the error: 'Key column 'user_id' doesn't exist in table.
Other answers advised to check that DB is InnoDB, which I did, and it is.
Can't understand why it's telling me that user_id doesn't exist, when it clearly does exist in the users table.
Firstly check if table user is created successfully, due to the additional ',' on last column!
Secondly, the column you reffered in FOREIGN KEY(user_id) is not defined in table quizzes, you need to add this column in quizzes table.
First: You do not need the last comma - , in the first CREATE statement. -
Second: you have to create the columns before you can use them in a foreign key constraint and user_id does not exist in the second table at the moment of constraint creation.
Take a look at the example below. The last create succeeds when user_id column is added before the constraint is created:
The following is the JSON file...
{
"name":"Magic 2014 Core Set",
"code":"M14",
"releaseDate":"2013-07-19",
"border":"black",
"type":"core",
"cards":
[
{
"layout":"normal",
"type":"Creature - Human Warrior",
"types":["Creature"],
"colors":["Red"],
"multiverseid":370735,
"name":"Academy Raider",
"subtypes":["Human","Warrior"],
"cmc":3,
"rarity":"Common",
"artist":"Karl Kopinski",
"power":"1",
"toughness":"1",
"manaCost":"{2}{R}",
"text":"Intimidate (This creature can't be blocked except by artifact creatures and/or creatures that share a color with it.)\n\nWhenever Academy Raider deals combat damage to a player, you may discard a card. If you do, draw a card.",
"number":"124",
"imageName":"academy raider"
},
{
"layout":"normal",
"type":"Artifact - Equipment",
"types":["Artifact"],
"colors":[],
"multiverseid":370581,
"name":"Accorder's Shield",
"subtypes":["Equipment"],
"cmc":0,
"rarity":"Uncommon",
"artist":"Alan Pollack",
"manaCost":"{0}",
"text":"Equipped creature gets +0/+3 and has vigilance. (Attacking doesn't cause it to tap.)\n\nEquip {3} ({3}: Attach to target creature you control. Equip only as a sorcery.)",
"flavor":"An Auriok shield is polished to a mirror finish even on the inside, enabling its bearer to watch foes ahead and behind.",
"number":"204",
"imageName":"accorder's shield"
},
{
"layout":"normal",
"type":"Creature - Spirit",
"types":["Creature"],
"colors":["Black"],
"multiverseid":370811,
"name":"Accursed Spirit",
"subtypes":["Spirit"],
"cmc":4,
"rarity":"Common",
"artist":"Kev Walker",
"power":"3",
"toughness":"2",
"manaCost":"{3}{B}",
"text":"Intimidate (This creature can't be blocked except by artifact creatures and/or creatures that share a color with it.)",
"flavor":"Many have heard the slither of dragging armor and the soft squelch of its voice. But only its victims ever meet its icy gaze.",
"number":"83",
"imageName":"accursed spirit"
},
{...},
{...},
{...},
]
}
The cards data itself I think would be in a single table but I'm not sure how the...
"name":"Magic 2014 Core Set",
"code":"M14",
"releaseDate":"2013-07-19",
"border":"black",
"type":"core",
would be associated with the card data. How should I design the MySQL table(s) for easy and efficient access?
MySQL is a relational database. This means that any solution you come up with will need to include a primary key, a foreign key and normalization. Here is a simple tutorial that will show you what to do. Have fun!
http://www.dreamincode.net/forums/topic/179103-relational-database-design-normalization/
It's hard to say how data should be structured as that can depend on your application. However, as a first cut, some good rules of thumb might be:
All non-array data at the same "level" of a single JSON object is a single table. By level I mean how deeply nested the objects are. So, for example, given {"a": 100, "b": "hello", "c": {"x": 100, "y": "foo"}}, a, and b are on the same level, while x and y are on a different level.
You have a few options for handling data on different levels:
"flatten" the nesting so that, for the example above, you'd have a single table containing a, b, x, and y.
Create new tables for each nesting level. Given the example above, that's one table containing a and b, and one containing x and y. There's clearly a relationship between these two tables which tells you if you how to construct linking keys. See https://stackoverflow.com/a/7296873/1431244 for details on that.
Arrays pretty clearly indicate a one-to-many relationship so those go in their own table as described by the post linked above.
The JSON file above is pretty big, so I'm not going to construct all tables with all fields, but here's a sample that hopefully explains the rough idea:
create table card_pack (
# Primary key to uniquely identify the pack
id integer autoincrement primary key,
name TEXT,
# foreign key that links to the codes table
code_id integer,
# etc, etc...
);
create table codes (
# This is what the code_id field in the card_pack table refers to
id integer autoincrement primary key,
name CHAR(10)
);
create table cards (
# unique key for each card
id integer autoincrement primay key,
# Refers to the card_pack table for the card pack
# containing this card
pack_id integer,
name TEXT,
# This should probably be a foreign key referring to a layouts table
# which contains one row per layout
layout TEXT,
# etc, etc.
)
# Table with one row for every possible card color
create table colors {
id integer autoincrement primay key,
name TEXT,
)
# table that defines a many-to-many relationship
# indicating which cards are which colors, so a row with
# card_id = 7 and color_id = 11 means that card 7 is color 11.
# Note that another row might have card_id 7 and color_id 18
# so that card 7 is two colors, both color 11 and color 18.
create table cards_colors (
card_id integer,
color_id integer
)
In the above there's a lot of details missing. For example, you probably don't really want a generic TEXT type for all string fields. Some should probably be CHAR and some VARCHAR depending on field sizes, space vs. performance considerations, etc. Similarly where I have integer you might want bigint, mediumint, etc. depending on the number of values you expect, etc. There's also index considerations, foreign key constraints, and so on, but the above hopefully gives you the right idea and provides enough information to get started.
I think you must have 2 tables to store such data.
create table tbl_card (
card_id int primary key auto_increment,
name varchar(50) not null,
code varchar(10) not null,
release_date datetime not null,
border varchar(20) not null,
type varchar(20) not null
)
create table tbl_card_detail (
card_id int not null,
type varchar not null,
....
primary key (card_id,type)
)
Here is the Normalized Schema in Raw Form , You can alter it your needs and Update it with Null, Primary Key, Foreign Key attributes , Type with respect to database you are using
Bold (Highlighted) are table Names, PK = Primary key, FK = Foreign Key, u can alter as per your needs
Template (TABLE)
1- Name
2- Code
3- Release Date
4- Border
5- Type
6- Id (PK)
Template Cards (TABLE)
1- Template Id (FK) (Template Table )
2- Card Id (FK) (Cards Table)
Cards ( Has M-M relationship with Types, Cards ,Subtypes Table) (TABLE)
1- layout
2- type
3- mutiverseid
4- name
5- Card Id (PK)
6- Card Detail Id
Cards Detail
1- Card detail Id
2- Card Id
2- Object Type ( 0 = Types , 1 = Color , 2 = Subtypes )
3- Object Id ( This id corresponds to Types, Color , Subtypes Table with respect to Object Type )
Types (TABLE)
1- type id (PK)
2- type Detail/Code
Color (TABLE)
1- Color id (PK)
2- Color Detail/Code
SubTypes (TABLE)
1- Subtype id (PK)
2- Subtype Detail/Code
I think you should go with a table cardSet that would contain (name, code, releaseDate, border, type) and another table for cards with a foreign key referring to cardSet
you would also need to make type, color, subtype tables that would have a many to many relationship with the card table since you can have a card with more than one type, color or subtype
CREATE TABLE `card` (
`id` INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
);
CREATE TABLE `type` (
`id` INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
);
CREATE TABLE `cardType` (
`card` INT,
`type` INT
);
CREATE TABLE `cardSet` (
`id` INT NOT NULL AUTO_INCREMENT,
`` INT,
PRIMARY KEY (`id`)
);
CREATE TABLE `color` (
`id` INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
);
CREATE TABLE `cardColor` (
`card` INT,
`color` INT
);
CREATE TABLE `subType` (
`id` INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
);
CREATE TABLE `cardSubType` (
`card` INT,
`subType` INT
);
ALTER TABLE `cardType` ADD CONSTRAINT `cardType_fk1` FOREIGN KEY (`card`) REFERENCES card(`id`);
ALTER TABLE `cardType` ADD CONSTRAINT `cardType_fk2` FOREIGN KEY (`type`) REFERENCES type(`id`);
ALTER TABLE `cardSet` ADD CONSTRAINT `cardSet_fk1` FOREIGN KEY (``) REFERENCES cardSet(`id`);
ALTER TABLE `cardColor` ADD CONSTRAINT `cardColor_fk1` FOREIGN KEY (`card`) REFERENCES card(`id`);
ALTER TABLE `cardColor` ADD CONSTRAINT `cardColor_fk2` FOREIGN KEY (`color`) REFERENCES color(`id`);
ALTER TABLE `cardSubType` ADD CONSTRAINT `cardSubType_fk1` FOREIGN KEY (`card`) REFERENCES card(`id`);
ALTER TABLE `cardSubType` ADD CONSTRAINT `cardSubType_fk2` FOREIGN KEY (`subType`) REFERENCES subType(`id`);
I have 2 tables, customers and affiliates. I need to make sure that customers.email and affiliates.email are exclusive. In other words, a person cannot be both a customer and an affiliate. It's basically the opposite of a foreign key. Is there a way to do this?
You can use a table that stores emails and have unique constrain on the email, and reference that table from the customer and affiliate. (still need to ensure that there are no 2 records referencing the same key)
You can use trigger before insert and before update to check if the email is not present.
Or you can leave this validation to the application logic - not in the database, but in the applicationc ode.
There is no key you can do this with, but it sounds like you shouldn't be using two tables. Instead, you can have one table with either customer/affiliate data (that needs to be unique in this table) and another table that has the type (customer/affiliate).
CREATE TABLE People (
pplid,
pplEmail,
ptid,
UNIQUE KEY (pplEmail)
)
CREATE TABLE PeopleType (
ptid,
ptType
)
INSERT INTO PeopleType VALUES (1, 'affiliates'), (2, 'customers');
You can try the following.
Create a new table, which will be a master for customers and affiliates:
CREATE TABLE party
(
id int not null auto_increment primary key ,
party_type enum('customer','affiliate') not null,
email varchar(100),
UNIQUE (id,party_type)
);
--Then
CREATE TABLE customer
(
....
party_id INT NOT NULL,
party_type enum('customer') NOT NULL DEFAULT 'customer',
PRIMARY KEY (party_id,party_type)
FOREIGN KEY (party_id,party_type) REFERENCES party(id,party_type)
);
CREATE TABLE affiliates
(
....
party_id INT NOT NULL,
party_type enum('affiliate') NOT NULL DEFAULT 'affiliate',
PRIMARY KEY (party_id,party_type)
FOREIGN KEY (party_id,party_type) REFERENCES party(id,party_type)
)
-- enum is used because mysql still doesn't have CHECK constraints
This way each party can be only of one type
I am not sure how to phrase the question so I'll illustrate the tables and the explain what I want to achieve.
-- static table of the entity classes supported by the application
create table entity_type (
id integer not null auto_increment,
name varchar(30) not null,
primary key(id)
);
-- static table of statuses supported by the application
create table entity_status (
id integer not null auto_increment,
name varchar(30) not null,
primary key(id)
);
-- table of valid combinations
create table entity_type_entity_status_link (
entity_type_id integer not null,
entity_status_id integer not null,
unique key(entity_type_id, entity_status_id),
foreign key(entity_type_id) references entity_type(id),
foreign key(entity_status_id) references entity_status(id),
);
-- The tables where user types and statuses are defined
create table user_type (
id integer not null auto_increment,
name varchar(30) not null,
entity_type_id integer not null,
primary key(id),
foreign key(entity_type_id) references entity_type(id)
);
create table user_status (
id integer not null auto_increment,
name varchar(30) not null,
entity_status_id integer not null,
primary key(id),
foreign key(entity_status_id) references entity_status(id)
);
-- table of valid pairs
create table user_type_user_status_link (
user_type_id integer not null,
user_status_id integer not null,
unique key(user_type_id, user_status_id),
foreign key(user_type_id) references user_type(id),
foreign key(user_status_id) references user_status(id),
);
The basic premise behind these tables is that the system supports core types and statuses and the user is able to create their own user types and statues that derive from these.
The question I have is that I cannot see a way of creating any database constraints on the user_type_user_status_link table to ensure that the you cannot insert a file_type - file_status pair where the parent entity_type - entity_status is itself not valid. Or is this something that would have to be done with triggers.
The basic premise behind these tables is that the system supports core
types and statuses and the user is able to create their own user types
and statues that derive from these.
Although that sounds like a laudable goal on the surface, the effect is to delegate database design to your users. Database design, because the effect of your desire to set foreign key references to a subset of the rows in entity_type_entity_status_link means each of those subsets is a defacto, unnamed table.
This approach never ends well.
What you've developed is the "One True Lookup Table". Google that for a host of reasons why OTLT is an anti-pattern.
The best solution is to model real things in your tables. (Entity isn't a real thing. It's an abstraction of a real thing.) Something along the lines of either
create table file_status (
file_status varchar(30) primary key
);
or
create table file_status (
file_status_id integer primary key,
file_status varchar(30) not null unique
);
would work well for file statuses.
In the case of the second one, you can set a foreign key reference to either the id number (saves space, requires an additional join) or to the status text (takes more space, eliminates a join). Note that you need the unique constraint on the status text; your original design allows the user to enter the same text multiple times. (You could end up with 30 rows where entity_type.name is 'File'.
You should use triggers for that.
MySQL does not support constraints of the form that will prevent what you want.
I'm beginning to build a stamp collecting web app. Python/flask backend (i think :)) mySQL as db. I don't know much about db design so please keep that in mind if I do some really stupid mistake in the way I thought it out. I was thinking of splitting the data into 3 tables.
users table (all the users should be added upon registration to this table)
stamps table (all stamps should reside here and only modified by me)
owned table (junction table with user_id and stamp_id as foreign keys)
Question : if I put user_id and stamp_id as primary key , there will only be one unique entry of this type for example user_1 has card_1. But user_1 might have a duplicate of card_1 so i should have 2 rows
user_1 card_1
user_1 card_1
Another problem that arises is that I want to include state of owned stamp. For example user_1 might have a card_1 in mint condition and a card_1 in bad condition. As far as I understand I can only enter one unique pair of user_1 card_1 . What can I do to get the desired result? Also if there's a better way of doing this please let me know.
Aditional question. I was using mysql workbench to try to plot the db so I have a question about the sql it generates. the CONSTRAINT "fk_gibberish", is that normal or ... why is that ?
CREATE TABLE IF NOT EXISTS `stampcollect`.`users` (
`user_id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
`user_username` VARCHAR(45) NULL ,
`user_password` VARCHAR(45) NULL ,
`user_email` VARCHAR(45) NULL ,
PRIMARY KEY (`user_id`) )
CREATE TABLE IF NOT EXISTS `stampcollect`.`stamps` (
`stamp_id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
`stamp_name` VARCHAR(45) NULL ,
PRIMARY KEY (`stamp_id`) )
CREATE TABLE IF NOT EXISTS `stampcollect`.`owned` (
`user_id` INT NOT NULL ,
`stamp_id` INT NOT NULL ,
`stamp_status` BIT NULL ,
PRIMARY KEY (`user_id`, `stamp_id`) ,
INDEX `fk_{F5DBEF0D-24E0-4AFF-A5CB-2A6A0D448C96}` (`stamp_id` ASC) ,
CONSTRAINT `fk_{22B4468E-A5FB-4702-A8A9-576AA48A0543}`
FOREIGN KEY (`user_id` )
REFERENCES `stampcollect`.`users` (`user_id` ),
CONSTRAINT `fk_{F5DBEF0D-24E0-4AFF-A5CB-2A6A0D448C96}`
FOREIGN KEY (`stamp_id` )
REFERENCES `stampcollect`.`stamps` (`stamp_id` ));
If users can own the same stamp in multiple states then the state should go in the "owned" table and be part of the key. If he can own multiple copies of the same stamp then it would make sense to have a "quantity" column in that table (not part of the key).
Add an id field with auto-increment on your owned table, and make that the primary key.
Regarding the other question: it's just Workbench generating a unique id for your foreign key. You can rename them, just keep them unique.