IMPORTANT: for this lesson you need your database, where you have permissions to use the data definition commands.
By data definition, we mean the creation of the storage structures: creating databases, creating tables, indexes, procedures, etc. Also deleting and modifying them.
By data manipulation, we mean everything that has to do with the content of these structures: querying, inserting rows, deleting rows, modifying data...
As a summary of what is going to be developed from here on, we will see:
CREATE TABLE tableName (columns and constraints)
create a table defining its columns and data types, and with the necessary restrictions (primary key, foreign, non-null, etc.).
the tables persist in the schema until they are deleted.
DROP TABLE tableName
drop a table from the schema (any rows in it also disappear)
INSERT INTO tableName VALUES (values)
add a row to the table with corresponding values in each row component
INSERT INTO tableName querySelect
variant of the previous one that gets the values from a query to the same or another database
DELETE FROM tableName [WHERE condition].
delete one or more rows, depending on the conditions we require
UPDATE tableName SET assignments [WHERE conditions]
modify specific values in one or several rows, depending on the conditions we require.
The definition of tables is the first step in the building of a database. The set of table descriptions makes up the schema of the database and it is representing a specific information system
Supposing we want to implement a relational database schema for teachers, subjects (just a listing of teachers and subjects, without relationship between them). Firstly, we must decide the attributes of each table and the data type of these attributes:
PROFESORES
DNI: varchar(10),
nombre: varchar(40),
categoria: char(4),
ingreso: date
ASIGNATURAS
codigo: char(5),
descripcion: varchar(35),
creditos: decimal(3,1),
creditosp: decimal(3,1)
Besides, in order to fulfill the restrictions of the relational model, we must choose the appropriate primary keys: DNI for profesores and código for asignaturas. Obviously, the way we build these tables is our decision as database designers. Maybe, in other situation, the definition of the tables could be different.
The statement CREATE TABLE allows us to create each table we need for our database:
CREATE TABLE nameTable( {listColumns} [,{restrictions}] )
The list of columns, in its simplest form, is a set of expressions (as many as columns we want, and separated with commans) like:
column dataType[,column dataType[, ...]]
All the types managed by MySQL, being most of them common between database engines except slight differences, can be found in https://mariadb.com/kb/en/data-types/.
Restrictions are rules, usually established in the moment of the creation of a table, to guarantee the integrity of data.
Basically, restrictions oblide to follow certain rules when a row is inserted, deleted or updated, and the operation will be performed only if the restrictions of the table are fulfilled.
We have the following types of restrictions for data integrity:
NOT NULL: specifies that the column must have a value.
PRIMARY KEY: identifies each row uniquely using one or more columns, the columns that are part of a primary key can not have null value.
FOREIGN KEY: establishes a relation between one/more column(s) of a table and another column(s) of the referenced table, being this/these last column(s) the PRIMARY KEY.
CHECK: specifies a condition that must be evaluated as "true" .
From these restrictions, only the one referring the primary key, containing as many columns as necessary, will be used:
PRIMARY KEY (column[,column[, ...]])
The following sentences create PROFESORES and ASIGNATURAS tables
create table profesores (
DNI varchar(10),
nombre varchar(40),
categoria char(4),
ingreso date,
primary key (DNI));
create table asignaturas (
codigo char(5),
descripcion varchar(35),
creditos decimal(3,1),
creditosp decimal(3,1),
primary key (codigo));
create table imparte (
dni varchar(10),
asignatura char(5),
primary key (dni,asignatura),
foreign key (dni) references profesores (DNI),
foreign key (asignatura) references asignaturas (codigo));
What was shown in previous section is the standard of SQL and its syntax is admitted by most of the commercial DBMS
However, MySQL is a peculiar product that offers various storing and management options in order to offer alternatives to improve performance and data integrity. In particular, we can choose between tables MyISAM and InnoDB.
If we want to keep referential integrity between our tables is necessary to specify the engine InnoDB. In a standard instalation of MySQL, if we don´t say anything, the creation of the table is done using MyISAM and it has a very important effect: if we define foreign keys, the system ignores them and does not review the referential integrity.
Eso nos obligaría a concretar el motor de almacenamiento tanto en las tablas con claves ajenas como en las referenciadas:
create table profesores (...) engine=innodb;
create table asignaturas (...) engine=innodb;
create table imparte (...) engine=innodb;
Al igual que se va a comentar a continuación, tenemos varias posibilidades de gestión del almacenamiento, algunas de ellas directamente relacionadas con la integridad referencial.
No obstante, y adelantándonos, si no especificamos nada MariaDB utiliza el motor innodb, y no hace falta añadir la cláusula engine=innodb a la creación de tablas, como sí exige MySQL. A partir de ahora, asumimos que trabajaremos con MariaBD y no incluiremos esa especificación.
If we want to delete a table, we must order it to the DBMS with the statement DROP TABLE:
DROP TABLE nombreTabla
When using this statement, the data or rows that the table contains are also deleted. It is possible to delete and create a table as many times as we want.
Delete the table asignaturas
drop table asignaturas
Remember that executing DESC nombreTabla or DESCRIBE nombreTabla, all the information related to the columns of the table must be shown, the internal order of them in the table, and their data types.
In the moment of creating a restriction, apart from specifying the rules that must be fulfilled, we can give it a name. To establish the names of the restrictions, the following agreement is used: being descriptive names, starting with, for example,
PK_ in case of Primary Key
FK_ in case of Foreign Key
C_ in case of CHECK
create table imparte (
dni varchar(10),
asignatura char(5),
constraint PK_imparte primary key (dni,asignatura),
constraint FK_imparte_profesores foreign key (dni)
references profesores (dni),
constraint FK_imparte_asignaturas foreign key (asignatura)
references asignaturas (codigo)) engine=innodb;
Obviously, this agreement is only a recommendation.
We are not going to study in depth the name of the restrictions nor the syntax to create them, but we need to know that if we don't assign them a name, the DBMS will do.
In order to insert new data in a database we will use the statement INSERT of SQL. With the syntax shown next we will be able to add new data in each table of a database. At first, we will see the minumum statement syntax, formed by INTO and VALUES clauses.
INSERT INTO nombreTabla VALUES ( listaExpresiones )
Add a new teacher with the following data:
dni 55555555
nombre PATRICIO MARTÍNEZ,
categoría TU
fecha de incorporación 01/01/2000
insert into profesores values ('55555555','PATRICIO MARTINEZ','TU','2000-1-1')
Add a new teacher with the following data:
dni 66
nombre ERNESTO PEREZ
categoría ASO
fecha de incorporación 01/01/1985
insert into profesores values ('66','ERNESTO PEREZ','ASO','1985-1-1');
The result of the statement INSERT, will always be the number of added rows, in case of a properly execution. For the cases in the statement breaking any restriction of the database, and therefore, the execution is not correct, the result will indicate which restriction has been broken. The DBMS, each time we add a new data in a table, is in charge of checking the active restrictions, in our case, the primary keys, that as we already know, do not admit nulls or duplicates.
Add a new teacher with the following data:
dni 66
nombre JUAN JUANÍTEZ
categoría XXX
fecha de incorporación 01/01/1905
insert into profesores values ('66','JUAN JUANITEZ','XXX','1905-1-1')
Sometimes we do not want or we can't have values for all the columns, or we want to use a different order that the one defined in the table. Specifying a list of columns before the VALUES allows to indicate the system which columns will have a value and which is this value.
Add a new teacher with DNI 88888888 and nombre ARMANDO SUÁREZ
insert into profesores (dni, nombre)
values ('88888888', 'ARMANDO SUAREZ');
The system will try to assign to the non indicate columns a default value, or in case it was defined, a null value.
It is advisable to indicate always the columns with values, being all of them or not part of the table. The reason are:
There is no need to take into account if we are giving values to all of the columns or only some of them in the INSERT statement.
If the structure of the table is modified by any reason, for example new columns are added, and we usually do not indicate the name of the columns, the statement won't work anymore
There exists the possibility of using NULL value, when the column admits it. Although it is usually simplified as "absence of value", remember that NULL means unkown data (we don`t know if it has a value and in case it has some we don't know it). In any case, if the column admits them it can be specified in the INSERT sentence.
insert into profesores (dni,nombre,categoría,ingreso)
values ('99999999','MARIA MIRO', NULL, NULL);
Equally, a change in the order of the columns must correspond with the exact position of the value to be assigned:
insert into profesores (categoria, dni, nombre)
values (NULL, '77','ANA FERNANDEZ');
Suppose that in the BD Ejemplo there exists a table called OPTATIVAS with the code and credits of the optative subjects.
We will create this table, choosing the code of the subject as primary key and adding the restriction that all the rows must have a value in the credits column.
create table optativas (
asignatura char (5),
creditos decimal(3,1) not null,
primary key (asignatura));
There exists the possibility to insert the result of a column instead of indicating a list of values to be inserted. This allows us to insert more than one row in a table in a unique operation, specifically, as many rows as tuples are returned in the SELECT statement.
INSERT INTO nombreTabla [ ( listaColumnas ) ] selectOrder
Suppose that all the subjects with less than 9 credits are optative. We need to insert the code of these subjects in the table OPTATIVAS. In this case, as we have the table ASIGNATURAS, we have to possible options. One option is performing the SELECT and introducing one by one the subjects using INSERT, copying the data of the rows obtained.
The other option is inserting the result of the SELECT in a unique operation in the table OPTATIVAS.
insert into optativas (asignatura, creditos)
select codigo, creditos
from asignaturas
where creditos < 9;
The result fo the SELECT statement must be coherent with the number of columns and the data types. The following statement will provoke compiling errors:
insert into optativas (asignatura) select codigo, creditos from asignaturas where creditos < 9;
insert into optativas (asignatura,creditos) select codigo from asignaturas where creditos < 9;
insert into optativas (asignatura,creditos) select dni,ingreso from profesores;
This case is different, because we need to assure that the rest of the columns allows this insertion. With this type of command, the database engine will assign null values to the remaining columns. A typical situation is that one of the omitted columns does not allow nulls and makes insertion impossible.
Check the definition of the OPTATIVAS table, and you will find the NOT NULL constraint on the credits column. The result will be an error message, the constraint prevents the insertion of rows to ensure the integrity of the data and, precisely, preventing null values to be put in that column.
insert into optativas (asignatura)
select codigo from asignaturas
where creditos < 9
Before starting, we need to clean the database:
drop table if exists optativas;
drop table if exists imparte;
drop table if exists profesores;
drop table if exists asignaturas;
create table profesores (
DNI varchar(10),
nombre varchar(40),
categoria char(4),
ingreso date,
primary key (DNI));
create table asignaturas (
codigo char(5),
descripcion varchar(35),
creditos decimal(3,1),
creditosp decimal(3,1),
primary key (codigo));
create table imparte (
dni varchar(10),
asignatura char(5),
primary key (dni,asignatura),
foreign key (dni) references profesores (dni),
foreign key (asignatura) references asignaturas (codigo));
insert into asignaturas (codigo, descripcion, creditos, creditosp) values ('HI', 'HISTORIA DE LA INFORMATICA', 4.5, NULL), ('FBD', 'FUNDAMENTOS DE LAS BASES DE DATOS', 6.0, 1.5), ('DGBD', 'DISEÑO Y GESTION DE BASES DE DATOS', 6.0, 3.0), ('PC', 'PROGRAMACION CONCURRENTE', 6.0, 1.5), ('FP', 'FUNDAMENTOS DE LA PROGRAMACION', 9.0, 4.5);
insert into profesores (dni, nombre, categoria, ingreso) values ('21111222','EVA GOMEZ','TEU','1993-10-01'), ('21222333','MANUEL PALOMAR','TEU','1989-06-16'), ('21333444','RAFAEL ROMERO','ASO6','1992-06-16');
insert into imparte (dni, asignatura) values ('21111222','FBD'), ('21111222','DGBD'), ('21333444','PC');
The DELETE sentece allows us to delete the rows of the table.
DELETE [FROM] nombreTabla [WHERE condición]
See what we have in the table now
select * from imparte;
Delete all the rows from IMPARTE table
delete from imparte;
Check again
select * from imparte;
Delete all subjects with less than 5 credits.
delete from asignaturas where creditos < 5;
In order to delete rows of various tables we need to execute as many DELETE statements as rows we want to delete.
(Note: in MySQL is possible to delete over various tables but it can be assure that other DBMS allows that also)
Before starting, we need to rebuild the database:
delete from imparte;
delete from profesores;
delete from asignaturas;
insert into asignaturas (codigo, descripcion, creditos, creditosp) values ('HI', 'HISTORIA DE LA INFORMATICA', 4.5, NULL), ('FBD', 'FUNDAMENTOS DE LAS BASES DE DATOS', 6.0, 1.5), ('DGBD', 'DISEÑO Y GESTION DE BASES DE DATOS', 6.0, 3.0), ('PC', 'PROGRAMACION CONCURRENTE', 6.0, 1.5), ('FP', 'FUNDAMENTOS DE LA PROGRAMACION', 9.0, 4.5);
insert into profesores (dni, nombre, categoria, ingreso) values ('21111222','EVA GOMEZ','TEU','1993-10-01'), ('21222333','MANUEL PALOMAR','TEU','1989-06-16'), ('21333444','RAFAEL ROMERO','ASO6','1992-06-16');
insert into imparte (dni, asignatura) values ('21111222','FBD'), ('21111222','DGBD'), ('21333444','PC');
The statement UPDATE will allow us to modify the information stored in a table.
UPDATE nombreTabla [aliasTabla]
SET { {columna=expresion | columna=subconsulta} | listaColumnas=subconsulta}
[WHERE condición]
It is not possible to modify more than one table in a single sentence. To modify the values of various tables it is necessary to perform as many UPDATE sentences as tables. (NOTE:the same as with delete ).
select codigo,creditos from asignaturas;
update asignaturas set creditos = 0;
And check again
select codigo,creditos from asignaturas;
When we want to modify more than one column, the list of columns with the new value will be indicated separated with commas:
Modify the credits of the subjects to 4, and the practical credits to 2
update asignaturas set creditos=4, creditosp=2;
In case a condition is indicated, only the rows that fulfill the condition/s will be updated:
Modify the date of "ingreso" to 1 de enero de 2003 only for those teachers with TEU category.
update profesores
set ingreso='01/01/2003'
where categoria = 'TEU';
There exists the possibility of modifying the information stored in a table assigning as new value/s the result of a query.
The result of the query can be assign to one single column or a list of columns. In the first case, the SELECT statement will only return one value that must match with the data type of the column being assigned.
It is important to assure that the subselect returns only one value and this value matches with the expected data type.
update imparte
set asignatura='BDA',
dni = (select dni from profesores)
where asignatura like '%BD%';
ERROR:
the subquery returns more than one row
It is important to understand that every product, depending on its objectives, is closer or more distant to the SQL standard. For example, in MySQL, it is possible to perform deletes and updatings of the rows of various tables in a single statement, and this is not possible in other DBMS.
On the other hand, the following statement will work in others DBMS but not in MySQL, which is not allowing updating a table from a subquery of the same table, we need to use a temporal table to perform this type of operation. If we access to the database using a programming language, PHP for example, it would be more common to store the value in a variable and modifying the table with this.
Modify the date of enrollment of the teachers with TEU category in order to have the same as the teacher with DNI 21333444
select * from profesores;update profesores
set ingreso = (select ingreso from profesores where dni='21333444')
where categoria = 'TEU';
For this statement we must obtain:
However, MariaDB/MySQL returns an error with the message, more or less, "can't update the same table being queried". This also happens with delete. The solution is to "trick" MariaDB/MySQL with a temporary query:
update profesores
set ingreso = (select ingreso
from (select ingreso
from profesores
where dni='21333444') ttemp
)
where categoria = 'TEU';
Actually, it is not that we are "cheating" MariaDB/MySQL; as you can see in the "Temporary tables" topic, what we are doing is generating a temporary table (ttemp) where the TEACHERS data we are interested in is copied.
MariaDB, from version 10.3.2 onwards, does not have this limitation.