Mysql
 sql >> Datenbank >  >> RDS >> Mysql

InnoDB fügt Datensatz nur ein, wenn referenzierte ID existiert (ohne FOREIGN KEYS)

Sie können eine Kategorie nur LÖSCHEN, wenn kein passender Witz vorhanden ist:

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;

Wenn es Witze für die Kategorie gibt, findet der Join sie, und daher gibt der Outer Join ein Ergebnis ungleich Null zurück. Die Bedingung in der WHERE-Klausel eliminiert Nicht-Null-Ergebnisse, sodass die Gesamtlöschung mit null Zeilen übereinstimmt.

Ebenso können Sie einen Witz nur dann in eine Kategorie einfügen, wenn die Kategorie existiert:

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

Wenn es keine solche Kategorie gibt, gibt das SELECT null Zeilen zurück und das INSERT ist ein no-op.

Beide Fälle erzeugen eine gemeinsame Sperre (S-Sperre) für die Kategorientabelle.

Demonstration eines S-Locks:

In einer Sitzung führe ich Folgendes aus:

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

In der zweiten Sitzung führe ich Folgendes aus:

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

Wie Sie sehen, erzeugt dies eine IS-Sperre auf der Tabelle foo und eine S-Sperre auf einer Zeile von foo, der Tabelle, aus der ich lese.

Dasselbe passiert für alle hybriden Lese-/Schreiboperationen wie SELECT...FOR UPDATE , INSERT...SELECT , CREATE TABLE...SELECT , um zu verhindern, dass die gelesenen Zeilen geändert werden, während sie als Quelle für den Schreibvorgang benötigt werden.

Die IS-Sperre ist eine Sperre auf Tabellenebene, die DDL-Operationen für die Tabelle verhindert, sodass niemand DROP TABLE ausgibt oder ALTER TABLE während diese Transaktion von einigen Inhalten in der Tabelle abhängt.