What does an UNIQUE KEY constraint for a primary key mean? - php

In Symfony2 doc 'How to use PdoSessionStorage to store Sessions in the Database', which show the session table like this:
CREATE TABLE `session` (
`session_id` varchar(255) NOT NULL,
`session_value` text NOT NULL,
`session_time` int(11) NOT NULL,
PRIMARY KEY (`session_id`),
UNIQUE KEY `session_id_idx` (`session_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Why unique key constraint is needed for the primary key?

A primary key is by definition a unique key. In this example, it's just a duplicated unecessary key.
In other cases, where the primary key could potentially be composite (consisting of two or more fields), such secondary indexes would allow the individual components of the primary key to be addressed seperately.
For instance:
create table X {
a char,
b char,
primary key (a,b)
}
where you do a query with WHERE b=something, would not use the primary key index, as B's index entries are tied to 'a', and you're not using 'a' in the query. Adding a secondary seperate index dedicated to just B allows index use for this where clause.

Primary keys have to be unique by definition. (regardless of RDBMS)
A primary key is a combination of columns which uniquely specify a row.

Related

MYSQL table wont allow multiple foreign keys

I know this has been asked again and again, and I've tried so many times and don't understand why I keep getting errors, but I'm trying to connect the order details table to the order items, users and payment table, but SQL is coming up with. (this is for a school project)
I've been able to connect a table with two constraints but never with three.
#1005 - Can't create table oursmall.order_details (errno: 150 "Foreign key constraint is incorrectly formed")
CREATE TABLE IF NOT EXISTS order_details(
order_details_id INT(10) NOT NULL AUTO_INCREMENT,
order_items_id INT(10) NOT NULL,
users_id INT(10) NOT NULL,
total DECIMAL(6,2) NOT NULL,
payment_id INT(10) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(order_details_id),
CONSTRAINT fk_order FOREIGN KEY(order_items_id) REFERENCES order_items(order_items_id),
CONSTRAINT fk_users FOREIGN KEY(users_id) REFERENCES users(users_id),
CONSTRAINT fk_payment FOREIGN KEY(payment_id) REFERENCES users(payment_id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE="utf8_unicode_ci";
Thank you!
The column(s) referenced by a foreign key must be a key of the referenced table. Either the primary key or at least a secondary unique key.*
CONSTRAINT fk_payment FOREIGN KEY(payment_id) REFERENCES users(payment_id)
Is payment_id really the primary or unique key of the users table? I would be surprised if it is.
The second foreign key references users.users_id, right? That's what I assume is the primary key of that table.
* InnoDB supports a non-standard feature to allow the referenced column to be any indexed column, even a non-unique one. But this is not the standard of foreign keys in the SQL language, and I don't recommend doing it. For example, if a foreign key references a value that may appear on multiple rows in the parent table, what does that mean? Which row is truly the parent row?

Cannot create MYSQL primary keys

I am trying to drop the existing primary keys and add two new primary primary keys in an existing database table using the following query:
ALTER TABLE `match_team_recruit` DROP PRIMARY KEY,
ADD PRIMARY KEY (`ind_stnum`, `team_send`);
However, I get the following error when running the query.
#1062 - Duplicate entry '183-0' for key 'PRIMARY'
Please see attached Image below:
Can anyone advise how I can solve this?
A primary key in MySQL has to follow these three rules.
A primary key must contain unique values. If the primary key consists of multiple columns, the combination of values in these columns must be unique.
A primary key column cannot contain NULL values. It means that you have to declare the primary key column with the NOT NULL attribute. If you don’t, MySQL will force the primary key column as NOT NULL implicitly.
A table has only one primary key.
Courtesy: Introduction to MySQL primary key
To fix your problem you should just add one Primary Key to your table. The Primary Key is used to distinguish Row's, therefor you can't have multiple Primary Key's in one table!

Why a can't connect my tables in MySQL?

shippings table structure
I want to connect in to another table like this(I got "1215 error"):
CREATE TABLE goods_and_shippings (
good_id INT NOT NULL,
s_date DATE NOT NULL,
shipping_id INT NOT NULL,
PRIMARY KEY (good_id),
FOREIGN KEY (s_date) REFERENCES shippings(s_date)
)
Connected columns have same data types as you can see (both DATE and NOT NULL) and all tables use InnoDB engine. But I have this snippet and it works:
CREATE TABLE goods_and_shippings (
good_id INT NOT NULL,
s_date DATE NOT NULL,
shipping_id INT NOT NULL,
PRIMARY KEY (good_id),
FOREIGN KEY (shipping_id) REFERENCES shippings(shipping_id)
)
All tables are empty for now. Here is query for creating shippings:
CREATE TABLE shippings (
shipping_id INT NOT NULL,
s_date DATE NOT NULL,
driver_id INT NOT NULL,
start_place VARCHAR(50) NOT NULL,
end_place VARCHAR(50) NOT NULL,
car_id INT NOT NULL,
price DECIMAL(5,2) NOT NULL,
PRIMARY KEY (shipping_id, s_date)
)
Here alters I've used after:
ALTER TABLE shippings ADD CONSTRAINT fk_car_id FOREIGN KEY (car_id) REFERENCES cars(car_id);
ALTER TABLE shippings ADD CONSTRAINT fk_driver_id FOREIGN KEY (driver_id) REFERENCES drivers(driver_id);
What's wrong in my queries? How to fix this and connect goods_and_shippings.s_date and shippings.s_date?
In general, foreign key references are to unique or primary keys. However, this condition is relaxed for INNODB, as explained in the documentation:
InnoDB permits a foreign key to reference any index column or group of
columns. However, in the referenced table, there must be an index
where the referenced columns are listed as the first columns in the
same order.
So, you can have a foreign reference to shipping_id because it is the first key in the primary key, but not to date. However, I would advise you to set up your foreign key relationships to complete primary keys. And, I usually have an auto-incrementing primary key in all tables, to facilitate such relationships.

Creating composite foreign key on a primary key

I have a table called events with event_id as a primary key and a table person with person_id as a primary key.
I want to have a table that contains two columns event_id and person_id as foreign keys to the above two primary keys.
I am able to create a foreign key something like this:
create table pe(
event_id INTEGER UNSIGNED UNIQUE,
person_id INTEGER UNSIGNED UNIQUE,
FOREIGN KEY (event_id) REFERENCES events(event_id),
FOREIGN KEY (person_id) REFERENCES person(person_id)
);
but I cannot insert values like:
----------------------
event_id person_id
----------------------
1 1
1 2
2 1
2 2
----------------------
For that I need a composite foreign key.
I am not able to decide how to do that. Any suggestions or help are much appreciated!
Thanks a lot!
You need to make the combination of event_id and person_id unique. I'd just make the combination the primary key, as follows:
create table pe(
event_id INTEGER UNSIGNED,
person_id INTEGER UNSIGNED,
FOREIGN KEY (event_id) REFERENCES events(event_id),
FOREIGN KEY (person_id) REFERENCES person(person_id),
PRIMARY KEY (event_id, person_id)
);
Because you have set individual unique key for each column. Here's how to enforce composite unique key,
create table pe
(
event_id INTEGER UNSIGNED,
person_id INTEGER UNSIGNED,
FOREIGN KEY (event_id) REFERENCES events(event_id),
FOREIGN KEY (person_id) REFERENCES person(person_id),
UNIQUE (event_id, person_id) // <<== or it could be PRIMARY KEY
);
I played around with this schema to check what you were trying to do:
CREATE TABLE `events` (
`event_id` int(11) NOT NULL AUTO_INCREMENT,
`event_name` varchar(255) NOT NULL,
PRIMARY KEY (`event_id`),
UNIQUE KEY `event_name_UNIQUE` (`event_name`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
CREATE TABLE `person` (
`person_id` int(11) NOT NULL AUTO_INCREMENT,
`person_name` varchar(225) DEFAULT NULL,
PRIMARY KEY (`person_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
CREATE TABLE `pe` (
`event_id` int(11) NOT NULL,
`person_id` int(11) NOT NULL,
PRIMARY KEY (`event_id`,`person_id`),
KEY `fk_events_has_person_person1` (`person_id`),
KEY `fk_events_has_person_events` (`event_id`),
CONSTRAINT `fk_events_has_person_events` FOREIGN KEY (`event_id`) REFERENCES `events` (`event_id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `fk_events_has_person_person1` FOREIGN KEY (`person_id`) REFERENCES `person` (`person_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8
I think your confusion lies in where you put the UNIQUE property. Each event and person needs to be unique. That is guaranteed by the primary key in the respective tables and you can also add a UNIQUE constraint in, for example, a column like person_name to ensure actual values are unique. There was nothing wrong with your foreign keys; the problem was that you added UNIQUE constraints to each field of the interim table. That's a mistake. If you want to ensure that each row of the interim table is unique then you need to add a composite primary key or as JW suggested a composite UNIQUE constraint.

How can I make a key pair primary?

I have table that doesn't need a specific field to be the primary key. I could add a auto-increment ID field, but it won't be used at all within database queries...
Can I make a UNIQUE KEY to be primary too?
the UNIQUE KEY consists of two fields paired together:
a VARCHAR(64) NOT NULL,
b VARCHAR(64) NOT NULL,
UNIQUE KEY uk_ab(a,b)
Sure (no need for UNIQUE KEY):
PRIMARY KEY (a, b)
Have a look at the documentation:
A PRIMARY KEY is a unique index where all key columns must be defined as NOT NULL. If they are not explicitly declared as NOT NULL, MySQL declares them so implicitly (and silently). A table can have only one PRIMARY KEY. The name of a PRIMARY KEY is always PRIMARY, which thus cannot be used as the name for any other kind of index.
and
A PRIMARY KEY can be a multiple-column index. However, you cannot create a multiple-column index using the PRIMARY KEY key attribute in a column specification. Doing so only marks that single column as primary. You must use a separate PRIMARY KEY(index_col_name, ...) clause.
Not sure if this would work...
PRIMARY KEY uk_ab(a,b)
If your table already has a unique constraint, then you need to add primary key (ALTER TABLE [table_name] ADD CONSTRAINT [constraint_name] PRIMARY KEY (a,b)), and drop the existing unique constraint. Otherwise, you will have 2 unique indexes on the same columns.
If you create a new table, use PRIMARY KEY(a,b) instead of UNIQUE(a,b) as proposed by others.

Categories