Esta sección describe cómo MySQL se relaciona con el estándard ANSI/ISO SQL. MySQL Server tiene varias extensiones del estándard SQL, y aquí puede encontrar cuáles son y cómo usarlas. También puede encontrar información sobre lagunas de funcionalidades en MySQL Server, y cómo tratar algunas diferencias.
El estándard SQL ha ido evolucionando desde 1986 y existen varias versiones. En este manual, "SQL-92" se refiere al estándard publicado en 1992, "SQL:1999" se refiere al estándard publicado en 1999, y "SQL:2003" se refiere a la versión actual del estándard. Usamos la frase "el estándard SQL" para referirnos a la versión actual del estándard SQL en cualquier momento.
Nuestro objetivo es no restringir la usabilidad de MySQL ningún uso sin una muy buena razón para ello. Incluso si no tenemos los recursos para hacer un desarrollo para cada uso posible, estamos siempre deseando ayudar y ofrecer sugerencias a gente que intenta usar MySQL en nuevos campos.
Uno de nuestros fines principales con el producto es continuar el
trabajo hacia el cumplimiento del estándard SQL, pero sin
sacrificar velocidad o fiabilidad. No tememos añadir extensiones
a SQL o soporte para funcionalidades no SQL si esto aumenta la
usabilidad de MySQL Server para un gran segmento de nuestra base
de usuarios. La interfaz HANDLER
en MySQL
Server 4.0 es un ejemplo de esta estrategia. Consulte
Sección 13.2.3, “Sintaxis de HANDLER
”.
Continuamos soportando bases de datos transaccionales y no transaccionales para satisfacer uso crítico 24/7 y uso pesado en entornos Web o log.
MySQL Server fue diseñado originalmente para trabajar con bases de datos de tamaño medio (de 10 a 100 millones de regitros, o unas 100MB por tabla) en máquinas pequeñas. Hoy MySQL Server soporta bases de datos de tamaño de terabytes, pero el código todavía puede compilarse en una versión reducida adecuada para dispositivos hand-held o incrustados. El diseño compacto de MySQL Server hace el desarrollo en ambas direcciones posible sin ningún conflicto en el árbol fuente.
Actualmente, no tratamos soporte en tiempo real, aunque la capacidad de replicación en MySQL ofrece funcionalidades significativas.
Existe soporte para clusters de bases de datos a través de soluciones de terceras partes, así como la integración de tecnología NDB Cluster, disponible desde la versión 4.1.2. Consulte Capítulo 16, MySQL Cluster.
También estamos mirando de proveer de soporte XML en el servidor de base de datos.
Estamos intentando soportar en estándard ANSI/ISO completamente, pero sin hacer concesiones a la velocidad y calidad del código.
Niveles ODBC 0-3.51.
MySQL Server puede operar en distintos modos SQL y puede aplicar dichos modos de forma diferente para distintos clientes. Esto permite a una aplicación adaptar el funcionamiento del servidor a sus propios requerimientos.
Los modos definen la sintaxis que MySQL debe soportar y qué clase de validaciones debe efectuar a los datos. Esto hace más fácil usar MySQL en un conjunto de entornos diferentes y usar MySQL junto con otros servidores de bases de datos.
Puede inicializar el modo SQL por defecto inicializando
mysqld con la opición
--sql-mode="modes"
. Empezando en MySQL 4.1.,
se puede cambiar el modo tras inicializar mediante la variable
sql_mode
con un comando SET
[SESSION|GLOBAL] sql_mode='modes'
.
Para más información acerca de especificar el modo del servidor, consulte Sección 5.3.2, “El modo SQL del servidor”.
Puede decirle a mysqld que use el modo ANSI
con la opción --ansi
al arrancar. Consulte
Sección 5.3.1, “Opciones del comando mysqld”.
Ejecutar el servidor en modo ANSI es lo mismo que inicializarlo
con las siguientes opciones (especifique el valor de
--sql_mode
en una única línea):
--transaction-isolation=SERIALIZABLE --sql-mode=REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES, IGNORE_SPACE
En MySQL 4.1, puede conseguir el mismo efecto con los siguientes
2 comandos (especifique el valor de sql_mode
en una única línea):
SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE; SET GLOBAL sql_mode = 'REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES, IGNORE_SPACE';
Consulte Sección 1.7.2, “Selección de modos SQL”.
En MySQL 4.1.1, la opción sql_mode
puede
inicializarse con el siguiente comando:
SET GLOBAL sql_mode='ansi';
En ese caso, el valor de la variable sql_mode
se especifica para todas las opciones que son relevantes en el
modo ANSI. Puede comprobar el resultado de la siguiente manera:
mysql> SET GLOBAL sql_mode='ansi'; mysql> SELECT @@global.sql_mode; -> 'REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES, IGNORE_SPACE,ANSI';
MySQL Server incluye algunas extensiones que probablemente no
encontrará en otras bases de datos SQL. Tenga en cuenta que si
lo usa, su código no será portable a otros servidores SQL. En
algunos casos, puede escribir código que incluya extensiones
MySQL, pero siendo portable, mediante comentarios de la forma
/*! ... */
. En ese caso, MySQL parsea y
ejecuta el código dentro de los comentarios como si fuera
cualquier otro comando de MySQL, pero otros servidores SQL
ignorarán la extensión. Por ejemplo:
SELECT /*! STRAIGHT_JOIN */ col_name FROM table1,table2 WHERE ...
Si añade un número de versión tras el carácter
'!
', la sintaxis dentro del comentario se
ejecuta sólo si el número de versión de MySQL es igual o
mayor que el especificado:
CREATE /*!32302 TEMPORARY */ TABLE t (a INT);
Eso significa que si tiene la Versión 3.23.02 o posterior,
MySQL Server usa la palabra clave TEMPORARY
.
La siguiente lista describe las extensiones MySQL, organizadas por categorías.
-
Organización de los datos en disco
MySQL Server mapea cada base de datos a un directorio bajo el directorio de datos de MySQL, y las tablas dentro de cada directorio como ficheros. Esto tiene algunas implicaciones:
-
Nombres de bases de datos y nombres de tablas son case sensitive en MySQL Server en sistemas operativos que tienen nombres de ficheros case-sensitive (como la mayoría de sistemas Unix). Consulte Sección 9.2.2, “Sensibilidad a mayúsuclas y minúsculas de identificadores”.
-
Puede usar comandos de sistema estándard para hacer copia de seguridad, renombrar, mover, borrar y copiar tablas de tipo
MyISAM
oISAM
. Por ejemplo, para renombrar el nombre de una tablaMyISAM
renombre los archivos.MYD
,.MYI
, y.frm
que correspondan a la tabla.
Nombres de bases de datos, tablas, índices, columnas o alias pueden empezar con un dígito (pero no pueden consistir únicamente de dígitos).
-
-
Sintaxis general del lenguaje
-
Cadenas de carácteres deben limitarse por '
"
' o ''
', no sólo por ''
'. -
Use '
\
' como un carácter de escape en cadenas de carácteres. -
En comandos SQL, puede acceder a tablas de distintas bases de datos con la sintaxis
db_name.tbl_name
. Algunos servidores SQL proporcionan la misma fucnionalidad, pero lo llamanUser space
. MySQL Server no soporta espacios de tablas como los usados en comandos como:CREATE TABLE ralph.my_table...IN my_tablespace
.
-
-
Sintaxis de comandos SQL
-
Los comandos
ANALYZE TABLE
,CHECK TABLE
,OPTIMIZE TABLE
, yREPAIR TABLE
. -
Los comandos
CREATE DATABASE
yDROP DATABASE
. Consulte Sección 13.1.3, “Sintaxis deCREATE DATABASE
”. -
El comando
DO
. -
EXPLAIN SELECT
para obtener una descripción de cómo las tablas se usan. -
Los comandos
FLUSH
yRESET
. -
El comando
SET
. Consulte Sección 13.5.3, “Sintaxis deSET
”. -
El comando
SHOW
. Consulte Sección 13.5.4, “Sintaxis deSHOW
”. -
Uso de
LOAD DATA INFILE
. En muchos casos, esta sintaxis es compatible con el comando de OracleLOAD DATA INFILE
. Consulte Sección 13.2.5, “Sintaxis deLOAD DATA INFILE
”. -
Uso de
RENAME TABLE
. Consulte Sección 13.1.9, “Sintaxis deRENAME TABLE
”. -
Uso de
REPLACE
en lugar deDELETE
+INSERT
. Consulte Sección 13.2.6, “Sintaxis deREPLACE
”. -
Uso de
CHANGE col_name
,DROP col_name
, oDROP INDEX
,IGNORE
oRENAME
en un comandoALTER TABLE
. Uso de múltiplesADD
,ALTER
,DROP
, oCHANGE
cláusulas en un comandoALTER TABLE
. Consulte Sección 13.1.2, “Sintaxis deALTER TABLE
”. -
Uso de nombres de índices, índices sobre el prefijo de un cambio, y uso de
INDEX
oKEY
en un comandoCREATE TABLE
. Consulte Sección 13.1.5, “Sintaxis deCREATE TABLE
”. -
Uso de
TEMPORARY
oIF NOT EXISTS
conCREATE TABLE
. -
Uso de
IF EXISTS
conDROP TABLE
. -
Puede borrar varias tablas con un único comando
DROP TABLE
. -
Las cláusulas
ORDER BY
yLIMIT
de los comandosUPDATE
yDELETE
. -
Sintaxis de
INSERT INTO ... SET col_name = ...
. -
La cláusula
DELAYED
de los comandosINSERT
yREPLACE
. -
La cláusula
LOW_PRIORITY
de los comandosINSERT
,REPLACE
,DELETE
, yUPDATE
. -
Uso de
INTO OUTFILE
ySTRAIGHT_JOIN
en un comandoSELECT
. Consulte Sección 13.2.7, “Sintaxis deSELECT
”. -
La opción
SQL_SMALL_RESULT
en un comandoSELECT
. -
No necesita nombrar todas las columnas seleccionadas en la parte
GROUP BY
. Esto proporciona mejor rendimiento en algunas consultas muy específicas pero bastante normales. Consulte Sección 12.10, “Funciones y modificadores para cláusulasGROUP BY
”. -
Puede especificar
ASC
yDESC
conGROUP BY
. -
La habilidad para inicializar variables en un comando con el operador
:=
:mysql> SELECT @a:=SUM(total),@b=COUNT(*),@a/@b AS avg -> FROM test_table; mysql> SELECT @t1:=(@t2:=1)+@t3:=4,@t1,@t2,@t3;
-
-
Tipos de columnas
-
Los tipos de columnas
MEDIUMINT
,SET
,ENUM
, y los distintos tiposBLOB
yTEXT
. -
Los atributos de columnas
AUTO_INCREMENT
,BINARY
,NULL
,UNSIGNED
, yZEROFILL
.
-
-
Funciones y operadores
-
Para facilitar a los usuarios que vienen de otros entornos SQL, MySQL Server soporta alias para varias funciones. Por ejemplo, todas las funciones de cadenas de carácteres soportan sintaxis estándard SQL y ODBC.
-
MySQL Server entiende los operadores
||
y&&
para OR lógica y AND, como en el lenguaje de programación C. En MySQL Server,||
yOR
son sinónimos, como lo son&&
yAND
. Debido a esta sintaxis, MySQL Server no soporta el operador estándard SQL||
para concatenar cadenas de carácteres; use en su lugarCONCAT()
. ComoCONCAT()
toma cualquier número de argumentos, es fácil adaptarse al uso del operador||
a MySQL Server. -
Uso de
COUNT(DISTINCT list)
dondelist
tiene más de un elemento. -
Todas las comparaciones de cadenas de carácteres son case-insensitive por defecto, con la ordenación determinada por el conjunto de carácteres actual (ISO-8859-1 Latin1 por defecto). Si no quiere que sea así, puede declarar las columnas con el atributo
BINARY
o usar la conversiónBINARY
, que hace que las comparaciones se hagan usando el código de carácteres subyacente en lugar del orden léxico. -
El operador
%
es sinónimo deMOD()
. Esto es queN % M
es equivalente aMOD(N,M)
.%
se soporta para programadores C y por compatibilidad con PostgreSQL. -
Los operadores
=
,<>
,<=
,<
,>=
,>
,<<
,>>
,<=>
,AND
,OR
, oLIKE
se pueden usar en comparaciones de columnas a la izquierda delFROM
en comandosSELECT
. Por ejemplo:mysql> SELECT col1=1 AND col2=2 FROM
tbl_name
; -
La función
LAST_INSERT_ID()
retorna el valorAUTO_INCREMENT
más reciente. Consulte Sección 12.9.3, “Funciones de información”. -
LIKE
se permite en columnas numéricas. -
Los operadores de expresiones regulares extendidos
REGEXP
yNOT REGEXP
. -
CONCAT()
oCHAR()
con un argumento o más de dos argumentos. (En MySQL Server, estas funciones pueden tomar cualquier número de argumentos.) -
Las funciones
BIT_COUNT()
,CASE
,ELT()
,FROM_DAYS()
,FORMAT()
,IF()
,PASSWORD()
,ENCRYPT()
,MD5()
,ENCODE()
,DECODE()
,PERIOD_ADD()
,PERIOD_DIFF()
,TO_DAYS()
, yWEEKDAY()
. -
Uso de
TRIM()
para eliminar espacios en substrings. Funciones estándard sólo SQL soportan eliminar carácteres simples. -
Las funciones
GROUP BY
STD()
,BIT_OR()
,BIT_AND()
,BIT_XOR()
, yGROUP_CONCAT()
. Consulte Sección 12.10, “Funciones y modificadores para cláusulasGROUP BY
”.
-
Intentamos que MySQL Server siga los estándares ANSI SQL y el estándard ODBC SQL, pero MySQL Server ejecuta operaciones de forma distinta en algunos casos:
-
Para columnas
VARCHAR
, los espacios finales se eliminan cuando el valor se guarda. (Arreglado en MySQL 5.0.3). Consulte Sección A.8, “Problemas conocidos en MySQL”. -
En algunos casos, las columnas de tipo
CHAR
se convierten en columnasVARCHAR
cuando define una tabla o altera su estructura. (Arreglado en MySQL 5.0.3). Consulte Sección 13.1.5.1, “Cambios tácitos en la especificación de columnas”. -
Los privilegios para una tabla no se eliminan automáticamente cuando se borra una tabla. Debe usar explícitamente un comando
REVOKE
para quitar los privilegios de una tabla. Consulte Sección 13.5.1.3, “Sintaxis deGRANT
yREVOKE
”. -
La función
CAST()
no soporta conversión aREAL
oBIGINT
. Consulte Sección 12.8, “Funciones y operadores de cast”. -
SQL estándard necesita que las cláusulas
HAVING
en un comandoSELECT
puedan referirse a columnas en la cláusulaGROUP BY
. Esto no se permite antes de la versión MySQL 5.0.2.
MySQL 4.1 soporta sub-consultas y tablas derivadas. Una
"sub-consulta" es un comando SELECT
anidado en otro comando. Una tabla "derivada" (una vista sin
nombre) es una subconsulta en la cláusula
FROM
de otra consulta. Consulte
Sección 13.2.8, “Sintaxis de subconsultas”.
Para versiones MySQL anteriores a la 4.1, la mayoría de subconsultas pueden reescribirse usando joins u otros métodos. Consulte Sección 13.2.8.11, “Re-escribir subconsultas como joins en versiones de MySQL anteriores” para ejemplos que muestren cómo hacerlo.
MySQL Server no soporta la sintaxis de extensiones Sybase SQL:
SELECT ... INTO TABLE ...
. En su lugar,
MySQL Server soporta la sintaxis estándard SQL
INSERT INTO ... SELECT ...
, que
básicamente es lo mismo. Consulte
Sección 13.2.4.1, “Sintaxis de INSERT ... SELECT
”.
INSERT INTO tbl_temp2 (fld_id) SELECT tbl_temp1.fld_order_id FROM tbl_temp1 WHERE tbl_temp1.fld_order_id > 100;
Alternativamente, puede usar SELECT INTO OUTFILE
...
o CREATE TABLE ... SELECT
.
Para al versión 5.0, MySQL soporta SELECT ...
INTO
con variables de usuario. La misma sintaxis
puede usarse dentro de procedimientos almacenados usando
cursores y variables locales. Consulte
Sección 19.2.9.3, “La sentencia SELECT ... INTO
”.
MySQL Server (versiones 3.23-max y todas las versiones 4.0 y
posteriores) soportan transacciones con los motores
trasaccionales InnoDB
y
BDB
. InnoDB
proporciona
completa compatibilidad
ACID
. Consulte
Capítulo 14, Motores de almacenamiento de MySQL y tipos de tablas.
Los otros motores no transaccionales en MySQL Server (como
MyISAM
) siguen un paradigma diferente para
integridad de datos llamado "operaciones atómicas". En
términos transaccionales, tablas MyISAM
operan en modo AUTOCOMMIT=1
. Operaciones
atómicas a menudo ofrecen integridad comparable con mejor
rendimiento.
MySQL Server soporta ambos paradigmas, puede decidir si su aplicación necesita la velocidad de operaciones atómicas o el uso de características transaccionales. Esta elección puede hacerse para cada tabla.
Como se ha dicho, el compromiso entre tipos de tablas
transaccionales y no transaccionales reside principalmente en
el rendimiento. Tablas transaccionales tienen requerimientos
significativamente mayores para memoria y espacio de disco, y
mayor carga de CPU. Por otra parte, tipos de tablas
transaccionales como InnoDB
también ofrece
muchas características significativas. El diseño modular de
MySQL Server permite el uso concurrente de distintos motores
de almacenamiento para cumplir distintos requerimientos y
mostrarse óptimo en todas las situaciones.
Pero, ¿cómo usar las características de MySQL Server para
mantener integridad de forma rigurosa incluso en tablas no
transaccionales como MyISAM
, y cómo se
comparan estas características con los tipos de tablas
transaccionales?
-
Si su aplicación está escrita de forma que dependa en que pueda llamar a
ROLLBACK
en lugar deCOMMIT
en situaciones críticas, es preferible usar transacciones. Transacciones aseguran que actualizaciones no acabadas o actividades corruptas no se ejectuen en la base de datos; el sevidor tiene la oportunidad de hacer un rollback automático para mantener la base de datos a salvo.Si usa tablas no transaccionales, MySQL Server le permite solucionar problemas potenciales en prácticamente todos los casos simplemente incluyendo chequeos antes de las actualizaciones y ejecutando scripts sencillos que comprueban que la consistencia de la base de datos, dando una advertencia o reparando automáticamente cualquier incosistencia. Simplemente usando el log de MySQL o añadiendo un log extra, normalmente puede arreglar tablas sin pérdida de integridad en los datos.
-
Normalmente, las actualizaciones transaccionales críticas pueden reescribirse como atómicas.Generalmente hablando, todos los problemas de integridad que resuelven las transacciones pueden resolverse con
LOCK TABLES
o actualizaciones atómicas, asegurando que no se aborten automáticamente desde el servidor, el cuál es un problema habitual en sistemas de bases de datos transaccionales. -
Para tener un entorno fiable de MySQL, usando tablas transaccionales o no, sólo necesita tener copias de seguridad y el log binario activado. Con ello, puede recuperarse de cualquier situación de la que pueda hacerlo con cualquier otro sistema transaccional. Siempre es bueno tener copias de seguridad, independientemente del sistema de bases de datos usado.
El paradigma transaccional tiene sus ventajas y desventajas. Muchos usuarios y desarrolladores de aplicaciones dependen en la facilidad con la que pueden solucionar problemas donde un aborto parece ser o es necesario. Sin embargo, incluso si el paradigma de operaciones atómicas le es desconocido o está más familiarizado con las transacciones, considere el beneficio de la velocidad que pueden ofrecer las tablas no transaccionales, que puede ser de tres a cinco veces más rápido que las más optimizadas tablas transaccionales.
En las situaciones en las que la integridad es de máxima
importancia, MySQL Server ofrece integridad a nivel de
transacción incluso para tablas no transaccionales. Si
bloquea tablas con LOCK TABLES
, todas las
actualizaciones se bloquean hasta que se hacen las
comprobaciones necesarias. Si obtiene un bloqueo READ
LOCAL
(el contrario a un bloqueo de escritura) para
una tabla que permita inserciones concurrentes al final de la
tabla, las lecturas están permitidas, así como las
inserciones de otros clientes. Los registros insertados no
puede verlos el cliente que tenga el bloqueo hasta que lo
libere. Con INSERT DELAYED
, puede encolar
inserciones en una cola local, hasta que los bloqueos se
liberan, sin tener que esperar el cliente a que acabe la
inserción. Consulte Sección 13.2.4.2, “Sintaxis de INSERT DELAYED
”.
"Atómico", en el sentido en que nos referimos, no es nada mágico. Se trata que puede asegurar que mientras cada actualización específica está ejecutándose, ningún otro usuario puede interferir con ellas, y que nunca puede haber un rollback automático (lo que puede ocurrir con tablas transaccionales si no se es muy cuidadoso). MySQL Server garantiza que no hay dirty reads (lecturas sucias).
A continación se presentan algunas técnicas para trabajar con tablas no transaccionales:
-
Los bucles que necesiten transacciones normalmente pueden codificarse con la ayuda de
LOCK TABLES
, y no necesita cursores para actualizar registros en tiempo real. -
Para evitar usar
ROLLBACK
, puede usar la siguiente estrategia:-
Use
LOCK TABLES
para bloquear todas las tablas a las que quiere acceder. -
Compruebe las condiciones que deben darse antes de ejecutar la actualización.
-
Actualice si todo es correcto.
-
Use
UNLOCK TABLES
para liberar los bloqueos.
Este es un método mucho más rápido que usar transacciones con posibles rollbacks, aunque no siempre. La única situación en que esta situación no funciona es cuando alguien mata el thread durante una actualización. En ese caso, todos los bloqueos se liberan pero algunas actualizaciones pueden no ejecutarse.
-
-
Puede usar funciones para actualizar registros en una única operación. Puede obtener una aplicación muy eficiente usando las siguientes técnicas:
-
Modifique columnas con su valor actual.
-
Actualice sólo aquéllas que hayan cambiado.
Por ejemplo, cuando estamos actualizando la información de un cliente, sólo actualizamos los datos del cliente que han cambiado y comprobamos que los datos cambiados o datos que dependen de los datos cambiados, han cambiado respecto a los datos originales. El test para datos cambiados se hace con la cláusula
WHERE
en el comandoUPDATE
. Si el registro no se ha actualizado, mostramos un mensaje al cliente: "Algunos de los datos actualizados han sido cambiados por otro usuario". A continuación mostramos los registros viejos junto a los nuevos en una ventana para que el usuario pueda decidir qué versión del registro de usuario usar.Esto nos da algo que es similar a bloqueo de columnas pero es incluso mejor ya que sólo actualizamos algunas de las columnas, usando valores que son relativos a sus valores actuales. Eso significa que el típico comando
UPDATE
será algo así:UPDATE tablename SET pay_back=pay_back+125; UPDATE customer SET customer_date='current_date', address='new address', phone='new phone', money_owed_to_us=money_owed_to_us-125 WHERE customer_id=id AND address='old address' AND phone='old phone';
Esto es muy eficiente y funciona incluso si otro cliente ha cambiado los valores en las columnas
pay_back
omoney_owed_to_us
. -
-
En muchos casos, los usuarios han querido usar
LOCK TABLES
y/oROLLBACK
con la intención de administrar identificadores únicos. Se puede tratar de forma mucho más eficiente sin bloquear o rolling back usando columnasAUTO_INCREMENT
y la función SQLLAST_INSERT_ID()
o la función de la API Cmysql_insert_id()
. Consulte Sección 12.9.3, “Funciones de información”. Consulte Sección 24.3.3.34, “mysql_insert_id()
”.Normalmente puede codificar la necesidad de bloqueo a nivel de registro. Algunas situaciones realmente lo necesitan, y las tablas
InnoDB
lo soportan. Con tablasMyISAM
, puede usar una columna flag en la tabla y hacer algo como lo siguiente:UPDATE
tbl_name
SET row_flag=1 WHERE id=ID;MySQL retorna
1
para el número de registros afectados si la fila ha sido encontrada yrow_flag
no era1
en el registro original.Puede imaginarlo como si MySQL Server cambiase la consulta anterior a:
UPDATE
tbl_name
SET row_flag=1 WHERE id=ID AND row_flag <> 1;
Los procedimientos almacenados se implementan desde la versión 5.0. Consulte Capítulo 19, Procedimientos almacenados y funciones.
Funcionalidad básica para disparadores se implementa en MySQL desde la versión 5.0.2, con desarrollo adicional planeado para MySQL 5.1. Consulte Capítulo 20, Disparadores (triggers).
En MySQL Server 3.23.44 y posteriores, el motor
InnoDB
soporta chequeo para restricciones
de claves foráneas, incluyendo CASCADE
,
ON DELETE
, y ON UPDATE
.
Consulte Sección 15.6.4, “Restricciones (constraints) FOREIGN KEY
”.
Para otros motores diferentes a InnoDB
,
MySQL Server parsea la sintaxis de FOREIGN
KEY
en comandos CREATE TABLE
,
pero no lo usa ni almacena. En el futuro, la implemantación
se extenderá para almacenar esta información en el fichero
de especificaciones de las tablas de forma que puedan
obtenerla mysqldump y ODBC. En una etapa
posterior, restricciones de claves foráneas se implementarán
para tablas MyISAM
.
Restricciones de claves foráneas ofrecen distintos beneficios a los diseñadores de bases de datos:
-
Suponiendo un diseño adecuado de las relaciones, las restricciones de claves foráneas hacen más difícil que un programador introduzca inconsistencias en la base de datos.
-
Chequeo centralizado de restricciones por el servidor de base de datos hace que sea innecesario realizar esos chequeos en la parte de la aplicación, eliminando la posibilidad que distintas aplicaciones puedan no chequear todas las restricciones de la misma forma.
-
Usando actualizaciones y borrados en cascada puede simplificarse el código de aplicación.
-
Reglas diseñadas correctamente para claves foráneas pueden ayudar a documentar las relaciones entre tablas.
Tenga en cuenta que estos beneficios tienen el coste de un trabajo adicional para el servidor de base de datos para poder realizar todas las comprobaciones necesarias. Chequeos adicionales por parte del servidor afectan al rendimiento, lo que puede ser lo suficientemente malo para algunas aplicaciones como para evitarlo todo lo posible. (Algunas grandes aplicaciones comerciales han codificado la lógica de claves foráneas en el nivel de aplicación por esta razón.)
MySQL proporciona a diseñadores de bases de datos la
posibilidad de elegir qué paradigma elegir. Si no necesita
claves foráneas y quiere evitar la sobrecarga asociada con la
integridad referencial, puede usar otro tipo de tabla como
MyISAM
. (Por ejemplo, el motor
MyISAM
ofrece muy buen rendimiento para
aplicaciones que sólo realizan operaciones
INSERT
y SELECT
, ya que
las inserciones de pueden utilizar de forma concurrente con
consultas. Consulte Sección 7.3.2, “Cuestiones relacionadas con el bloqueo (locking) de tablas”.)
Si elige no utilizar integridad referencial, tenga en cuenta las siguientes consideraciones:
-
Sin un chequeo por parte del servidor de integridad referencial, la aplicación debe realizar este trabajo. Por ejemplo, debe tener cuidado de insertar registros en tablas en el orden apropiado, y evitar crear registros con hijos huérfanos. También debe ser capaz de recuperarse de errores que ocurran durante inserciones múltiples.
-
Si
ON DELETE
es la única integridad referencial que necesita la aplicación, desde la versión 4.0 de MySQL Server puede usar comandosDELETE
para borrar registros de distintas tablas con un único comando. Consulte Sección 13.2.1, “Sintaxis deDELETE
”. -
Una forma de suplir la falta de
ON DELETE
es añadir el comandoDELETE
apropiado a su aplicación cuando borre registros de una tabla que no tenga clave foránea. En la práctica, esto es tan rápido como usar una clave foránea, y más portable.
Tenga en cuenta que el uso de claves foráneas puede provocar algunos problemas:
-
El soporte de claves foráneas arregla muchas cuestiones relacionadas con la integridad, pero todavía es necesario diseñar las claves cuidadosamente para evitar reglas circulares o combinaciones incorrectas de borrados en cascada.
-
Es posible crear una topología de relaciones que haga difícil restaurar tablas individuales de una copia de seguridad. (MySQL alivia esta dificultad permitiendo desactivar claves foráneas temporalmente al recargar una tabla que dependa de otras. Consulte Sección 15.6.4, “Restricciones (constraints)
FOREIGN KEY
”. Desde MySQL 4.1.1, mysqldump genera ficheros que utilizan esta características automáticamente al recargarse.)
Tenga en cuenta que las claves foráneas en SQL se usan para
chequear y forzar integridad referencial, no para unir tablas.
Si quiere obtener resultados de múltiples tablas a partir de
un comando SELECT
, debe usar un join entre
ellas:
SELECT * FROM t1, t2 WHERE t1.id = t2.id;
Consulte Sección 13.2.7.1, “Sintaxis de JOIN
”. Consulte
Sección 3.6.6, “Usar claves foráneas (foreign keys)”.
La sintaxis de FOREIGN KEY
sin ON
DELETE ...
se usa a menudo por aplicaciones ODBC
para producir cláusulas WHERE
automáticamente.
Vistas (incluyendo vistas actualizables) se implementan en la versión 5.0 de MySQL Server. Las vistas están disponibles en las versiones binarias a partir de la 5.0.1. Consulte Capítulo 21, Vistas (Views).
Las vistas son útiles para permitir acceder a los usuarios a un conjunto de relaciones (tablas) como si fueran una sola, y limitar su acceso a las mismas. También se pueden usar las vistas para restringir el acceso a registros (un subconjunto de una tabla particular). Para control de acceso a columnas, puede usar el sofisticado sistema de privilegios de MySQL Server. Consulte Sección 5.6, “El sistema de privilegios de acceso de MySQL”.
Al diseñar la implementación de las vistas, nuestro ambicioso objetivo, dentro de los límites de SQL, ha sido la plena compatibilidad con la regla 6 de Codd para sistemas relacionales de bases de datos: "Todas las vistas que son actualizables en teoría, deben serlo en la práctica".
Algunas otras bases de datos SQL utilizan
'--
' para comenzar comentarios. MySQL
Server utiliza '#
' como carácter para
comenzar comentarios. Puede utilizar comentarios estilo C
/*this is a comment */
con MySQL Server.
Consulte Sección 9.5, “Sintaxis de comentarios”.
MySQL Server 3.23.3 y posteriores permiten comentarios del
estilo '--
', mientras el comentario esté
seguido de un carácter (o por un carácter de controlo como
una nueva línea). Se necesita dicho espacio para evitar
problemas con consultas SQL generadas automáticamente que
usen algo parecido al código a continuación, donde se
inserta automáticamente el valor de pago para
!payment!
:
UPDATE account SET credit=credit-!payment!
Piense acerca de lo que ocurre si el valor de
payment
es un valor negativo como
-1
:
UPDATE account SET credit=credit--1
credit--1
es una expresión legal en SQL,
pero si --
se interpreta como parte de un
comentario, una parte de la expresión se descarta. El
resultado es un comando que tiene un significado completamente
distinto al deseado:
UPDATE account SET credit=credit
Este comando no produce ningún cambio en absoluto! Lo cual
ilustra que permitir comentaros que empiecen con
'--
' puede tener serias consecuencias.
Usando la implementación de este método de comentarios en
MySQL Server desde 3.23.3, credit--1
es
seguro.
Otra medida de seguridad es que el cliente de líneas de
comando mysql elimina todas las líneas que
empiecen con '--
'.
La siguiente información sólo es relevante si utiliza versiones anteriores a la 3.23.3:
Si tiene un programa SQL en un fichero de texto que contenga
comentarios del estilo '--
', debería
utilizar la utilidad replace para convertir
los comentarios antiguos en carácteres '#
'
de la siguiente forma:
shell> replace " --" " #" < text-file-with-funny-comments.sql \
| mysql db_name
en lugar del usual:
shell> mysql db_name
< text-file-with-funny-comments.sql
También puede editar el fichero "a mano" para cambiar los
comentarios '--
' a '#
':
shell> replace " --" " #" -- text-file-with-funny-comments.sql
Vuelva a cambiarlos con el comando:
shell> replace " #" " --" -- text-file-with-funny-comments.sql
MySQL le permite trabajar con tablas transaccionales, que permiten hacer un rollback, y con tablas no transaccionales que no lo permiten. Es por ello que las restricciones son algo distintas en MySQL respecto a otras bases de datos. Debemos tratar el caso en el que se insertan o actualizan muchos registros en una tabla no transaccional en la que los cambios no pueden deshacerse cuando ocurre un error.
La filosofía básica es que MySQL Server trata de producir un error para cualquier cosa que detecte mientras parsea un comando que va a ejecutarse, y trata de recuperarse de cualquier error que ocurra mientras se ejecuta el comando. Lo hacemos en la mayoría de casos, pero todavía no en todos.
Las opciones en MySQL cuando ocurre un error son parar el comando en medio de la ejecución o recuperarse lo mejor posible del problema y continuar. Por defecto, el servidor utiliza esta última opción. Esto significa, por ejemplo, que el servidor puede cambiar algunos valores ilegales por el valor legal más próximo.
A partir de la versión 5.0.2 de MySQL, hay disponibles varios modos SQL para proporcionar un mayor control sobre cómo aceptar valores incorrectos y si continuar ejecutando el comando o abortarlo cuando ocurre el error. Usando estas opciones, puede configurar MySQL Server para actuar en un modo más tradicional como otros servidores de bases de datos que rechazan datos incorrectos. Los modos SQL pueden cambiarse en tiempo de ejecución, lo que permite a los clientes individuales seleccionar el comportamiento más apropiado para sus requerimientos. Consulte Sección 5.3.2, “El modo SQL del servidor”.
La siguiente sección describe qué ocurre para diferentes tipos de restricciones.
Normalmente, un error ocurre cuando trata de ejecutar un
INSERT
o UPDATE
en un
registro que viole la clave primaria, clave única o clave
foránea. Si usa un motor transaccional como
InnoDB
, MySQL automáticamente deshace el
comando. Si usa un motor no transaccional, MySQL para de
procesar el comando en el registro en el que ocurre el error y
deja sin procesar el resto de registros.
Si desea ignorar este tipo de violaciones de claves, MySQL
permite la palabra clave IGNORE
para
INSERT
y UPDATE
. En este
caso, MySQL ignora cualquier violación de clave y continúa
procesando el siguiente registro. Consulte
Sección 13.2.4, “Sintaxis de INSERT
”. See Sección 13.2.10, “Sintaxis de UPDATE
”.
Puede obtener información acerca del número de registro
insertados o actualizados realmente con la función de la API
de C mysql_info()
. Consulte
Sección 24.3.3.32, “mysql_info()
”. A partir de MySQL 4.1 puede usar
el comando SHOW WARNINGS
. Consulte
Sección 13.5.4.22, “Sintaxis de SHOW WARNINGS
”.
De momento, sólo las tablas InnoDB
soportan claves foráneas. Consulte
Sección 15.6.4, “Restricciones (constraints) FOREIGN KEY
”. El soporte
para claves foráneas para tablas MyISAM
está previsto para implementarse en MySQL 5.1.
Antes de la versión 5.0.2 de MySQL, se permitía insertar valores ilegales convirtiéndolos en valores legales. A partir de la versión 5.0.2, sigue este compartimiento por defecto, pero puede elegir un tratamiento para valores incorrectos más tradicional, como no aceptarlos y abortar los comandos que los incluyen. Esta sección describe el comportamiento por defecto de MySQL (permisivo), así como el nuevo modo estricto SQL y en qué se diferencian.
Lo siguiente es cierto si no usa modo estricto. Si inserta un
valor "incorrecto" en una columna, como
NULL
en una columna NOT
NULL
o una valor numérico demasiado grande en una
columna numérica, MySQL cambia el valor al "mejor valor
posible" para la columna en lugar de producir un error:
-
Si trata de almacenar un valor fuera de rango en una columna numérica, MySQL Server en su lugar almacena cero, el menor valor posible, o el mayor valor posible en la columna.
-
Para cadenas de carácteres, MySQL almacena una cadena vacía o tanto de la cadena de carácteras como quepa en la columna.
-
Si trata de almacenar una cadena de carácteres que no empiece con un número en una columna numérica, MySQL Server almacena 0.
-
MySQL le permite almacenar ciertos valores incorrectos en columnas
DATE
yDATETIME
(tales como'2000-02-31'
o'2000-02-00'
). La idea es que no es el trabajo del servidor SQL validar fechas. Si MySQL puede almacenar una fecha y recuperarla fielmente, se almacena tal y como se da. Si la fecha es totalmente incorrecta (más allá de la capacidad del servidor para almacenarla), se almacena en su lugar el valor especial'0000-00-00'
. -
Si intenta almacenar
NULL
en una columna que no admita valoresNULL
ocurre un error para los comandosINSERT
de un solo registro. Para comandosINSERT
de varios registros o para comandosINSERT INTO... SELECT
, MySQL Server almacena el valor implícito para el tipo de datos de la columna. En general, es0
para tipos numéricos, cadena vacía (""
) para tipos de cadenas de carácteres, y el valor "cero" para tipos de fecha y tiempo. Los valores implícitos por defecto se discuten en Sección 13.1.5, “Sintaxis deCREATE TABLE
”. -
Si un comando
INSERT
no especifica un valor para una columna, MySQL inserta su valor por defecto si la columna especifica un valor mediante la cláusulaDEFAULT
. Si la definición no tiene tal cláusulaDEFAULT
clause, MySQL inserta el valor por defecto implícito para el tipo de datos de la columna.
La razón para las reglas anteriores es que no podemos validar esas condiciones hasta que los comandos han empezado a ejecutarse. No podemos deshacer si encontramos un problema tras actualizar algunos registros, ya que el motor de almacenamiento puede no soportar rollback. La opción de terminar el comando no es siempre positiva; en este caso, la actualización quedaría "a medias", lo que posiblemente es la peor opción. En este caso, lo mejor es hacerlo "lo mejor posible" y continuar como si nada hubiera ocurrido.
A partir de MySQL 5.0.2, puede seleccionar un tratamiento de
validación de datos de entrada más estricto usando los modos
SQL STRICT_TRANS_TABLES
o
STRICT_ALL_TABLES
. Consulte
Sección 5.3.2, “El modo SQL del servidor”.
STRICT_TRANS_TABLES
funciona así:
-
Para motores de almacenamiento transaccionales, valores incorrectos en cualquier parte del comando provocan que se aborte el comando y se deshaga el mismo.
-
Para motores no transaccionales, el comando aborta si ocurre un error en el primer registro a insertar o actualizar. (En este caso, el comando dejará la tabla intacta, igual que en una tabla transaccional.) Los errores en registros después del primero no abortan el comando. En lugar de ello, los valores incorrectos se ajustan y se generan advertencias en lugar de errores. En otras palabras, con
STRICT_TRANS_TABLES
, un valor incorrecto provoca que MySQL deshaga todas las actualizaciones hechas hasta el momento, si es posible.
Para chequeo estricto, active
STRICT_ALL_TABLES
. Es equivalente a
STRICT_TRANS_TABLES
excepto que en motores
de almacenamiento no transaccionales, los errores abortan el
comando incluso cuando hay datos incorrectos a partir del
primer registro. Esto significa que si ocurre un error a
medias de una inserción o actualización de varios registros
en una tabla no transaccional, se produce una actualización
parcial. Los primeros registros se insertan o actualizan, pero
aquéllos a partir del punto en que ocurre el error no. Para
evitar esto en tablas no transaccionales, use inserciones de
un solo registro o use STRICT_TRANS_TABLES
para obtener advertencias en lugar de errores. Para evitar
problemas, no utilice MySQL para validar contenido de
columnas. Es preferible (y a menudo más rápido) dejar que la
aplicación se asegure de pasar sólo valores legales a la
base de datos.
Con cualquiera de las opciones de modo estricto, puede hacer
que se traten los errores como advertencias usando
INSERT IGNORE
o UPDATE
IGNORE
en lugar de INSERT
o
UPDATE
sin IGNORE
.
Las columnas ENUM
y SET
proporcionan una manera eficiente de definir columnas que
contienen un conjunto dado de valores. Sin embargo, antes de
MySQL 5.0.2, ENUM
y SET
no son restricciones reales. Esto es por la misma razón que
NOT NULL
tampoco lo es. Consulte
Sección 1.7.6.2, “Restricciones (constraints) sobre datos inválidos”.
Las columnas de tipo ENUM
siempre tienen un
valor por defecto. Si no especifica un valor por defecto,
entonces será NULL
para las columnas que
permitan valores NULL
, si no, se utiliza el
primer valor de la enumeración como valor por defecto.
Si inserta un valor incorrecto en una columna
ENUM
o si fuerza insertar un valor en una
columna ENUM
con IGNORE
,
se inicializa al valor reservado para enumeraciones
0
, el cual se muestra como una cadena
vacía en un contexto de cadenas de carácteres. Consulte
Sección 11.4.4, “El tipo de columna ENUM
”.
Si insertar un valor incorrecto en una columna
SET
, se ignora el valor incorrecto. Por
ejemplo, si la columna puede contener los valores
'a'
, 'b'
, y
'c'
, un intento de insertar
'a,x,b,y'
resulta en un valor de
'a,b'
. Consulte Sección 11.4.5, “El tipo SET
”.
En MySQL 5.0.2, puede configurar el servidor para que use el
modo estricto de SQL. Consulte
Sección 5.3.2, “El modo SQL del servidor”. Cuando el modo estricto
está activado, la definición de columnas
ENUM
o SET
no actúa
como una restricción en valores insertados en la columna. Los
valores que no satisfacen estas condiciones provocan un error:
-
Un valor
ENUM
debe elegirse entre los listados en la definición de la columna, o el equivalente numérico interno. El valor no puede ser un valor de error (esto es 0 o la cadena vacía). Para una columna definida comoENUM('a','b','c')
, valores tales como""
,'d'
, y'ax'
son ilegales y rehusados. -
Un valor
SET
debe ser una cadena vacía o un valor consistente en uno o más valores listados en la definición de la columna separados por comas. Para una columna definida comoSET('a','b','c')
, valores tales como'd'
, y'a,b,c,d'
serían ilegales y, por lo tanto, rehusados.
Se pueden suprimir los errores derivados de valores inválidos
en modo estricto usando INSERT IGNORE
o
UPDATE IGNORE
. En ese caso, se genera una
advertencia en lugar de un error. Para tipos
ENUM
, el valor se inserta como un miembro
erróneo (0
). Para tipo
SET
, el valor se inserta igual excepto que
se borra cualquier subcadena inválida. Por ejemplo,
'a,x,b,y'
se convertiría en
'a,b'
, como se ha descrito.