I have a table friend :
when I want to insert two new records like (1,2, true), (1,2, false) I got duplicate du champ '1-2' its logic, because when I insert another Two records (1,2, true) (2,1, false) it goes well. my question is why? I think that (1,2) (2,1) is also duplicated for the composite primary key (request_to , request_from )
my sql queries :
INSERT INTO `friends` (`request_to`, `request_from`, `confirmed`, `date_confirmation`) VALUES ('11', '12', b'1', NULL), ('12', '11', '', NULL)
Seems to me like the PRIMARY key "request_to" is enough to create a constraint violation for the duplicate (1) .
You have a primary key on request_to and request_from.
That means that you cannot insert duplicate values into this column. In your example that fails, (1, 2) is duplicated. In your example that works, (1, 2) <> (2, 1), so it is okay (for this constraint).
If you want uniqueness regardless of direction, add a unique constraint:
create unique index unq_friends_to_from on
friends(least(request_to, request_from), greatest(request_to, request_from));
Related
I have a simple table with students in MySQL database. Similar to:
student_id
student_name
teacher_id
1
Adam
100
2
Bob
100
3
Carl
100
4
Dan
200
Teachers can input new students or change existing student's names. Currently I have this set up to update via:
INSERT INTO student_list (name) VALUES (:name) ON DUPLICATE KEY UPDATE student name= values(name)
The problem is that this completely breaks any associated student_ids in other tables (as the ON DUPLICATE KEY UPDATE changes the student_id). I could look up each entry before updating, but it seems messy. Surely there's a better way.
CREATE TABLE `sabrep_db`.`students` ( `student_id` INT NOT NULL AUTO_INCREMENT , `name` TEXT NOT NULL , `teacher_id` INT NOT NULL , PRIMARY KEY (`student_id`)) ENGINE = InnoDB;
INSERT INTO `students` (`student_id`, `name`, `teacher_id`) VALUES (NULL, 'Adam', '100'), (NULL, 'Bob', '100');
Should also pass a key (usually the primary key) as part of the insert so that it knows the key reference to update when there is a duplicate, name is passed twice for the update portion:
INSERT INTO student_list (student_id, name)
VALUES (:student_id, :name) ON DUPLICATE KEY UPDATE student_name = :name;
I need to create the following database:
For semi-trucks I don't need extra subtypes, while for Car I need to have only those 3 subtypes and also for Sedan I need the four subtypes.
For SELECTs I will use JOINs (normalized database) but I need to find an easy way to make INSERTs.
Vehicle table stores common information
Semi-truck stores specific information for semis
Car tables has specific fields for cars and a car_type field which is linked to the three subtypes
Van, Suv and Sedan (and other types if I would need them) should be in one table CAR_TYPE
However, for Sedan type I need to have additional subtypes which maybe should be contained in another table. These subtypes are not needed for Suvs and Vans (in real life suv, vans can have the same subtypes as sedans but not in my case).
I need this database to be created exactly as it is in the diagram.
So far, my first approach is to have the following tables:
Vehicle: veh_id, veh_type(Semi, car), ..., other_fields
Vehicle_semis: veh_id, ..., other_semis_fields
Vehicle_car: veh_id, car_type(Van, Suv, Sedan), other_car_specific_fields
Car_type: car_type_id, type
Sedan_type: sedan_type_id, type
My problem is that I'm not sure this would be the right approach, and I don't know exactly how to create relationships between the tables.
Any ideas?
Thank you!
UPDATE:
The following diagram is based on #Mike 's answer:
Before I get started, I want to point out that "gas" describes either fuel or a kind of engine, not a kind of sedan. Think hard before you keep going down this path. (Semantics are more important in database design than most people think.)
What you want to do is fairly simple, but not necessarily easy. The important point in this kind of supertype/subtype design (also known as an exclusive arc) is to make it impossible to have rows about sedans referencing rows about semi-trucks, etc..
MySQL makes the code more verbose, because it doesn't enforce CHECK constraints. You're lucky; in your application, the CHECK constraints can be replaced by additional tables and foreign key constraints. Comments refer to the SQL above them.
create table vehicle_types (
veh_type_code char(1) not null,
veh_type_name varchar(10) not null,
primary key (veh_type_code),
unique (veh_type_name)
);
insert into vehicle_types values
('s', 'Semi-truck'), ('c', 'Car');
This is the kind of thing I might implement as a CHECK constraint on other platforms. You can do that when the meaning of the codes is obvious to users. I'd expect users to know or to figure out that 's' is for semis and 'c' is for cars, or that views/application code would hide the codes from users.
create table vehicles (
veh_id integer not null,
veh_type_code char(1) not null,
other_columns char(1) default 'x',
primary key (veh_id),
unique (veh_id, veh_type_code),
foreign key (veh_type_code) references vehicle_types (veh_type_code)
);
The UNIQUE constraint lets the pair of columns {veh_id, veh_type_code} be the target of a foreign key reference. That means a "car" row can't possibly reference a "semi" row, even by mistake.
insert into vehicles (veh_id, veh_type_code) values
(1, 's'), (2, 'c'), (3, 'c'), (4, 'c'), (5, 'c'),
(6, 'c'), (7, 'c');
create table car_types (
car_type char(3) not null,
primary key (car_type)
);
insert into car_types values
('Van'), ('SUV'), ('Sed');
create table veh_type_is_car (
veh_type_car char(1) not null,
primary key (veh_type_car)
);
Something else I'd implement as a CHECK constraint on other platforms. (See below.)
insert into veh_type_is_car values ('c');
Only one row ever.
create table cars (
veh_id integer not null,
veh_type_code char(1) not null default 'c',
car_type char(3) not null,
other_columns char(1) not null default 'x',
primary key (veh_id ),
unique (veh_id, veh_type_code, car_type),
foreign key (veh_id, veh_type_code) references vehicles (veh_id, veh_type_code),
foreign key (car_type) references car_types (car_type),
foreign key (veh_type_code) references veh_type_is_car (veh_type_car)
);
The default value for veh_type_code, along with the foreign key reference to veh_type_is_car, guarantees that this rows in this table can be only about cars, and can only reference vehicles that are cars. On other platforms, I'd just declare the column veh_type_code as veh_type_code char(1) not null default 'c' check (veh_type_code = 'c').
insert into cars (veh_id, veh_type_code, car_type) values
(2, 'c', 'Van'), (3, 'c', 'SUV'), (4, 'c', 'Sed'),
(5, 'c', 'Sed'), (6, 'c', 'Sed'), (7, 'c', 'Sed');
create table sedan_types (
sedan_type_code char(1) not null,
primary key (sedan_type_code)
);
insert into sedan_types values
('g'), ('d'), ('h'), ('e');
create table sedans (
veh_id integer not null,
veh_type_code char(1) not null,
car_type char(3) not null,
sedan_type char(1) not null,
other_columns char(1) not null default 'x',
primary key (veh_id),
foreign key (sedan_type) references sedan_types (sedan_type_code),
foreign key (veh_id, veh_type_code, car_type) references cars (veh_id, veh_type_code, car_type)
);
insert into sedans (veh_id, veh_type_code, car_type, sedan_type) values
(4, 'c', 'Sed', 'g'), (5, 'c', 'Sed', 'd'), (6, 'c', 'Sed', 'h'),
(7, 'c', 'Sed', 'e');
If you have to build additional tables that reference sedans, such as gas_sedans, diesel_sedans, etc., then you need to build one-row tables similar to "veh_type_is_car" and set foreign key references to them.
In production, I'd revoke permissions on the base tables, and either use
updatable views to do the inserts and updates, or
stored procedures to do the inserts and updates.
I refer you to the "Info" tab under the following three tags:
class-table-inheritance
single-table-inheritance
shared-primary-key
The first two describe the two major design patterns for dealing with a class/subclass (aka type/subtype) situation when designing a relational database. The third descibes a technique for using a single primary key that gets assigned in the superclass table and gets propagated to the subclass tables.
They don't completely answer the questions you raise, but they shed some light on the whole topic. This topic, of mimicking inheritance in SQL, comes up over and over again in both SO and the DBA area.
I am using insert on duplicate key update for updating the status of many orders.
However if I enter an id that does not exist, mysql creates a new order.
Is there any way to NOT create a new order?
Here is my query
INSERT INTO
`order`
( id, status )
VALUES (1, 'COMPLETE'), (2, 'COMPLETE'), (3, 'INVALID')
ON DUPLICATE KEY UPDATE
status = VALUES(status)
Add backtracks for table name
INSERT INTO `order`( id, status ) VALUES (1, '43534'), (2, '434'), (3,'345345') ON DUPLICATE KEY UPDATE status = VALUES(status)
So i want to implement an UPSERT query. Where i do not wish to query and first check if the user exists and then insert rather i want to check during insertion and update the field if the user exists. I have tried all these queries but none work.
INSERT INTO `sys_cart` (`userid`, `product_ids`, `date_added`, `date_updated`, `date_deleted`)
VALUES (2 ,`3,4`, `2017-02-01 00:00:00`, `2017-02-01 00:00:00`, null)
ON DUPLICATE `sys_cart.userid` UPDATE `product_ids` = '12,13';
INSERT INTO 'sys_cart'
VALUES (4, '34,12', '2017-02-01 00:00:00', '2017-02-01 00:00:00', null)
ON DUPLICATE userid UPDATE product_ids = VALUES('3,4');
INSERT INTO 'sys_cart'
VALUES (4, 'Gorilla', '2017-02-01 00:00:00', '2017-02-01 00:00:00', null)
ON DUPLICATE userid UPDATE product_ids;
INSERT INTO 'sys_cart'
VALUES (4, 'Gorilla', '2017-02-01 00:00:00', '2017-02-01 00:00:00', null)
ON DUPLICATE userid UPDATE product_ids = VALUES('3,4');
INSERT INTO sys_cart (userid, product_ids, date_added, date_updated, date_deleted)
VALUES (4, "Gorilla", "2017-02-01 00:00:00", "2017-02-01 00:00:00", null)
ON DUPLICATE userid UPDATE product_ids = VALUES("3,4");
INSERT INTO sys_cart (userid, product_ids, date_added, date_updated, date_deleted)
VALUES (4, "Gorilla", "2017-02-01 00:00:00", "2017-02-01 00:00:00", null)
ON DUPLICATE userid UPDATE product_ids = "3,4";
Where am i going wrong?
As per the documentation, the syntax is ON DUPLICATE KEY, literally. You can't specify which column is the key in the query - that's defined at the table level.
You syntax should be:
INSERT INTO sys_cart
VALUES (4, '34,12', '2017-02-01 00:00:00', '2017-02-01 00:00:00', null)
ON DUPLICATE KEY UPDATE product_ids = VALUES(product_ids)
What you may also be missing is that userid must be defined as the PRIMARY KEY of sys_cart. You may need to do something like:
ALTER TABLE sys_cart
MODIFY COLUMN userid INT PRIMARY KEY
As an aside, you should consider using a child table for the product ids, rather than stuffing a CSV into a single field, which will be hard to deal with later on.
I need to create the following database:
For semi-trucks I don't need extra subtypes, while for Car I need to have only those 3 subtypes and also for Sedan I need the four subtypes.
For SELECTs I will use JOINs (normalized database) but I need to find an easy way to make INSERTs.
Vehicle table stores common information
Semi-truck stores specific information for semis
Car tables has specific fields for cars and a car_type field which is linked to the three subtypes
Van, Suv and Sedan (and other types if I would need them) should be in one table CAR_TYPE
However, for Sedan type I need to have additional subtypes which maybe should be contained in another table. These subtypes are not needed for Suvs and Vans (in real life suv, vans can have the same subtypes as sedans but not in my case).
I need this database to be created exactly as it is in the diagram.
So far, my first approach is to have the following tables:
Vehicle: veh_id, veh_type(Semi, car), ..., other_fields
Vehicle_semis: veh_id, ..., other_semis_fields
Vehicle_car: veh_id, car_type(Van, Suv, Sedan), other_car_specific_fields
Car_type: car_type_id, type
Sedan_type: sedan_type_id, type
My problem is that I'm not sure this would be the right approach, and I don't know exactly how to create relationships between the tables.
Any ideas?
Thank you!
UPDATE:
The following diagram is based on #Mike 's answer:
Before I get started, I want to point out that "gas" describes either fuel or a kind of engine, not a kind of sedan. Think hard before you keep going down this path. (Semantics are more important in database design than most people think.)
What you want to do is fairly simple, but not necessarily easy. The important point in this kind of supertype/subtype design (also known as an exclusive arc) is to make it impossible to have rows about sedans referencing rows about semi-trucks, etc..
MySQL makes the code more verbose, because it doesn't enforce CHECK constraints. You're lucky; in your application, the CHECK constraints can be replaced by additional tables and foreign key constraints. Comments refer to the SQL above them.
create table vehicle_types (
veh_type_code char(1) not null,
veh_type_name varchar(10) not null,
primary key (veh_type_code),
unique (veh_type_name)
);
insert into vehicle_types values
('s', 'Semi-truck'), ('c', 'Car');
This is the kind of thing I might implement as a CHECK constraint on other platforms. You can do that when the meaning of the codes is obvious to users. I'd expect users to know or to figure out that 's' is for semis and 'c' is for cars, or that views/application code would hide the codes from users.
create table vehicles (
veh_id integer not null,
veh_type_code char(1) not null,
other_columns char(1) default 'x',
primary key (veh_id),
unique (veh_id, veh_type_code),
foreign key (veh_type_code) references vehicle_types (veh_type_code)
);
The UNIQUE constraint lets the pair of columns {veh_id, veh_type_code} be the target of a foreign key reference. That means a "car" row can't possibly reference a "semi" row, even by mistake.
insert into vehicles (veh_id, veh_type_code) values
(1, 's'), (2, 'c'), (3, 'c'), (4, 'c'), (5, 'c'),
(6, 'c'), (7, 'c');
create table car_types (
car_type char(3) not null,
primary key (car_type)
);
insert into car_types values
('Van'), ('SUV'), ('Sed');
create table veh_type_is_car (
veh_type_car char(1) not null,
primary key (veh_type_car)
);
Something else I'd implement as a CHECK constraint on other platforms. (See below.)
insert into veh_type_is_car values ('c');
Only one row ever.
create table cars (
veh_id integer not null,
veh_type_code char(1) not null default 'c',
car_type char(3) not null,
other_columns char(1) not null default 'x',
primary key (veh_id ),
unique (veh_id, veh_type_code, car_type),
foreign key (veh_id, veh_type_code) references vehicles (veh_id, veh_type_code),
foreign key (car_type) references car_types (car_type),
foreign key (veh_type_code) references veh_type_is_car (veh_type_car)
);
The default value for veh_type_code, along with the foreign key reference to veh_type_is_car, guarantees that this rows in this table can be only about cars, and can only reference vehicles that are cars. On other platforms, I'd just declare the column veh_type_code as veh_type_code char(1) not null default 'c' check (veh_type_code = 'c').
insert into cars (veh_id, veh_type_code, car_type) values
(2, 'c', 'Van'), (3, 'c', 'SUV'), (4, 'c', 'Sed'),
(5, 'c', 'Sed'), (6, 'c', 'Sed'), (7, 'c', 'Sed');
create table sedan_types (
sedan_type_code char(1) not null,
primary key (sedan_type_code)
);
insert into sedan_types values
('g'), ('d'), ('h'), ('e');
create table sedans (
veh_id integer not null,
veh_type_code char(1) not null,
car_type char(3) not null,
sedan_type char(1) not null,
other_columns char(1) not null default 'x',
primary key (veh_id),
foreign key (sedan_type) references sedan_types (sedan_type_code),
foreign key (veh_id, veh_type_code, car_type) references cars (veh_id, veh_type_code, car_type)
);
insert into sedans (veh_id, veh_type_code, car_type, sedan_type) values
(4, 'c', 'Sed', 'g'), (5, 'c', 'Sed', 'd'), (6, 'c', 'Sed', 'h'),
(7, 'c', 'Sed', 'e');
If you have to build additional tables that reference sedans, such as gas_sedans, diesel_sedans, etc., then you need to build one-row tables similar to "veh_type_is_car" and set foreign key references to them.
In production, I'd revoke permissions on the base tables, and either use
updatable views to do the inserts and updates, or
stored procedures to do the inserts and updates.
I refer you to the "Info" tab under the following three tags:
class-table-inheritance
single-table-inheritance
shared-primary-key
The first two describe the two major design patterns for dealing with a class/subclass (aka type/subtype) situation when designing a relational database. The third descibes a technique for using a single primary key that gets assigned in the superclass table and gets propagated to the subclass tables.
They don't completely answer the questions you raise, but they shed some light on the whole topic. This topic, of mimicking inheritance in SQL, comes up over and over again in both SO and the DBA area.