2013-04-07 17 views
5

Sto imparando transazioni MySQL. Ho cercato risposte a questo, ma sembrano tutti usare PHP per fare ciò che voglio fare lavorare. Ecco l'esempio di quello che sto cercando di fare:come sapere se un inserto mysql ha successo

  1. Iniziare la transazione
  2. aggiornamento Table1
  3. Inserire nel Table2
  4. Se Insert è successo, a. quindi inserire in Table3 e commit. b. altrimenti rollback della transazione.

Non capisco come determinare a livello di programmazione se l'inserimento nel passaggio 3 ha avuto esito positivo. Certo, posso interrogare la tabella e vedere, ma ho pensato che ci fosse un modo per usare il valore di ritorno, ma sembra che funzioni solo quando sto usando PHP per fare la transazione.

Questo è il blocco di codice per quello che sto cercando - non funziona:

begin; 
start transaction; 
-- attempt to reduce inventory 
update store_inventory set item_qty = item_qty - 2 where id = 1; 
update store_inventory set item_qty = item_qty -1 where id = 5; 

-- insert the order record and check whether it succeded 
insert into store_orders (purchaser_name, purchase_date) 
values ('test user', now()); 
    -- if successful, do final insert and commit 
if Row_Count() > 0 Then  
insert into store_inventory (order_id, inventory_id, item_qty) 
values (1, 1, 2), 
     (1, 2, 1); 
commit; 
else -- otherwise rollback 
rollback; 
end if; 

end; 
+2

Quale lingua e adattatore stai utilizzando per provare ed eseguire queste azioni? –

+0

Utilizzo editor di query MySQL Workbench. –

+0

Quindi stai provando a vedere se l'inserimento ha avuto successo in una seguente query? –

risposta

2

La risposta è un mix di Itay Moav-Malimovka e la risposta di Gordon.

Tutto tra start transaction e commit è un'azione atomica. Basta scriverlo in questo modo:

start transaction; 
-- attempt to reduce inventory 
update store_inventory set item_qty = item_qty - 2 where id = 1; 
update store_inventory set item_qty = item_qty -1 where id = 5; 

-- insert the order record 
insert into store_orders (purchaser_name, purchase_date) 
values ('test user', now()); 
insert into store_inventory (order_id, inventory_id, item_qty) 
values (1, 1, 2), 
     (1, 2, 1); 
commit; 

Oppure vorrei spiegarlo su un esempio più semplice di quello che sta succedendo.

create table foo(id int primary key); 
insert into foo values (1); 

Ora, se si dispone di codice come questo:

start transaction; 
insert into foo values(2); 
insert into foo values(1); 
insert into foo values(3); 
commit; 

viene generato un errore quando il valore 1 viene inserito perché viola la chiave primaria, una voce con 1 esiste già e il codice che segue non verrà mai eseguito. Se fai un select * from foo; ora, vedrai, c'è un valore di 2 nella tua tabella.Ma probabilmente è solo tu che vedi il 2 lì, che dipende dal livello di isolamento (potresti voler leggere su quelli). Questo perché la transazione è ancora in sospeso. Ora tocca a te, se non ti interessa e continua con l'inserimento del valore 3 e commit o il rollback. MA questo viene fatto a livello di applicazione. Basta verificare un errore, se uno è stato sollevato il rollback, in caso contrario, va tutto bene. Non c'è c'è bisogno di controllare all'interno della transazione, perché se qualcosa va storto/l'inserto non riesce, il codice per verificare se non verrà mai raggiunto niente fallito.

+0

Grazie a @tombom. Penso che stavo solo guidando sulla strada sbagliata; pensando che tutto ciò potrebbe essere fatto all'interno di una transazione e semplicemente all'interno di MySQL stesso, senza utilizzare un proc memorizzato. –

+0

Non sono sicuro che tu mi abbia capito correttamente. Puoi farlo in una stored procedure, ma non devi. – fancyPants

0

SE tutte le query sono all'interno della stessa transazione, allora è considerata un'azione atomica. O ALL riuscito o ALL fallire.
Non è necessario controllare e utilizzare le transazioni.

+0

Ma la transazione non termina finché non lo faccio tornare indietro o lo impegno. Come faccio a sapere quale comando utilizzare se non riesco a capire se il successo/fallimento dell'inserimento è stato inserito in table2? Il tuo commento sembra indicare che i due comandi sono inutili. –

1

Probabilmente avrete bisogno di procedure memorizzate, ma potrei sbagliarmi essendo questo un requisito. Avrai bisogno di configurare le transazioni da solo e fare qualche test.

DELIMITER $$ 
CREATE PROCEDURE `sample`(name VARCHAR(100)) 
BEGIN 
    START TRANSACTION; -- Begin a transaction 
    INSERT INTO `users` (`name`) VALUES name; 
    IF ROW_COUNT() > 0 THEN -- ROW_COUNT() returns the number of rows updated/inserted/deleted 
     COMMIT; -- Finalize the transaction 
    ELSE 
     ROLLBACK; -- Revert all changes made before the transaction began 
    END IF 
END$$ 
DELIMITER ; 

Qualcosa di simile può funzionare (questo non è testato, puramente messo insieme dalla ricerca) e si dovrà utilizzare InnoDB come il motore di memorizzazione perché MyISAM non supporta le transazioni.

+1

http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_row-count – mbrownnyc

0

se si utilizza java e JPA è possibile utilizzare l'annotazione @TransactionManagement(TransactionManagementType.CONTAINER) nel bean che si sta utilizzando per fare inserimenti. questo assicurerà che se una transazione fallisce, il contenitore annulla tutte le modifiche. puoi google EJB 3.0 per saperne di più sulla gestione delle transazioni

Problemi correlati