I have this table:
CREATE TABLE `test` (`id` INT(11) NOT NULL AUTO_INCREMENT , `name` VARCHAR(100) NOT NULL , PRIMARY KEY (`id`)) ENGINE = InnoDB;
| id | name |
| -- | ---- |
In which I insert the following two rows:
INSERT INTO `test`(`name`) VALUES ('Oscar'), ('Alba')
| id | name |
| -- | ----- |
| 1 | Oscar |
| 2 | Alba |
Now, I want to update the existing rows and create new ones:
INSERT INTO `test` (`id`, `name`) VALUES (1, 'Oscar'), (2, 'Nadia'), ('', 'Pedro') ON DUPLICATE KEY UPDATE `id` = VALUES (`id`), `name` = VALUES (`name`)
| id | name |
| -- | ----- |
| 1 | Oscar |
| 2 | Nadia |
| 3 | Pedro |
If I update existing rows again and create new ones, this is what happens:
INSERT INTO `test` (`id`, `name`) VALUES (1, 'Oscar'), (2, 'Nadia'), (3, 'Lucas'), ('', 'Maria'), ('', 'Sergio') ON DUPLICATE KEY UPDATE `id` = VALUES (`id`), `name` = VALUES (`name`)
| id | name |
| -- | ------ |
| 1 | Oscar |
| 2 | Nadia |
| 3 | Lucas |
| 6 | Maria |
| 7 | Sergio |
There is a jump in the auto increment id. I don't know why this happens. I would like to know if there is any way to avoid this.
Related
I have a table people, a table departments and a table addresses.
I am wondering if there is a way in mySql to have some of the results as JSON rather than added rows or tables.
For this example:
people:
+--------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| id | int | YES | | NULL | |
| name | varchar(50) | YES | | NULL | |
| departmentId | int | YES | | NULL | |
+--------------+-------------+------+-----+---------+-------+
addresses
+-------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+-------+
| id | int | YES | | NULL | |
| personId | int | YES | | NULL | |
| fullAddress | varchar(125) | YES | | NULL | |
+-------------+--------------+------+-----+---------+-------+
departments;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int | YES | | NULL | |
| name | varchar(50) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
Note: to create tables, run:
create table people ( id INT(11), name varchar(50), departmentId INT(11));
create table departments ( id INT(11), name varchar(50));
create table addresses ( id INT(11), personId INT(11), fullAddress varchar(125));
So a person can be linked to one specific department, but can have several addresses.
insert into departments values (0, 'sales');
insert into departments values (1, 'dev');
insert into people values (0, 'Chiara', 0);
insert into people values (1, 'Geoff', 0);
insert into people values (2, 'Tony', 1);
insert into people values (3, 'Raphael', 1);
insert into addresses values (0, 0, 'Street 0');
insert into addresses values (1, 0, 'Street 1');
insert into addresses values (2, 1, 'Street 2');
insert into addresses values (3, 1, 'Street 3');
insert into addresses values (4, 2, 'Street 4');
insert into addresses values (5, 2, 'Street 5');
insert into addresses values (6, 2, 'Street 6');
insert into addresses values (7, 2, 'Street 7');
insert into addresses values (8, 3, 'Street 8');
insert into addresses values (9, 3, 'Street 9');
QUESTION 1: JOIN 1:n as array rather than as multiple results
I can easily do a select and get all records in people:
select * from people left join addresses on people.id = addresses.personId where people.id = 2;
The result of this is:
+------+------+--------------+------+----------+-------------+
| id | name | departmentId | id | personId | fullAddress |
+------+------+--------------+------+----------+-------------+
| 2 | Tony | 1 | 7 | 2 | Street 7 |
| 2 | Tony | 1 | 6 | 2 | Street 6 |
| 2 | Tony | 1 | 5 | 2 | Street 5 |
| 2 | Tony | 1 | 4 | 2 | Street 4 |
+------+------+--------------+------+----------+-------------+
Is there an easy, straightforward way to have only ONE record as result (the contact ID 2) and have the addresses in an ARRAY (or, a JSON containing the addresses) instead?
QUESTION 2: JOIN 1:1 as a sub-object rather than adding columns
I can easily get the department information by using joins:
select * from people left join departments on departments.id = people.departmentId where people.id = 2 ;
Result:
+------+------+--------------+------+------+
| id | name | departmentId | id | name |
+------+------+--------------+------+------+
| 2 | Tony | 1 | 1 | dev |
+------+------+--------------+------+------+
However, what if I wanted a result like this instead:
+------+------+--------------+----------------------+
| id | name | departmentId | departmentIdRecord |
+------+------+--------------+----------------------+
| 2 | Tony | 1 | { id: 1, name: "dev"}|
+------+------+--------------+----------------------+
Basically having the departmentIdRecord column as a JSON containing the department record.
Is this even possible with MySql?
I have a table
table location_category {
id,
location_id,
category_id,
is_primary
}
What I want is to set a UNIQUE constraint for the combination location_id and is_primary.
I get that using this will make a multi column UNIQUE constraint
ALTER TABLE `votes` ADD UNIQUE `unique_index`(`location_id`, `is_primary`);
But my concern is that we can have multiple categories for a location but only set 1 category as primary.
For example:
| id | location_id | category_id | is_primary |
| 1 | 1 | 1 | 0 |
| 2 | 1 | 2 | 0 |
| 3 | 1 | 3 | 1 |
| 4 | 1 | 4 | 0 |
Will this violate the UNIQUE contraint? Since I have multiple instances of location_id = 1 and is_primary = 0?
Just trying to figure this out. Thank you for helping.
There is no need to change anything, UNIQUE allows multiple NULL values
CREATE TABLE `votes` (
`id` INTEGER,
`location_id` INTEGER,
`category_id` INTEGER,
`is_primary` INTEGER
);
ALTER TABLE `votes` ADD UNIQUE `unique_index`(`location_id`, `is_primary`);
INSERT INTO `votes`
(`id`, `location_id`, `category_id`, `is_primary`)
VALUES
('1', '1', '1', NULL),
('2', '1', '2', NULL),
('3', '1', '3', '1'),
('4', '1', '4', NULL);
SELECT * from `votes`
id | location_id | category_id | is_primary
-: | ----------: | ----------: | ---------:
1 | 1 | 1 | null
2 | 1 | 2 | null
3 | 1 | 3 | 1
4 | 1 | 4 | null
db<>fiddle here
So you can only have one location with is primary 1
In MySQL, when CREATE TABLE, is there a way for MySQL to implicitly create a column (i.e. a column not explicitly declared in CREATE TABLE command) as the primary key of the table?
Thanks.
No, the PRIMARY KEY needs to be defined on the table.
You may be thinking about this, which applies to InnoDB engine:
If the table has no PRIMARY KEY or suitable UNIQUE index, InnoDB
internally generates a hidden clustered index named GEN_CLUST_INDEX on
a synthetic column containing row ID values. The rows are ordered by
the ID that InnoDB assigns to the rows in such a table. The row ID is
a 6-byte field that increases monotonically as new rows are inserted.
Thus, the rows ordered by the row ID are physically in insertion
order.
Below is an example that shows this index's creation for a table with no PRIMARY KEY and no UNIQUE column.
# Create the table
create table test.check_table (id int, description varchar(10)) ENGINE = INNODB;
# Verify that there is no primary or unique column
desc test.check_table;
+-------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| description | varchar(10) | YES | | NULL | |
+-------------+-------------+------+-----+---------+-------+
# Insert some values
insert into test.check_table values(1, 'value-1');
insert into test.check_table values(2, 'value-2');
insert into test.check_table values(null, 'value-3');
insert into test.check_table values(4, null);
insert into test.check_table values(1, 'value-1');
# Verify table
select * from test.check_table;
+------+-------------+
| id | description |
+------+-------------+
| 1 | value-1 |
| 2 | value-2 |
| NULL | value-3 |
| 4 | NULL |
| 1 | value-1 |
+------+-------------+
# Verify that the GEN_CLUST_INDEX index is auto-created.
select * from INFORMATION_SCHEMA.INNODB_INDEX_STATS where TABLE_SCHEMA='test' and TABLE_NAME = 'check_table';
+--------------+-------------+-----------------+--------+--------------+-------------------+------------------+
| table_schema | table_name | index_name | fields | rows_per_key | index_total_pages | index_leaf_pages |
+--------------+-------------+-----------------+--------+--------------+-------------------+------------------+
| test | check_table | GEN_CLUST_INDEX | 1 | 5 | 1 | 1 |
+--------------+-------------+-----------------+--------+--------------+-------------------+------------------+
# Duplicate rows are still allowed (Primary Key constraints not enforced)
insert into test.check_table values(1, 'value-1');
select * from test.check_table;
+------+-------------+
| id | description |
+------+-------------+
| 1 | value-1 |
| 2 | value-2 |
| NULL | value-3 |
| 4 | NULL |
| 1 | value-1 |
| 5 | value-5 |
| 1 | value-1 |
+------+-------------+
To contrast, a table with a PRIMARY KEY specified creates an index with name PRIMARY.
# Create another table
create table test.check_table_2 (id int, description varchar(10), PRIMARY KEY(id)) ENGINE = INNODB;
# Verify primary key column
desc check_table_2;
+-------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | 0 | |
| description | varchar(10) | YES | | NULL | |
+-------------+-------------+------+-----+---------+-------+
# Verify index
select * from INFORMATION_SCHEMA.INNODB_INDEX_STATS where TABLE_SCHEMA='test' and TABLE_NAME = 'check_table_2';
+--------------+---------------+------------+--------+--------------+-------------------+------------------+
| table_schema | table_name | index_name | fields | rows_per_key | index_total_pages | index_leaf_pages |
+--------------+---------------+------------+--------+--------------+-------------------+------------------+
| test | check_table_2 | PRIMARY | 1 | 0 | 1 | 1 |
+--------------+---------------+------------+--------+--------------+-------------------+------------------+
# Primary key is enforced
insert into check_table_2 values(1,'value-1');
OK
insert into check_table_2 values(1,'value-1');
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
--
-- Table structure for table `emp`
--
CREATE TABLE `emp` (
`Emp_id` int(11) NOT NULL,
`Name` varchar(30) DEFAULT NULL,
`Sup_id` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Dumping data for table `emp`
--
INSERT INTO `emp` (`Emp_id`, `Name`, `Sup_id`) VALUES
(1, 'Mark 18', NULL),
(2, 'Iron Man', 1),
(3, 'Hulk', NULL),
(4, 'Ant-Man', 2);
--
-- Indexes for dumped tables
--
--
-- Indexes for table `emp`
--
ALTER TABLE `emp`
ADD PRIMARY KEY (`Emp_id`),
ADD KEY `Sup_id` (`Sup_id`);
--
this is my table DESC
i want output as this
like in case of iron man
iwant out put like this
2 Iron Man Mark 18
this means it want to check the Emp_id and Dispaly correspond name of Emp _id
DESc Stucture
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| Emp_id | int(11) | NO | PRI | NULL | |
| Name | varchar(30) | YES | | NULL | |
| Sup_id | int(11) | YES | MUL | NULL | |
+--------+-------------+------+-----+---------+-------+
Values Inside Table
+--------+----------+--------+
| Emp_id | Name | Sup_id |
+--------+----------+--------+
| 1 | Mark 18 | NULL |
| 2 | Iron Man | 1 |
| 3 | Hulk | NULL |
| 4 | Ant-Man | 2 |
+--------+----------+--------+
Output format i want
+--------+----------+--------+
| Emp_id | Name | Sup_id |
+--------+----------+--------+
| 1 | Mark 18 |NULL |
| 2 | Iron Man |MArk 18 |
| 3 | Hulk | NULL |
| 4 | Ant-Man |Iron Man|
+--------+----------+--------+
Just LEFT JOIN table on itself:
SELECT e.Emp_id, e.Name, es.Name AS Sup_name FROM emp AS e LEFT JOIN emp AS es ON e.Sup_id = es.Emp_id
I want to make it in such a way that I get:
Main | Column I want to reset on new main value
1 | 100
1 | 101
1 | 102
1 | 103
1 | 104
2 | 100
2 | 101
You can use MyIsam engine to achieve this -
CREATE TABLE table1(
id1 INT(11) NOT NULL,
id2 INT(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id1, id2)
);
INSERT INTO table1 VALUES (1, NULL);
INSERT INTO table1 VALUES (1, NULL);
INSERT INTO table1 VALUES (2, NULL);
INSERT INTO table1 VALUES (2, NULL);
SELECT * FROM table1;
+-----+-----+
| id1 | id2 |
+-----+-----+
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
| 2 | 2 |
+-----+-----+