Tabla de Contenidos

SQL

Edición de bases de datos

Crear

CREATE DATABASE nombre

CREATE DATABASE bookstore;

Edición de tablas

Crear

CREATE TABLE nombre (columna tipo propiedades, columna tipo propiedades…)

CREATE TABLE books (
  rec_id INT, 
  title VARCHAR(50),
  author VARCHAR(50)
);

Modificar

ALTER TABLE nombre modificiación, modificación…
Las modificaciones posibles:

ALTER TABLE books
  CHANGE COLUMN rec_id rec_id INT AUTO_INCREMENT PRIMARY KEY,
  CHANGE COLUMN author author_id INT,
  ADD COLUMN description BLOB;

Tipos de datos

Las enumeraciones se asignan entre parentesis un grupo de valores que aceptan, estos entre comillas simples:

Si se le asigna un valor que no existe provoca un warning e inserta un valor en blanco. Cada valor insertado recibe un número, siendo el primero 1, el segundo 2… Y el valor en blanco un 0. Por lo que puedes hacer selects preguntando por el valor numérico o el valor dado.
Los ENUM ocupan: 1 byte si tienen menos de 255 elementos o 2 bytes si tienen menos 65535. Los SET, en cambio, ocupan mucho más (1-8 elementos: 1byte, 9-16 elementos: 2 bytes… 33-64 elementos: 8 bytes).

Propiedades

Las foreign keys

La sintaxis para definir una foreign key en MySql es:

[CONSTRAINT símbolo] FOREIGN KEY (nombre_columna, ...)
  REFERENCES nombre_tabla (nombre_columna, ...)
  [ON DELETE {CASCADE | SET NULL | NO ACTION | RESTRICT}]
  [ON UPDATE {CASCADE | SET NULL | NO ACTION | RESTRICT}]
CREATE TABLE publicaciones (isbn VARCHAR(10) PRIMARY KEY, id_editorial INT, FOREIGN KEY (id_editorial) REFERENCES editoriales(id));

Un ejemplo para añadir una foreign key tras haber creado la tabla:

ALTER TABLE venta ADD FOREIGN KEY(id_cliente) REFERENCES cliente(id_cliente);

Eliminar

DROP TABLE nombre

DROP TABLE books;

Opcionalmente puedes añadir IF EXISTS tras TABLE, de esa forma si la tabla no existe el comando no dará error:

DROP TABLE IF EXISTS books;

Ejemplos

CREATE TABLE rel_autores_publicaciones (id_autor INT, isbn VARCHAR(10), PRIMARY KEY (id_autor, isbn), FOREIGN KEY (id_autor) REFERENCES autores(id), FOREIGN KEY (isbn) REFERENCES publicaciones(isbn));
 
CREATE TABLE diccionarios (isbn VARCHAR(10) PRIMARY KEY, id_idioma1 INT NOT NULL, id_idioma2 INT, FOREIGN KEY (isbn) REFERENCES publicaciones(idiomas), FOREIGN KEY (id_idioma1) REFERENCES idiomas (id), FOREIGN KEY (id_idioma2) REFERENCES idiomas(id));

Edición de datos

Insertar

INSERT INTO tabla (campo1, campo2…) VALUES (valorNumerico, 'valorString'…)

INSERT INTO authors (author_last, author_first, country) VALUES('Vernon','Olympia','USA');

Modificar

UPDATE tabla SET campo1=valor1, campo2=valor2, … [WHERE columnaN=valorN]

UPDATE City SET Population=5000000 WHERE Name='JoanBrossa';
UPDATE City SET Population=5000000 WHERE Population<1000000;

Eliminar

Consulta de datos

Selects

SELECT campos FROM tablas [WHERE condicion] [ORDER BY campoOrden tipoOrden] [LIMIT límite]

Ejemplos

SELECT * FROM books;
SELECT title, description FROM books;
SELECT title AS titulo FROM books;
SELECT rec_id, title, description FROM books WHERE genre = 'novel';
SELECT * FROM books ORDER BY title, pub_year LIMIT 20, 10;
SELECT books.title, a.name FROM books, authors AS a;
SELECT * FROM autores WHERE nombre REGEXP 'r{2}';

Selects avanzados

joins

Imaginemos una BD donde tenemos una relación de películas\director, para sacar películas por director haremos:

SELECT title, name FROM movies m, directors d WHERE m.director = d.id;

Con JOIN sería:

SELECT title, name FROM movies m INNER JOIN directors d ON (m.director = d.id);

Los joins funcionan de la siguiente manera:

Selects anidados

En el siguiente ejemplo se buscan todos los contactos que puede ver el trabajador 1 (los suyos y los que son públicos (visibilidad = 1)):

SELECT * FROM Contactos 
  WHERE Contactos.id IN (SELECT Contactos.id FROM Contactos, RelContTrab WHERE RelConTrab.idCon = Contactos.id AND RelConTrab.idTrab = 1)
  OR Contactos.id IN (SELECT Contactos.id FROM Contactos WHERE Contactos.Visibility = 1);

También podemos pedir campos que estén o no en una lista:

SELECT * FROM tags WHERE id NOT IN (SELECT id FROM Elements);
SELECT * FROM tags WHERE id IN (3, 4, 5);

Funciones

SELECT COUNT(*) FROM users;
SELECT ciudad.nombre, SUM(pueblo.hab) FROM pueblo, ciudad WHERE (pueblo.id_ciudad = ciudad.id) GROUP BY (ciudad.nombre);

Notas

Tips

Insertar los datos de un select

Teniendo dos tablas:

CREATE TABLE b (ca INT, cb INT);
CREATE TABLE c (xa INT, xb INT);

Insertamos en la tabla b unos datos cb con un identificador ca (que puede estar repetido), ahora queremos insertar en la tabla c la suma de los valores cb con un mismo identificador:

INSERT INTO c (xa, xb) SELECT ca, SUM(cb) FROM b GROUP BY ca;

Errores comunes

SELECT userid
FROM userrole
WHERE roleid IN (1, 2, 3)
GROUP by userid
HAVING COUNT(1) = 3

Query time: 0.312s
------------------------------------------------------

SELECT t1.userid
FROM userrole t1
JOIN userrole t2 ON t1.userid = t2.userid AND t2.roleid = 2
JOIN userrole t3 ON t2.userid = t3.userid AND t3.roleid = 3
AND t1.roleid = 1

Query time: 0.016s
Bad:
... WHERE a = 2 OR a = 5 OR a = 11
Better:
... WHERE a IN (2, 5, 11)
Model:
    * Party: people and organisations;
    * Party Role: things those parties did eg Employer and Employer;
    * Party Role Relationship: how those roles related to each other.

Example:
    * Ted is a Person, being a subtype of Party;
    * Ted has many roles, one of which is Employee;
    * Intel is an organisation, being a subtype of a Party;
    * Intel has many roles, one of which is Employer;
    * Intel employs Ted, meaning there is a relationship between their respective roles.

So there are five tables joined to link Ted to his employer. You assume all employees are Persons (not organisations) and provide this helper view:

CREATE VIEW vw_employee AS
SELECT p.title, p.given_names, p.surname, p.date_of_birth, p2.party_name employer_name
FROM person p
JOIN party py ON py.id = p.id
JOIN party_role child ON p.id = child.party_id
JOIN party_role_relationship prr ON child.id = prr.child_id AND prr.type = 'EMPLOYMENT'
JOIN party_role parent ON parent.id = prr.parent_id = parent.id
JOIN party p2 ON parent.party_id = p2.id

And suddenly you have a very simple view of the data you want but on a highly flexible data model.

Sacado de Stack Overflow