Transakcja w SQL jest jednostką wykonania, która grupuje jedno lub więcej zadań razem. Transakcja jest uważana za udaną, jeśli wszystkie zawarte w niej zadania są wykonywane bez błędów.
Jednakże, jeśli którekolwiek z zadań w ramach transakcji nie zostanie wykonane, cała transakcja zakończy się niepowodzeniem. Transakcja ma tylko dwa wyniki:udana lub nieudana.
Praktyczny scenariusz
Rozważmy praktyczny przykład bankomatu (automatycznego bankomatu). Idziesz do bankomatu, a on prosi o kartę. Uruchamia zapytanie, aby sprawdzić, czy karta jest ważna, czy nie. Następnie prosi o podanie kodu PIN. Ponownie uruchamia zapytanie, aby dopasować kod PIN. Bankomat poprosi Cię o kwotę, którą chcesz wypłacić, a Ty wprowadzisz żądaną kwotę. Bankomat wykonuje kolejne zapytanie, aby potrącić tę kwotę z Twojego konta, a następnie przekaże Ci środki.
Co się stanie, jeśli kwota zostanie potrącona z twojego konta, a następnie system ulegnie awarii z powodu awarii zasilania bez wydawania banknotów?
Jest to problematyczne, ponieważ klient ma potrącone środki bez otrzymania żadnych pieniędzy. W tym miejscu transakcje mogą być przydatne.
W przypadku awarii systemu lub innego błędu, wszystkie zadania w ramach transakcji zostaną wycofane. Dlatego w przypadku bankomatu kwota zostanie zwrócona na Twoje konto, jeśli z jakiegokolwiek powodu nie będziesz mógł jej wypłacić.
Co to jest transakcja?
Najprostsza zmiana w tabeli bazy danych jest transakcją. Dlatego wyciągi INSERT, UPDATE i DELETE są wyciągami transakcji. Kiedy piszesz zapytanie, wykonywana jest transakcja. Jednak tej transakcji nie można cofnąć. Zobaczymy, jak transakcje są tworzone, zatwierdzane i wycofywane poniżej, ale najpierw utwórzmy kilka fikcyjnych danych do pracy.
Przygotowywanie danych
Uruchom następujący skrypt na serwerze bazy danych.
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)
Powyższy skrypt SQL tworzy schooldb bazy danych. W tej bazie danych tworzona jest tabela student i do tej tabeli dodawane są niektóre dane fikcyjne.
Wykonywanie zapytań bez transakcji
Wykonajmy trzy standardowe zapytania. W tej chwili nie korzystamy z transakcji.
INSERT INTO student VALUES (6, 'Suzi', 'Female', 25, 395) UPDATE student SET age = 'Six' WHERE id= 6 DELETE from student WHERE id = 6
Tutaj pierwsze zapytanie wstawia rekord ucznia do bazy danych. Drugie zapytanie aktualizuje wiek ucznia, a trzecie zapytanie usuwa nowo wstawiony rekord.
Jeśli wykonasz powyższy skrypt, zobaczysz, że rekord zostanie wstawiony do bazy danych, a następnie wystąpi błąd podczas wykonywania drugiego zapytania.
Jeśli spojrzysz na drugie zapytanie, aktualizujemy wiek, przechowując wartość ciągu w kolumnie wiek, która może przechowywać dane typu liczb całkowitych. Dlatego zostanie zgłoszony błąd. Jednak pierwsze zapytanie nadal zakończy się pomyślnie. Oznacza to, że jeśli wybierzesz wszystkie rekordy z tabeli uczniów, zobaczysz nowo wstawiony rekord.
[identyfikator tabeli=23 /]
Widać, że rekord o id=6 i nazwie „Suzi” został wstawiony do bazy danych. Nie udało się jednak zaktualizować wieku, a drugie zapytanie nie powiodło się.
A co, jeśli tego nie chcemy? A co jeśli chcemy mieć pewność, że albo wszystkie zapytania zostaną wykonane pomyślnie, albo żadne z nich nie zostanie wykonane w ogóle? Tutaj przydają się transakcje.
Wykonywanie zapytań z transakcjami
Teraz wykonajmy trzy powyższe zapytania w ramach transakcji.
Najpierw zobaczmy, jak utworzyć i zatwierdzić transakcję.
Tworzenie transakcji
Aby uruchomić zapytanie/zapytania jako transakcję, po prostu umieść zapytania w słowach kluczowych BEGIN TRANSACTION i COMMIT TRANSACTION. BEGIN TRANSACTION deklaruje początek TRANSAKCJI, natomiast COMMIT TRANSACTION stwierdza, że transakcja została zakończona.
Wykonajmy trzy nowe zapytania do bazy danych, którą utworzyliśmy wcześniej jako transakcję. Dodamy nowy rekord dla nowego ucznia z identyfikatorem 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
Kiedy powyższa transakcja zostanie wykonana, ponownie wystąpi błąd w drugim zapytaniu, ponieważ ponownie wartość typu string jest przechowywana w kolumnie age, która przechowuje tylko dane typu integer.
Jednakże, ponieważ błąd występuje wewnątrz transakcji, wszystkie zapytania, które zostały pomyślnie wykonane przed wystąpieniem tego błędu, zostaną automatycznie wycofane. W związku z tym pierwsze zapytanie, które wstawia nowy rekord ucznia o identyfikatorze =7 i nazwie „Jena”, również zostanie wycofane.
Teraz, jeśli wybierzesz wszystkie rekordy z tabeli uczniów, zobaczysz, że nowy rekord dla „Jeny” nie został wstawiony.
Ręczne przywracanie transakcji
Wiemy, że jeśli zapytanie spowoduje błąd w transakcji, cała transakcja, w tym wszystkie zapytania już wykonane, są automatycznie wycofywane. Możemy jednak również ręcznie wycofać transakcję ręcznie, kiedy tylko chcemy.
W celu wycofania transakcji używa się słowa kluczowego ROLLBACK, po którym następuje nazwa transakcji. Aby nazwać transakcję, używana jest następująca składnia:
BEGIN TRANSACTION Transaction_name
Załóżmy, że chcemy, aby nasza tabela uczniów nie zawierała rekordów zawierających zduplikowane nazwiska uczniów. Dodamy rekord dla nowego ucznia. Sprawdzimy wtedy, czy w bazie istnieje uczeń o nazwisku identycznym z nazwiskiem nowo wstawionego ucznia. Jeśli uczeń o tym nazwisku jeszcze nie istnieje, zatwierdzimy naszą transakcję. Jeśli uczeń o tym nazwisku istnieje, wycofamy naszą transakcję. W naszym zapytaniu użyjemy instrukcji warunkowych.
Spójrz na następującą transakcję:
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
Przyjrzyj się uważnie powyższemu skryptowi. Dużo się tu dzieje.
W pierwszym wierszu tworzymy zmienną SQL typu integer NameCount.
Następnie rozpoczynamy transakcję o nazwie „AddStudent”. Transakcji możesz nadać dowolną nazwę.
W ramach transakcji wstawiliśmy nowy rekord dla ucznia o id =8 i nazwisku „Jacob”.
Następnie, korzystając z funkcji agregującej LICZBA, zliczamy liczbę rekordów uczniów, których imię to „Jacob” i zapisujemy wynik w zmiennej „Imię Liczba”.
Jeśli wartość zmiennej jest większa niż 1, oznacza to, że uczeń o imieniu „Jacob” już istnieje w bazie. W takim przypadku cofamy naszą transakcję i DRUKUJEMY komunikat na ekranie, że „Student o tym nazwisku już istnieje”.
Jeśli nie, zatwierdzamy naszą transakcję i wyświetlamy komunikat „Nowy rekord został pomyślnie dodany”.
Gdy po raz pierwszy uruchomisz powyższą transakcję, nie będzie rekordu ucznia o imieniu „Jacob”. Dlatego transakcja zostanie zatwierdzona i zostanie wydrukowany następujący komunikat:
Teraz spróbuj uruchomić następujący skrypt SQL na serwerze:
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
Tutaj ponownie wstawiamy rekord ucznia o identyfikatorze =9 i nazwisku „Jacob”. Ponieważ rekord ucznia o imieniu „Jacob” już istnieje w bazie danych, transakcja zostanie wycofana i zostanie wydrukowany następujący komunikat:
Przydatne linki
- Klasy dotyczące transakcji SQL