sql >> Databáze >  >> RDS >> Database

Pochopení transakcí v SQL

Transakce v SQL je jednotka provádění, která seskupuje jeden nebo více úkolů dohromady. Transakce je považována za úspěšnou, pokud jsou všechny úkoly v ní provedeny bez chyby.

Pokud se však některá z úloh v rámci transakce neprovede, celá transakce selže. Transakce má pouze dva výsledky:úspěšná nebo neúspěšná.

Praktický scénář

Zvažte praktický příklad bankomatu (Automated Teller Machine). Jdete k bankomatu a ten vás požádá o kartu. Spustí dotaz, zda je karta platná či nikoli. Dále se vás zeptá na váš PIN kód. Znovu spustí dotaz, aby odpovídal PIN kódu. Bankomat se vás pak zeptá na částku, kterou chcete vybrat, a vy zadáte částku, kterou byste chtěli. Bankomat provede další dotaz k odečtení této částky z vašeho účtu a poté vám peníze vydá.

Co když je částka stržena z vašeho účtu a poté dojde k selhání systému kvůli výpadku napájení, aniž by byly vydány bankovky?

To je problematické, protože zákazníkovi jsou odečteny prostředky, aniž by nějaké peníze obdržel. Zde mohou být transakce užitečné.

V případě zhroucení systému nebo jakékoli jiné chyby budou všechny úkoly v rámci transakce vráceny zpět. V případě bankomatu vám tedy bude částka připsána zpět na váš účet, pokud si ji nebudete moci z jakéhokoli důvodu vybrat.

Co je to transakce?

V nejjednodušší podobě je změna v databázové tabulce transakcí. Proto příkazy INSERT, UPDATE a DELETE jsou všechny výpisy transakcí. Když napíšete dotaz, provede se transakce. Tuto transakci však nelze vrátit zpět. Níže uvidíme, jak jsou transakce vytvářeny, schvalovány a vráceny zpět, ale nejprve si vytvořte fiktivní data, se kterými budeme pracovat.

Příprava dat

Spusťte na svém databázovém serveru následující skript.

CREATE DATABASE schooldb

CREATE TABLE student
(
    id INT PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    gender VARCHAR(50) NOT NULL,
    age INT NOT NULL,
    total_score INT NOT NULL,
    
 )

INSERT INTO student 

VALUES (1, 'Jolly', 'Female', 20, 500), 
(2, 'Jon', 'Male', 22, 545), 
(3, 'Sara', 'Female', 25, 600), 
(4, 'Laura', 'Female', 18, 400), 
(5, 'Alan', 'Male', 20, 500)

Výše uvedený SQL skript vytvoří databázi schooldb. V této databázi se vytvoří student tabulky a do této tabulky se přidají nějaká fiktivní data.

Provádění dotazů bez transakcí

Proveme tři standardní dotazy. Momentálně nepoužíváme transakce.

INSERT INTO student 
VALUES (6, 'Suzi', 'Female', 25, 395)

UPDATE student
SET age = 'Six' WHERE id= 6

DELETE from student
WHERE id = 6

Zde první dotaz vloží záznam studenta do databáze. Druhý dotaz aktualizuje věk studenta a třetí dotaz smaže nově vložený záznam.

Pokud spustíte výše uvedený skript, uvidíte, že záznam bude vložen do databáze a poté dojde k chybě při provádění druhého dotazu.

Pokud se podíváte na druhý dotaz, aktualizujeme stáří uložením hodnoty řetězce do sloupce stáří, do kterého lze uložit data typu celé číslo. Proto bude vyvolána chyba. První dotaz však bude stále úspěšně dokončen. To znamená, že pokud vyberete všechny záznamy z tabulky studentů, uvidíte nově vložený záznam.

[id tabulky=23 /]

Můžete vidět, že záznam s id=6 a jménem ‚Suzi‘ byl vložen do databáze. Stáří však nebylo možné aktualizovat a druhý dotaz se nezdařil.

Co když to nechceme? Co když si chceme být jisti, že se buď všechny dotazy provedou úspěšně, nebo se nespustí vůbec žádný z dotazů? Zde jsou transakce užitečné.

Provádění dotazů s transakcemi

Nyní provedeme tři výše uvedené dotazy v rámci transakce.

Nejprve se podívejme, jak vytvořit a potvrdit transakci.

Vytvoření transakce

Chcete-li spustit dotaz/dotazy jako transakci, jednoduše zabalte dotazy do klíčových slov BEGIN TRANSACTION a COMMIT TRANSACTION. BEGIN TRANSACTION deklaruje začátek TRANSAKCE, zatímco COMMIT TRANSACTION uvádí, že transakce byla dokončena.

Pojďme provést tři nové dotazy v databázi, kterou jsme dříve vytvořili jako transakci. Budeme přidávat nový záznam pro nového studenta s ID 7.

BEGIN TRANSACTION

	INSERT INTO student 
	VALUES (7, 'Jena', 'Female', 22, 456)

	UPDATE student
	SET age = 'Twenty Three' WHERE id= 7

	DELETE from student
	WHERE id = 7

COMMIT TRANSACTION

Když je výše uvedená transakce provedena, opět dojde k chybě ve druhém dotazu, protože opět je ve sloupci stáří uložena hodnota typu řetězec, který ukládá pouze data typu celé číslo.

Vzhledem k tomu, že k chybě dochází uvnitř transakce, budou všechny dotazy, které byly úspěšně provedeny před výskytem této chyby, automaticky vráceny zpět. Proto bude také vrácen první dotaz, který vloží nový záznam studenta s id =7 a jménem ‚Jena‘.

Pokud nyní vyberete všechny záznamy z tabulky studentů, uvidíte, že nový záznam pro ‚Jena‘ nebyl vložen.

Ruční vrácení transakce

Víme, že pokud dotaz vyvolá chybu v rámci transakce, celá transakce, včetně všech již provedených dotazů, se automaticky vrátí zpět. Transakci však můžeme kdykoli ručně vrátit zpět, kdykoli budeme chtít.

K vrácení transakce se použije klíčové slovo ROLLBACK následované názvem transakce. K pojmenování transakce se používá následující syntaxe:

BEGIN TRANSACTION Transaction_name

Předpokládejme, že chceme, aby naše tabulka studentů neměla žádné záznamy obsahující duplicitní jména studentů. Přidáme záznam pro nového studenta. Následně zkontrolujeme, zda v databázi existuje student se jménem shodným se jménem nově vloženého studenta. Pokud student s tímto jménem ještě neexistuje, potvrdíme naši transakci. Pokud student s tímto jménem existuje, vrátíme naši transakci zpět. V našem dotazu použijeme podmíněné příkazy.

Podívejte se na následující transakci:

DECLARE @NameCount int

BEGIN TRANSACTION AddStudent

	INSERT INTO student 
	VALUES (8, 'Jacob', 'Male', 21, 600)

	SELECT @NameCount = COUNT(*) FROM student WHERE name = 'Jacob'

	IF @NameCount > 1
		BEGIN 
			ROLLBACK TRANSACTION AddStudent
			PRINT 'A student with this name already exists'
		END
	ELSE
		BEGIN
			COMMIT TRANSACTION AddStudent
			PRINT 'New record added successfully'
		END

Pozorně si prohlédněte výše uvedený skript. Děje se tu spousta věcí.

Na prvním řádku vytvoříme proměnnou SQL typu celé číslo NameCount.

Dále zahájíme transakci s názvem „AddStudent“. Transakci můžete pojmenovat libovolným způsobem.

Do transakce jsme vložili nový záznam pro studenta s ID =8 a jménem ‚Jacob‘.

Dále pomocí agregační funkce COUNT spočítáme počet záznamů studentů, kde je jméno ‚Jacob‘, a výsledek uložíme do proměnné ‚NameCount‘.

Pokud je hodnota proměnné větší než 1, znamená to, že student se jménem ‚Jacob‘ již v databázi existuje. V takovém případě VRÁTíme naši transakci a VYTISKneme na obrazovku zprávu, že ‚Student s tímto jménem již existuje‘.

Pokud ne, potvrdíme naši transakci a zobrazíme zprávu ‚Nový záznam byl úspěšně přidán‘.

Když výše uvedenou transakci spustíte poprvé, nebude existovat záznam studenta se jménem ‚Jacob‘. Proto bude transakce potvrzena a vytiskne se následující zpráva:

Nyní zkuste na serveru spustit následující skript SQL:

DECLARE @NameCount int

BEGIN TRANSACTION AddStudent

	INSERT INTO student 
	VALUES (9, 'Jacob', 'Male', 22, 400)

	SELECT @NameCount = COUNT(*) FROM student WHERE name = 'Jacob'

	IF @NameCount > 1
		BEGIN 
			ROLLBACK TRANSACTION AddStudent
			PRINT 'A student with this name already exists'
		END
	ELSE
		BEGIN
			COMMIT TRANSACTION
			PRINT 'New record added successfully'
		END

Zde opět vkládáme záznam studenta s id =9 a jménem ‚Jacob‘. Protože záznam studenta se jménem ‚Jacob‘ již v databázi existuje, transakce se vrátí zpět a vytiskne se následující zpráva:

Užitečné odkazy

  • Třídy o transakcích SQL

  1. REGEX, chcete-li vybrat n-tou hodnotu ze seznamu, s možností null

  2. Jak přidat oddělovač do zřetězeného řetězce v MySQL – CONCAT_WS()

  3. Zjistěte historii SQL dotazů

  4. Jak mohu získat přístup k příkazovému řádku MySQL pomocí XAMPP pro Windows?