MySQL: What kind of index should I create in this table? - mysql

Suppose this is the SQL code of the table:
CREATE TABLE `user_is_in` (
`id_user` INT NULL ,
`id_city` INT NULL ,
`when` DATETIME NULL ,
INDEX `fk_user` (`id_user` ASC) ,
INDEX `fk_city` (`id_city` ASC) ,
CONSTRAINT `fk_user`
FOREIGN KEY (`id_user` )
REFERENCES `user` (`id` )
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT `fk_city`
FOREIGN KEY (`id_city` )
REFERENCES `city` (`id` )
ON DELETE SET NULL
ON UPDATE CASCADE)
ENGINE = InnoDB;
The use of the table is to store kind of Foursquare checkins (A user was registered on one place at one time).
Now I have 2 options:
Create an unique index with the 3 fields and no primary key:
UNIQUE INDEX id_user_is_in_UNIQUE (id_user ASC, id_city ASC, when ASC)
Create an additional classic id autoincrement field
I don't like the 2nd option because I want to create queries over users and cities (i.e.: search all users who made a checkin in a city on one date)
Thanks in advance.

You should do both. Add an auto-incrementing primary key and add a uniqueness constraint against all three columns. With a separate system assigned keys you make it easier to define foreign keys to this new table, if and when eventually required. And having the uniqueness constraint against all three columns will ensure that duplicate data is not created.
Some quick side notes:
Since this is an association table, your columns really should be
NOT NULL.
You probably want to CASCADE delete's of a city down to the
association table.

Related

Make mySQL column unique for each foreign key

Let's say I have the following column in my database:
Item:
id int PRIMARY KEY,
name string,
foreign_id FOREIGN KEY
Is there a way without querying the database before insertion each time, that one foreign key cannot contain two rows with the same name?
Sure, you want to add an (unique) index for your foreign key column.
The SQL command to add that is
ALTER TABLE `mytable`
ADD UNIQUE INDEX `mytable_idx__1` (`foreign_id`);
If I understand correctly, you might want to use the UNIQUE constraint:
CREATE TABLE (
id INT PRIMARY KEY
, name VARCHAR(50) --or whatever you need
, foreign_id INT UNIQUE
FOREIGN KEY (foreign_id) REFERENCES...
);
As i Understand using FOREIGN KEY (foreign_id) REFERENCES --- will solve it. And make sure that the always make a unique key of table as foreign key for other table.
CREATE TABLE profile
(
id int NOT NULL PRIMARY KEY,
name varchar(50),
FOREIGN KEY (name)
REFERENCES member (name)
ON DELETE CASCADE
ON UPDATE CASCADE
) ENGINE=InnoDB ;

Creating a table with composite primary key referencing two foreign keys

I'm trying to create a the following table using MySQL:
CREATE TABLE registrations (
eventNumber CHAR(3) UNIQUE NOT NULL
CHECK (EXISTS (SELECT eventNumber FROM events)),
employeeNumber CHAR(5) UNIQUE NOT NULL
CHECK (EXISTS (SELECT employeeNumber FROM employees)),
PRIMARY KEY(eventNumber , employeeNumber ),
FOREIGN KEY (eventNumber) REFERENCES eventNumber (employees)
ON UPDATE RESTRICT
ON DELETE RESTRICT,
FOREIGN KEY (employeeNumber ) REFERENCES employeeNumber(employees)
ON UPDATE RESTRICT
ON DELETE RESTRICT
) ENGINE=InnoDB;
However, I get a can't create table error (1005) when I run the command. What might be going wrong here?
For reference, I got the REFERENCES statement wrong.
It should in fact read:
REFERENCES <table name>(<attribute name>)

Creating foreign keys on already indexed columns with MySQL Workbench

I am creating a database model with Workbench and create the following table:
CREATE TABLE IF NOT EXISTS `Database`.`table1` (
`idtable1` INT NOT NULL ,
`uniquecolumn` INT NOT NULL ,
PRIMARY KEY (`idtable1`) ,
UNIQUE INDEX `UniqueIndex` (`uniquecolumn` ASC) )
ENGINE = InnoDB
It has a primary key, and a unique key on my second column.
When I create foreign key constraints on them, Workbench automatically adds two indexes:
CREATE TABLE IF NOT EXISTS `Database`.`table1` (
`idtable1` INT NOT NULL ,
`uniquecolumn` INT NOT NULL ,
PRIMARY KEY (`idtable1`) ,
UNIQUE INDEX `UniqueIndex` (`uniquecolumn` ASC) ,
INDEX `FKOne` (`idtable1` ASC) , //here
INDEX `FKTwo` (`uniquecolumn` ASC) , //(I don't want this!)
CONSTRAINT `FKOne`
FOREIGN KEY (`idtable1` )
REFERENCES `Database`.`table2` (`idtable2` )
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT `FKTwo`
FOREIGN KEY (`uniquecolumn` )
REFERENCES `Database`.`table2` (`idtable2` )
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB
(The above is the forward-engineered script after adding the foreign keys to my model)
I have four indexes now.
This is what the MySQL Reference Manual says:
In the referencing table, there must be an index where the foreign key
columns are listed as the first columns in the same order. Such an
index is created on the referencing table automatically if it does not
exist.
So I understand there is no need to create indexes FKOne and FKTwo, since there are already a Primary Key and a Unique index, on the same columns, in the same order. Yet MySQL Workbench doesn't allow me to delete indexes FKOne and FKTwo. And I think I should be able to do this:
CREATE TABLE IF NOT EXISTS `Database`.`table1` (
`idtable1` INT NOT NULL ,
`uniquecolumn` INT NOT NULL ,
PRIMARY KEY (`idtable1`) ,
UNIQUE INDEX `UniqueIndex` (`uniquecolumn` ASC) ,
CONSTRAINT `FKOne`
FOREIGN KEY (`idtable1` )
REFERENCES `Database`.`table2` (`idtable2` )
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT `FKTwo`
FOREIGN KEY (`uniquecolumn` )
REFERENCES `Database`.`table2` (`idtable2` )
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB
Am I right? Would this code work? Is there some way to do it with Workbench? (Apart from deleting those two lines at the last moment before forward-engineering).
Or maybe MySQL is smart enough to refrain from creating totally redundant indexes and I don't have to worry about it...?
(I'm assuming this is when defining a model.)
See Bug 53277, where I mention the following obscure workaround:
You start with a foreign key and its corresponding generated index that you want to get rid of. Make sure the key is (at least temporarily) on a single non-unique column. In the Indexes tab, change the Type to UNIQUE. Then go to the Columns tab, where UQ is now checked, and uncheck it. The unwanted index is eliminated!

How to create composite key?

I am new to MySQL WB so I can create foreign key by adding relation between to dependen tables.
But how to create a composite key?
For example I have this table sql
CREATE TABLE TASKS
(
TEST_ID NUMBER(6) CONSTRAINT FK_TASKS_TESTS REFERENCES TESTS(TEST_ID),
TASK_ID NUMBER(3),
MAX_POINTS NUMBER,
CONSTRAINT PK_TASKS PRIMARY KEY (TEST_ID, TASK_ID)
);
Is there an option for this or it should be created otherwise?
The question comes down to uniqueness. If you know that TASK_ID will be unique then it will be better to have a single column as your primary key. MySQL allows for a multi-column primary key, but if TASK_ID will be unique just make that the primary key and add a another index on TEST_ID. The syntax for the primary key would be:
CREATE TABLE TASKS
(
TEST_ID NUMBER(6),
TASK_ID NUMBER(3),
MAX_POINTS NUMBER,
PRIMARY_KEY(TASK_ID) -- OR PRIMARY_KEY(TASK_ID, TEST_ID) for the composite key
);
See this discussion for more information.
First of all the Foreign Key constraint, i don't think it should be put there. As far as i can tell all the constraints are declared after variable declaration (it's one of the norms of sql in general)
for the composite key you nearly had it, you just one thing wrong and that is writing Contraint. here is the example working
CREATE TABLE IF NOT EXISTS TASK (
TEST_ID NUMBER(6) ,
TASK_ID NUMBER(3) ,
MAX_POINTS NUMBER ,
PRIMARY KEY (TEST_ID,TASK_ID),
CONSTRAINT fk_1 FOREIGN KEY (`TEST_ID`) REFERENCES TEST (TEST_ID)
)
Suppose you have already created a table now you can use this query to make composite primary key
alter table employee add primary key(emp_id,emp_name);

what is the difference between declaring multiple foreign keys at once or declaring them individually?

I have a table called Order_List that contains a list of orders. Each column contains a foreign key that references the primary key of an order in the order table. My question is, what is the best way to declare these foreign keys. Using MySQL Workbench I found two ways...
Method #1
CREATE TABLE IF NOT EXISTS 'mydb'.'Order_List' (
'idOrder_List' INT UNSIGNED NOT NULL AUTO_INCREMENT ,
'orderID01' INT UNSIGNED NULL ,
'orderID02' INT UNSIGNED NULL ,
'orderID03' INT UNSIGNED NULL ,
'orderID04' INT UNSIGNED NULL ,
PRIMARY KEY ('idOrder_List') ,
INDEX 'fk_Order_List_1' ('orderID01' ASC, 'orderID02' ASC, 'orderID03' ASC, 'orderID04' ASC) ,
CONSTRAINT 'fk_Order_List_1'
FOREIGN KEY ('orderID01' , 'orderID02' , 'orderID03' , 'orderID04' )
REFERENCES 'mydb'.'Order' ('idOrder' , 'idOrder' , 'idOrder' , 'idOrder' )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
Method #2
CREATE TABLE IF NOT EXISTS 'mydb'.'Order_List' (
'idOrder_List' INT UNSIGNED NOT NULL AUTO_INCREMENT ,
'orderID01' INT UNSIGNED NULL ,
'orderID02' INT UNSIGNED NULL ,
'orderID03' INT UNSIGNED NULL ,
'orderID04' INT UNSIGNED NULL ,
PRIMARY KEY ('idOrder_List') ,
INDEX 'fk_Order_List_1' ('orderID01' ASC) ,
INDEX 'fk_Order_List_2' ('orderID02' ASC) ,
INDEX 'fk_Order_List_3' ('orderID03' ASC) ,
INDEX 'fk_Order_List_4' ('orderID04' ASC) ,
CONSTRAINT 'fk_Order_List_1'
FOREIGN KEY ('orderID01' )
REFERENCES 'mydb'.'Order' ('idOrder' )
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT 'fk_Order_List_2'
FOREIGN KEY ('orderID02' )
REFERENCES 'mydb'.'Order' ('idOrder' )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT 'fk_Order_List_3'
FOREIGN KEY ('orderID03' )
REFERENCES 'mydb'.'Order' ('idOrder' )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT 'fk_Order_List_4'
FOREIGN KEY ('orderID04' )
REFERENCES 'mydb'.'Order' ('idOrder' )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
The first method combines the declaration. The second method splits it up. Which one is better? Are there any inherent weaknesses to one over the other? Thanks!
This isn't the same FK.
One ensures that the combination of the 4 columns in any OrderList row exist in a single row row in 'mydb'.'Order'
The other ensures that the 4 column values in any OrderList row exist independently of the others in some 'mydb'.'Order' row
The difference is that in the first example you have one FOREIGN KEY constraint (made of four columns), while in your second example you have four FOREIGN KEY constraints.
In your first example, the four columns refer to the same column in the Order table, so you'll be able to only store combinations of 4 identical order ids. So, it is no more useful than a simple one-column reference.
If you use the second example, you'll be able to store any combination of 4 orders in the OrderList table.
That is one god awful way of doing an order list. You should have an order list table, and a order list entries table. That way you don't have just 4 items in the list, and only a single index/foreign key from the order list entries table to the orders table.