← Cloudflare D1 / d1 / sql-api
Definování cizích klíčů
D1 podporuje definování a vynucování omezení cizích klíčů napříč tabulkami v databázi.
Omezení cizího klíče umožňují vynutit vztahy mezi tabulkami. Cizí klíče můžete použít například k vytvoření pevné vazby mezi user_id v users tabulku a user_id v orders tabulku, aby nebylo možné vytvořit objednávku vůči uživateli, který neexistuje.
Omezení cizího klíče vám také mohou zabránit ve smazání řádků, které odkazují na řádky v jiných tabulkách. Například smazání řádků z users tabulce, když jsou řádky v orders tabulky na ně odkazují.
Ve výchozím nastavení D1 vynucuje platnost omezení cizích klíčů ve všech dotazech a migracích. Jde o stejné chování, jaké byste pozorovali při nastavení PRAGMA foreign_keys = on v SQLite pro každou transakci.
Odložení omezení cizích klíčů
Při spuštění dotaz, migrace nebo import dat vůči databázi D1 mohou nastat situace, kdy je nutné během vytváření tabulky nebo změn schématu deaktivovat ověřování cizích klíčů.
Vynucování cizích klíčů v D1 odpovídá vynucování v SQLite PRAGMA foreign_keys = on direktivu. Protože D1 spouští každý dotaz uvnitř implicitní transakce, uživatelské dotazy ji nemohou během dotazu ani migrace změnit.
Místo toho vám D1 umožňuje volat PRAGMA defer_foreign_keys = on nebo off, což vám umožňuje dočasně porušit omezení cizích klíčů (do konce aktuální transakce).
Volání PRAGMA defer_foreign_keys = off nevypíná vynucování cizích klíčů mimo aktuální transakci. Pokud na konci transakce nemáte vyřešena nedokončená porušení cizích klíčů, transakce selže s chybou FOREIGN KEY constraint failed chyba.
Chcete-li odložit vynucování cizích klíčů, nastavte PRAGMA defer_foreign_keys = on na začátku transakce nebo před změnami, které by porušily omezení:
-- Defer foreign key enforcement in this transaction.
PRAGMA defer_foreign_keys = on
-- Run your CREATE TABLE or ALTER TABLE / COLUMN statements
ALTER TABLE users ...
-- This is implicit if not set by the end of the transaction.
PRAGMA defer_foreign_keys = offMůžete také explicitně nastavit PRAGMA defer_foreign_keys = off ihned poté, co vyřešíte nevyřízená omezení cizích klíčů. Pokud stále existují nevyřízená omezení cizích klíčů, obdržíte FOREIGN KEY constraint failed chybou a bude nutné porušení vyřešit.
Definování vztahu cizího klíče
Vztah cizího klíče lze definovat při vytváření tabulky pomocí CREATE TABLE nebo při přidávání sloupce do existující tabulky pomocí ALTER TABLE příkaz.
Jako příklad poslouží e-commerce web se dvěma tabulkami:
- A
userstabulku, která definuje společné vlastnosti uživatelského účtu, včetně jedinečnéhouser_ididentifikátor. -
orderstabulku, která mapuje objednávku zpět nauser_idv tabulce user.
Toto mapování je definováno jako FOREIGN KEY, což zajišťuje, že:
- Řádek nelze odstranit z
userstabulky, které by porušily omezení cizího klíče. To znamená, že nemůžete skončit s objednávkami, které nemají platného uživatele, na kterého by se mapovaly. ordersjsou vždy definovány vůči platnémuuser_id, což snižuje riziko vytvoření objednávek odkazujících na neplatné (nebo neexistující) uživatele.
CREATE TABLE users (
user_id INTEGER PRIMARY KEY,
email_address TEXT,
name TEXT,
metadata TEXT
)
CREATE TABLE orders (
order_id INTEGER PRIMARY KEY,
status INTEGER,
item_desc TEXT,
shipped_date INTEGER,
user_who_ordered INTEGER,
FOREIGN KEY(user_who_ordered) REFERENCES users(user_id)
)Pro jednu tabulku můžete definovat více vztahů cizích klíčů a definice cizích klíčů mohou odkazovat na více tabulek v rámci celého schématu databáze.
Akce cizího klíče
Můžete definovat akce jako součást definic cizích klíčů, abyste omezili nebo propagovali změny nadřazeného řádku (REFERENCES table(column)). Definování akce usnadňuje pochopení použití omezení cizích klíčů ve vaší aplikaci a pomáhá buď vyčistit související data, nebo zabránit jejich izolaci.
Při definování ON UPDATE a/nebo ON DELETE klauzule jako součást vztahu cizího klíče. Můžete také definovat různé akce pro ON UPDATE a ON DELETE v závislosti na vašich požadavcích.
CASCADE- Aktualizace nebo odstranění rodičovského klíče odstraní všechny přidružené podřízené klíče (řádky).RESTRICT- Rodičovský klíč nelze aktualizovat ani odstranit, pokud any podřízený klíč na něj odkazuje. Na rozdíl od výchozího vynucování cizích klíčů platí, že vztahy sRESTRICTse při aplikování vrací chyby okamžitě, nikoli až na konci transakce.SET DEFAULT- Nastaví podřízený sloupec (nebo sloupce), na které odkazuje definice cizího klíče, naDEFAULThodnotu definovanou ve schématu. Pokud není žádnáDEFAULTje nastaven na podřízených sloupcích, nelze tuto akci použít.SET NULL- Nastaví podřízený sloupec (nebo sloupce), na které odkazuje definice cizího klíče, na SQLNULL.NO ACTION- Neprovede žádnou akci.
V následujícím příkladu smazání uživatele z users tabulky odstraní všechny související řádky v scores tabulku, jak jste definovali ON DELETE CASCADE. Odstraňte všechny související řádky v scores tabulky, pokud si nechcete ponechávat skóre uživatelů, které jste zcela smazali. To může znamenat, že ostatní uživatelé už nemohou vyhledávat ani odkazovat na skóre, která byla ještě platná.
CREATE TABLE users (
user_id INTEGER PRIMARY KEY,
email_address TEXT,
)
CREATE TABLE scores (
score_id INTEGER PRIMARY KEY,
game TEXT,
score INTEGER,
player_id INTEGER,
FOREIGN KEY(player_id) REFERENCES users(user_id) ON DELETE CASCADE
)Další kroky
- Přečtěte si SQLite
FOREIGN KEY↗ dokumentace. - Přečtěte si, jak použijte D1 Workers Binding API z Workeru.
- Pochopte, jak fungují migrace databáze s D1.