SQL how to create a table with a unique key? - mysql

Create a courses table with this definition (try using a multi-line SQL statement):
+---------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+---------------------+------+-----+---------+----------------+
| id | int(3) unsigned | NO | PRI | NULL | auto_increment |
| title | varchar(255) | NO | UNI | NULL | |
| credits | tinyint(2) unsigned | NO | | 1 | |
I keep getting an error when trying to create the table, this is what I have:
CREATE TABLE courses
(
id int(3) unsigned NOT NULL AUTO_INCREMENT,
title varchar(255) NOT NULL UNIQUE,
credits tinyint(2) unsigned NOT NULL DEFAULT 1;

Error:
Incorrect table definition; there can be only one auto column and it must be defined as a key
Correct SQL sentence:
CREATE TABLE courses (
id int(3) unsigned primary key NOT NULL AUTO_INCREMENT,
title varchar(255) NOT NULL UNIQUE,
credits tinyint(2) unsigned NOT NULL DEFAULT 1);
Your sentence loses primary key.

Two mistakes:
The auto_increment column must be a primary key in MySQL.
You need to end the SQL sentence with a ).
This SQL works:
CREATE TABLE courses (
id int(3) unsigned primary key NOT NULL AUTO_INCREMENT,
title varchar(255) NOT NULL UNIQUE,
credits tinyint(2) unsigned NOT NULL DEFAULT 1
);

Related

indexes and constraints not created in CREATE TABLE statement

I am using MySQL/MariaDB, and I create an employees table:
CREATE TABLE employees(
id INT AUTO_INCREMENT,
name VARCHAR(40) NOT NULL,
description VARCHAR(50) DEFAULT 'No Description',
random_assignment_id INT UNIQUE,
birth_date DATE,
salary DECIMAL(5,2),
supervisor_id INT,
branch_id INT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT random_assignment_check CHECK (LENGTH(random_assignment_id) = 5),
INDEX(random_assignment_id, supervisor_id, branch_id),
PRIMARY KEY(id)
)
Then I confirm the table is created as expected:
SHOW CREATE TABLE employees\G;
*************************** 1. row ***************************
Table: employees
Create Table: CREATE TABLE `employees` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(40) NOT NULL,
`description` varchar(50) DEFAULT 'No Description',
`random_assignment_id` int(11) DEFAULT NULL,
`birth_date` date DEFAULT NULL,
`salary` decimal(5,2) DEFAULT NULL,
`supervisor_id` int(11) DEFAULT NULL,
`branch_id` int(11) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `random_assignment_id` (`random_assignment_id`),
KEY `random_assignment_id_2` (`random_assignment_id`,`supervisor_id`,`branch_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.01 sec)
I don't see the random_assignment_check constraint listed, and I expected it to index random_assignment_id, supervisor_id and branch_id, but it does not:
DESCRIBE employees;
+----------------------+--------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------------+--------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(40) | NO | | NULL | |
| description | varchar(50) | YES | | No Description | |
| random_assignment_id | int(11) | YES | UNI | NULL | |
| birth_date | date | YES | | NULL | |
| salary | decimal(5,2) | YES | | NULL | |
| supervisor_id | int(11) | YES | | NULL | |
| branch_id | int(11) | NO | | NULL | |
| created_at | timestamp | NO | | CURRENT_TIMESTAMP | |
| updated_at | timestamp | NO | | CURRENT_TIMESTAMP | |
+----------------------+--------------+------+-----+-------------------+----------------+
There are no MUL flags under key.
Note that I read MariaDB now supports Constraints; according to homebrew, I am using:
brew info mariadb
mariadb: stable 10.3.12 (bottled)
Drop-in replacement for MySQL
What am I doing wrong?
MySQL treats KEY as a synonym for INDEX. Your index INDEX(random_assignment_id, supervisor_id, branch_id) became KEY random_assignment_id_2 (random_assignment_id,supervisor_id,branch_id). The index name was generated by MySQL, but logically they're the same index.
When I tested your CREATE TABLE statement and then use DESC to display it, I also see no MUL indicators. This fits the documentation:
If Key is MUL, the column is the first column of a nonunique index in which multiple occurrences of a given value are permitted within the column.
So in your output, the Key field for random_assignment_id is UNI because it's a unique key, in addition to part of a multi-column key.
MySQL doesn't support CHECK constraints. It parses them, then ignores them. They are not stored with your table, and subsequently using SHOW CREATE TABLE doesn't show them.
MariaDB has implemented CHECK constraints in 10.2.1 according to https://mariadb.com/kb/en/library/constraint/#check-constraints (I don't use MariaDB, so I'll trust their doc).
It's not clear from your question if you tested your CHECK constraint on MySQL Community Edition or MariaDB. CHECK constraint will not be saved on MySQL, and on MariaDB it seems okay per the doc, but I have never tested it.
We should all stop thinking of MariaDB a drop-in replacement for MySQL. The two products have been diverging for nearly 10 years, and they can no longer be assumed to be compatible.

Why won't my SQL table creation work in Codio?

I am trying to complete my homework but am getting an error message saying that the table I'm creating doesn't match what is expected to be input. Here is what the table is supposed to contain:
+-----------+-----------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-----------------+------+-----+---------+----------------+
| id | int(3) unsigned | NO | PRI | NULL | auto_increment |
| room_num | int(4) unsigned | NO | UNI | NULL | |
| course_id | int(3) unsigned | YES | MUL | NULL | |
+-----------+-----------------+------+-----+---------+----------------+
The code I am entering to try and achieve this is:
CREATE TABLE college.classrooms (
id INT(3) UNSIGNED NOT NULL AUTO_INCREMENT,
room_num INT(4) UNSIGNED NOT NULL UNIQUE KEY,
course_id INT(3) UNSIGNED DEFAULT NULL,
PRIMARY KEY (id),
FOREIGN KEY (course_id) REFERENCES college.courses(id)
) AUTO_INCREMENT = 1;
My school uses Codio and it auto checks the table to see if it's correct and that is the error message I'm getting:
[Error]: Create a 'classrooms' table with the requested structure. Reset the database and try again
What am I missing from my code to make this work? I've already created the table it is referencing (courses).
Is it probably failing on the FOREIGN KEY REFERENCES context? You are trying to create a table that is EXPECTING the course_id to be found in a secondary table "college.courses". If the college.courses table is not created yet, this table could never reference it.
Make sure the COURSES table is created FIRST
CREATE TABLE classrooms
(
id INT(3) unsigned primary key NOT NULL AUTO_INCREMENT,
room_num INT(4) unsigned NOT NULL UNIQUE,
course_id INT(3) unsigned DEFAULT NULL,
FOREIGN KEY (course_id) REFERENCES college.courses(id)
)
AUTO_INCREMENT = 1;

How ro reduce the mysql query running time

This is my query running in one page of my site
SELECT
DISTINCT b.CruisePortID,
b.SailingDates,
b.CruisePortID,
b.ArriveTime,
b.DepartTime,
b.PortName,
b.DayNumber
FROM
cruise_itineraries a,
cruise_itinerary_days b,
cruise_ports c
WHERE
a.ID = b.CruiseItineraryID
AND a.CruisePortID = c.ID
AND a.ID = '352905'
AND b.CruisePortID != 0
GROUP BY b.DayNumber;
while running this query in phpmy admin its take 3.20 sec because of cruise_itineraries had more 300 000 records
I tried indexing also after indexing it show 2.92 sec. Is any possible to reduced query time less .10 sec. Its help my site performance
here details
CREATE TABLE IF NOT EXISTS `cruise_itineraries` (
`cl` int(11) NOT NULL,
`ID` bigint(20) NOT NULL,
`Description` varchar(500) NOT NULL,
`SailingPlanID` varchar(100) NOT NULL,
`VendorID` varchar(100) NOT NULL,
`VendorName` varchar(100) NOT NULL,
`ShipID` varchar(100) NOT NULL,
`ShipName` varchar(100) NOT NULL,
`Duration` int(11) NOT NULL,
`DestinationID` varchar(100) NOT NULL,
`Date` datetime NOT NULL,
`CruisePortID` varchar(100) NOT NULL,
`TradeRestriction` varchar(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `cruise_itinerary_days` (
`cld` int(11) NOT NULL,
`CruiseItineraryID` varchar(100) NOT NULL,
`SailingDates` datetime NOT NULL,
`VendorID` int(11) NOT NULL,
`VendorName` varchar(100) NOT NULL,
`ShipID` int(11) NOT NULL,
`ShipName` varchar(100) NOT NULL,
`SailingPlanID` int(11) NOT NULL,
`PlanName` varchar(100) NOT NULL,
`DayNumber` bigint(20) NOT NULL,
`PortName` varchar(100) NOT NULL,
`CruisePortID` varchar(100) NOT NULL,
`ArriveTime` varchar(100) NOT NULL,
`DepartTime` varchar(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `cruise_ports` (
`cp` int(11) NOT NULL,
`ID` varchar(100) NOT NULL,
`Name` varchar(100) NOT NULL,
`Description` varchar(1000) NOT NULL,
`NearestAirportCode` varchar(100) NOT NULL,
`UNCode` varchar(100) NOT NULL,
`Address` varchar(500) NOT NULL,
`City` varchar(100) NOT NULL,
`StateCode` varchar(100) NOT NULL,
`CountryCode` varchar(100) NOT NULL,
`PostalCode` varchar(100) NOT NULL,
`Phone` varchar(50) NOT NULL,
`Fax` varchar(100) NOT NULL,
`Directions` varchar(1000) NOT NULL,
`Content` varchar(1000) NOT NULL,
`HomePageURL` varchar(100) NOT NULL,
`Longitude` varchar(100) NOT NULL,
`Latitude` varchar(500) NOT NULL,
`CarnivalID` varchar(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ALTER TABLE `cruise_itineraries`
ADD PRIMARY KEY (`cl`),
ADD KEY `ID_2` (`ID`);
ALTER TABLE `cruise_itineraries`
ADD PRIMARY KEY (`cl`),
ADD KEY `ID_2` (`ID`);
ALTER TABLE `cruise_itinerary_days`
ADD PRIMARY KEY (`cld`);
ALTER TABLE `cruise_ports`
ADD PRIMARY KEY (`cp`);
ALTER TABLE `cruise_itineraries`
MODIFY `cl` int(11) NOT NULL AUTO_INCREMENT;
ALTER TABLE `cruise_itinerary_days`
MODIFY `cld` int(11) NOT NULL AUTO_INCREMENT;
ALTER TABLE `cruise_ports`
MODIFY `cp` int(11) NOT NULL AUTO_INCREMENT;
EXPLAIN RESULT:
+----+-------------+-------+------+---------------+------+---------+-------+---------+--------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+-------+---------+--------------------------------------------------------+
| 1 | SIMPLE | a | ref | ID_2 | ID_2 | 8 | const | 1 | Using index condition; Using temporary; Using filesort |
| 1 | SIMPLE | c | ALL | NULL | NULL | NULL | NULL | 3267 | Using where; Using join buffer (Block Nested Loop) |
| 1 | SIMPLE | b | ALL | NULL | NULL | NULL | NULL | 2008191 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+-------+------+---------------+------+---------+-------+---------+--------------------------------------------------------+
+----+-------------+-------+------+------------------------------------+------------------------------------+---------+-------+------+--------------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+------------------------------------+------------------------------------+---------+-------+------+--------------------------------------------------------------+
| 1 | SIMPLE | b | ref | Idx_CruiseItineraryID_CruisePortID | Idx_CruiseItineraryID_CruisePortID | 9 | const | 12 | Using index condition; Using temporary; Using filesort |
| 1 | SIMPLE | a | ref | ID_2 | ID_2 | 8 | const | 1 | Distinct |
| 1 | SIMPLE | c | ALL | NULL | NULL | NULL | NULL | 3267 | Using where; Distinct; Using join buffer (Block Nested Loop) |
+----+-------------+-------+------+------------------------------------+------------------------------------+---------+-------+------+--------------------------------------------------------------+
First I would like to state that try to avoid IMPLICIT MySQL JOINS.
Use INNER JOINS instead.
I personally think the INNER JOIN is better, because it is more
readable. It shows better the relations between the table. You got
those relations in the join, and you do the filtering in the WHERE
clause. This separation makes the query more readable.
The faults I've found:
The data type of cruise_itineraries.ID is BIGINT and the data type of cruise_itinerary_days.CruiseItineraryID is varchar. But you are matching them in a query. So it will run slow no matter if you use index on cruise_itinerary_days.CruiseItineraryID in cruise_itinerary_days table.
Change the data type of cruise_itinerary_days.CruiseItineraryID to BIGINT.
ALTER TABLE cruise_itinerary_days MODIFY CruiseItineraryID BIGINT;
Next you have to create a composite index on cruise_itinerary_days table based on your query.
ALTER TABLE cruise_itinerary_days ADD INDEX Idx_CruiseItineraryID_CruisePortID (CruiseItineraryID, CruisePortID)`
Now create an index in cruise_ports table on cruise_ports.ID field.
ALTER TABLE cruise_ports ADD INDEX Idx_cruise_ports_ID (ID);
And finally the query is formulated using INNER JOINS since I've stated reasons above behind this choice:
SELECT
DISTINCT b.CruisePortID,
b.SailingDates,
b.CruisePortID,
b.ArriveTime,
b.DepartTime,
b.PortName,
b.DayNumber
FROM cruise_itineraries a
INNER JOIN cruise_itinerary_days b ON a.ID = b.CruiseItineraryID
INNER JOIN cruise_ports c ON a.CruisePortID = c.ID
WHERE a.ID = 352905
AND b.CruisePortID != 0
GROUP BY b.DayNumber;

How do I auto create student id number in mysql?

I'm very new to MySQL. I created a table for student.
CREATE TABLE student(
studentId int(10) NOT NULL,
firstName VARCHAR(100) NOT NULL,
lastName VARCHAR(100) NOT NULL,
birthday VARCHAR(12) NOT NULL,
gender VARCHAR(7),
course_name VARCHAR(150) NOT NULL,
PRIMARY KEY(studentId )
);
I thought it would be nice studentId auto create by the system. And I don't know how to do this. This may be a simple question to you guys. Please help me with this.
Thanks.
The AUTO_INCREMENT attribute can be used to generate a unique identity for new rows:
Ex -
CREATE TABLE animals (
id INT NOT NULL AUTO_INCREMENT,
name CHAR(30) NOT NULL,
PRIMARY KEY (id)
);
When inserting data into table you don't have input data to id.
INSERT INTO animals (name) VALUES
('dog'),('cat'),('penguin'),
('lax'),('whale'),('ostrich');
Which returns -
+----+---------+
| id | name |
+----+---------+
| 1 | dog |
| 2 | cat |
| 3 | penguin |
| 4 | lax |
| 5 | whale |
| 6 | ostrich |
+----+---------+
Answer to your question -
CREATE TABLE student(
studentId int(10) NOT NULL AUTO_INCREMENT,
firstName VARCHAR(100) NOT NULL,
lastName VARCHAR(100) NOT NULL,
birthday VARCHAR(12) NOT NULL,
gender VARCHAR(7),
course_name VARCHAR(150) NOT NULL,
PRIMARY KEY(studentId )
);
For more information refer here.

Column is not autoincrementing in mysql

When I insert a new row the treeId column is always 1.
The treeId column is not included in the insert statement.
What could be causing it to not increment?
My table code is
CREATE TABLE `users` (
`uuid` varchar(36) NOT NULL,
`parentUuid` varchar(36) DEFAULT NULL,
`treePath` text,
`treeId` int(11) NOT NULL AUTO_INCREMENT,
`firstName` varchar(50) NOT NULL,
`lastName` varchar(50) NOT NULL,
`email` varchar(255) NOT NULL,
`salt` varchar(40) NOT NULL,
`password` varchar(40) NOT NULL,
`state` enum('subscribed','registered','banned') NOT NULL,
`dobMonth` int(11) DEFAULT NULL,
`dobYear` int(11) DEFAULT NULL,
`dateSubscribed` datetime DEFAULT NULL,
`dateRegistered` datetime DEFAULT NULL,
`gender` enum('unspecified','male','female') NOT NULL DEFAULT 'unspecified',
`dd` float DEFAULT '0',
`mainRegion` int(11) DEFAULT NULL,
PRIMARY KEY (`uuid`,`treeId`),
KEY `parentid` (`parentUuid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
if you want it to auto-increment don't specify the treeId field in your insert.
Found the answer (Documentation)
For MyISAM and BDB tables you can specify AUTO_INCREMENT on a
secondary column in a multiple-column index. In this case, the
generated value for the AUTO_INCREMENT column is calculated as
MAX(auto_increment_column) + 1 WHERE prefix=given-prefix. This is
useful when you want to put data into ordered groups.
CREATE TABLE animals (
grp ENUM('fish','mammal','bird') NOT NULL,
id MEDIUMINT NOT NULL AUTO_INCREMENT,
name CHAR(30) NOT NULL,
PRIMARY KEY (grp,id)
) ENGINE=MyISAM;
INSERT INTO animals (grp,name) VALUES
('mammal','dog'),('mammal','cat'),
('bird','penguin'),('fish','lax'),('mammal','whale'),
('bird','ostrich');
SELECT * FROM animals ORDER BY grp,id;
Which returns:
+--------+----+---------+
| grp | id | name |
+--------+----+---------+
| fish | 1 | lax |
| mammal | 1 | dog |
| mammal | 2 | cat |
| mammal | 3 | whale |
| bird | 1 | penguin |
| bird | 2 | ostrich |
So because I had a joint key on uuid (which is always unique) and on treeId (which is the auto-increment) then it was creating a new increment group each time.