2012-06-13 23 views

Odpowiedz

24

Oprócz korzystania z transakcji, jak powiedział Imad (które powinno być obowiązkowe mimo to), możesz również wykonać kontrolę poprawności, na które wiersze ma wpływ uruchomienie selekcji przy użyciu tej samej klauzuli WHERE co UPDATE.

Więc jeśli UPDATE jest

UPDATE foo 
    SET bar = 42 
WHERE col1 = 1 
    AND col2 = 'foobar'; 

Poniższa pokaże, które będą aktualizowane wiersze:

SELECT * 
FROM foo 
WHERE col1 = 1 
    AND col2 = 'foobar'; 
+1

Korzystanie z transakcji jest lepsze, aby następnie sprawdzić dane. Zakładając, że chce sprawdzić wynik, dochodzę do wniosku, że jego wypowiedź jest bardziej złożona niż "SET bar = 42", więc w trakcie jego sesji będzie mógł wykonać kilka zapytań, aby przetestować wynikowy zestaw danych ... –

+1

@ImadMoqaddem: Zgadzam się i dlatego napisałem "* Oprócz użycia transakcji, jak powiedział Imad *" –

+0

A jeśli masz "FOREIGN KEY UPDATE CASCADE" Twój sql nie powiedzie się – Green

40

AUTOCOMMIT OFF ...

MySQL

set autocommit=0; 

Ustawia autommit off dla bieżącej sesji.

Wykonujesz wyciąg, widzisz, co się zmieniło, a następnie wycofujesz, jeśli jest błędny lub zatwierdzasz, jeśli jest to zgodne z oczekiwaniami!

EDYCJA: Zaletą korzystania z transakcji zamiast uruchamiania kwerendy wyboru jest łatwiejsze sprawdzenie wynikowego zestawu.

+7

Sprawdź, czy transakcje obsługujące tabelę obsługują ... –

+4

@dystroy: każdy rozsądny system DBMS obsługuje transakcje. –

+3

Pamiętaj tylko, aby szybko zatwierdzić lub wycofać transakcję, lub ryzykujesz zablokowanie innych transakcji - aw najgorszym przypadku - zatrzymanie aplikacji. Nie jest to dobry pomysł, aby wykonać zapytanie, a następnie zjeść lunch, a następnie wrócić, aby zobaczyć wyniki! :-) –

1

Wykonaj zapytanie o wybór w tej samej tabeli z wszystkimi warunkami where, które stosujesz w zapytaniu o aktualizację.

0

dokonać SELECT go,

jak jeśli masz

UPDATE users SET id=0 WHERE name='jan'

przekształcić go

SELECT * FROM users WHERE name='jan'

3

Nie bezpośrednia odpowiedź, ale widziałem wiele borked sytuacje danych prod że można było uniknąć przez wpisując WHERE klauzula pierwszy! Czasami WHERE 1 = 0 może pomóc w bezpiecznym złożeniu oświadczenia roboczego. Przydatne może być także spojrzenie na szacowany plan wykonania, który oszacuje liczbę dotkniętych wierszy. Poza tym w transakcji, którą wycofujesz, jak powiedzieli inni.

+1

Co jest nie tak z "GDZIE FAŁSZ"? – SystemParadox

+0

@SystemParadox - nic, chociaż "GDZIE 1 = 0" jest bardziej przenośne, jeśli ktoś natknie się na to, kto pracuje z innym systemem DBMS. Na przykład SQL Server nie zaakceptuje "WHERE FALSE". –

6

wiem, że to jest powtórzeniem innych odpowiedzi, ale ma pewne wsparcie emocjonalne wziąć dodatkowy krok do aktualizacji Testowanie: D

do aktualizacji testowania, hash # jest twoim przyjacielem.

Jeśli masz instrukcję aktualizacji takiego:

UPDATE 
wp_history 
SET history_by="admin" 
WHERE 
history_ip LIKE '123%' 

You hash UPDATE i wyruszył do testowania, a następnie mieszania ich z powrotem w:

SELECT * FROM 
#UPDATE 
wp_history 
#SET history_by="admin" 
WHERE 
history_ip LIKE '123%' 

działa dla prostych stwierdzeń.

Dodatkowym, praktycznie obowiązkowym rozwiązaniem jest pobranie kopii (kopii zapasowej) za każdym razem, gdy używa się aktualizacji na stole produkcyjnym. Phpmyadmin> operacje> copy: table_yearmontday. Zajmuje to tylko kilka sekund dla tabel < = 100M.

33

Co z transakcjami? Mają funkcję ROLLBACK.

@see https://dev.mysql.com/doc/refman/5.0/en/commit.html

Na przykład:

START TRANSACTION; 
SELECT * FROM nicetable WHERE somthing=1; 
UPDATE nicetable SET nicefield='VALUE' WHERE somthing=1; 
SELECT * FROM nicetable WHERE somthing=1; #check 

COMMIT; 
# or if you want to reset changes 
ROLLBACK; 

SELECT * FROM nicetable WHERE somthing=1; #should be the old value 

Odpowiedź na pytanie @rickozoe poniżej:

Ogólnie linie te nie będą wykonywane tak jak kiedyś. W PHP f.e. możesz napisać coś takiego (być może trochę czystsze, ale chciał odpowiedzieć na szybko ;-)):

$MysqlConnection->query('START TRANSACTION;'); 
$erg = $MysqlConnection->query('UPDATE MyGuests SET lastname='Doe' WHERE id=2;'); 
if($erg) 
    $MysqlConnection->query('COMMIT;'); 
else 
    $MysqlConnection->query('ROLLBACK;'); 

Innym sposobem byłoby wykorzystanie zmiennych MySQL (patrz https://dev.mysql.com/doc/refman/5.7/en/user-variables.htm l i https://stackoverflow.com/a/18499823/1416909 ):

# do some stuff that should be conditionally rollbacked later on 

SET @v1 := UPDATE MyGuests SET lastname='Doe' WHERE id=2; 
IF(v1 < 1) THEN 
    ROLLBACK; 
ELSE 
    COMMIT; 
END IF; 

Ale proponuję użyć wrapperów dostępnych w twoim ulubionym języku programowania.

+0

Ładne, bezpieczne podejście, dzięki. – input

+0

Powoduje to nieoczekiwane wyniki w przypadku transakcji zagnieżdżonych. – scones

+0

Czy możesz podać przykład? –