sql >> Base de Datos >  >> RDS >> Mysql

InnoDB solo inserta un registro si existe una identificación referenciada (sin CLAVES EXTRANJERAS)

Puede ELIMINAR una categoría solo si no hay una broma coincidente:

DELETE c FROM categories AS c
LEFT OUTER JOIN jokes AS j ON c.id=j.category_id
WHERE c.id = $category_id AND j.category_id IS NULL;

Si hay chistes para la categoría, la combinación los encontrará y, por lo tanto, la combinación externa devolverá un resultado no nulo. La condición en la cláusula WHERE elimina los resultados no nulos, por lo que la eliminación general coincidirá con cero filas.

Asimismo, puede INSERTAR un chiste en una categoría solo si la categoría existe:

INSERT INTO jokes (category_id, joke_text)
SELECT c.id, '$joke_text'
FROM categories AS c WHERE c.id = $category_id;

Si no existe tal categoría, SELECCIONAR devuelve cero filas y INSERTAR no es operativo.

Ambos casos crean un bloqueo compartido (S-lock) en la tabla de categorías.

Demostración de un candado S:

En una sesión ejecuto:

mysql> INSERT INTO bar (i) SELECT SLEEP(600) FROM foo;

En la segunda sesión ejecuto:

mysql> SHOW ENGINE INNODB STATUS\G
. . .
---TRANSACTION 3849, ACTIVE 1 sec
mysql tables in use 2, locked 2
2 lock struct(s), heap size 376, 1 row lock(s)
MySQL thread id 18, OS thread handle 0x7faefe7d1700, query id 203 192.168.56.1 root User sleep
insert into bar (i) select sleep(600) from foo
TABLE LOCK table `test`.`foo` trx id 3849 lock mode IS
RECORD LOCKS space id 22 page no 3 n bits 72 index `GEN_CLUST_INDEX` of table `test`.`foo` trx id 3849 lock mode S

Puede ver que esto crea un bloqueo IS en la tabla foo y un bloqueo S en una fila de foo, la tabla que estoy leyendo.

Lo mismo sucede con cualquier operación híbrida de lectura/escritura como SELECT...FOR UPDATE , INSERT...SELECT , CREATE TABLE...SELECT , para bloquear la modificación de las filas que se están leyendo mientras se necesitan como fuente para la operación de escritura.

El bloqueo IS es un bloqueo a nivel de tabla que evita las operaciones DDL en la tabla, por lo que nadie emite DROP TABLE o ALTER TABLE mientras que esta transacción depende de algún contenido en la tabla.