Vous pouvez SUPPRIMER une catégorie uniquement s'il n'y a pas de blague correspondante :
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;
S'il existe des blagues pour la catégorie, la jointure les trouvera et, par conséquent, la jointure externe renverra un résultat non nul. La condition dans la clause WHERE élimine les résultats non nuls, de sorte que la suppression globale correspondra à zéro ligne.
De même, vous pouvez INSÉRER une blague dans une catégorie uniquement si la catégorie existe :
INSERT INTO jokes (category_id, joke_text)
SELECT c.id, '$joke_text'
FROM categories AS c WHERE c.id = $category_id;
S'il n'y a pas une telle catégorie, le SELECT renvoie zéro ligne et l'INSERT est un no-op.
Ces deux cas créent un verrou partagé (S-lock) sur la table des catégories.
Démonstration d'un antivol en S :
En une session, je lance :
mysql> INSERT INTO bar (i) SELECT SLEEP(600) FROM foo;
Dans la deuxième session, je lance :
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
Vous pouvez voir que cela crée un verrou IS sur la table foo et un verrou S sur une ligne de foo, la table à partir de laquelle je lis.
La même chose se produit pour toutes les opérations de lecture/écriture hybrides telles que SELECT...FOR UPDATE
, INSERT...SELECT
, CREATE TABLE...SELECT
, pour empêcher la modification des lignes en cours de lecture alors qu'elles sont nécessaires comme source pour l'opération d'écriture.
Le verrou IS est un verrou au niveau de la table qui empêche les opérations DDL sur la table, donc personne n'émet DROP TABLE
ou ALTER TABLE
tandis que cette transaction dépend d'un certain contenu dans la table.