Uso le stored procedure il più possibile per una serie di motivi.
Ridurre round trip al database
Se è necessario modificare più tabelle correlate in una sola volta, quindi è possibile utilizzare un singolo stored procedure in modo che è fatta solo una chiamata al database.
definire chiaramente la logica di business
Se certe cose devono essere vere su una query, quindi una procedura di memorizzazione permette di qualcuno che conosce SQL (un linguaggio abbastanza semplice) assicurano che le cose sono fatte bene.
Creare semplici interfacce per altri programmatori
I suoi compagni di squadra competenti non SQL possono utilizzare interfacce molto più semplice per il database e si può essere certi che non possono mettere le relazioni in cattivo stato in incidente.
considerare:
SELECT a.first_name, IFNULL(b.plan_id, 0) AS plan_id
FROM account AS a
LEFT JOIN subscription AS s ON s.account_id = a.id
WHERE a.id = 23
Rispetto a:
CALL account_get_current_plan_id(23);
scrivere loro un bel po 'involucro di prendersi cura di gestire le chiamate di stored procedure e sono nel mondo degli affari.
aggiornamento tutti gli utilizzi in un sistema in una volta
Se tutti usano le stored procedure per interrogare il database ed è necessario cambiare come funziona qualcosa, è possibile aggiornare la stored procedure e viene aggiornato ovunque il più a lungo non cambi l'interfaccia.
sicurezza forzate
Se è possibile utilizzare solo le stored procedure di fare tutto all'interno del vostro sistema, allora si può dare i permessi seriamente limitate all'account utente che accede ai dati. Non c'è bisogno di dare loro le autorizzazioni UPDATE, DELETE o SELECT.
facile movimentazione
Molte persone non si rendono conto dell'errore, ma è possibile creare le stored procedure in modo tale che la maggior parte dei problemi rintracciare diventa molto facile.
È anche possibile integrare il codice base per gestire correttamente gli errori restituiti se si utilizza una buona struttura.
Ecco un esempio che fa il seguente:
- utilizza un gestore di uscita per problemi seri
- Utilizza un gestore di proseguire per problemi meno gravi
- Fa non tabella di convalida di scansione in attacco
- Verifica di scansione della tabella successiva se la convalida non è fallita
- Esegue l'elaborazione in una transazione se le cose convalidano
- rollback tutto se c'è un problema
- segnala eventuali problemi riscontrati
- Evita aggiornamenti inutili
Qui è la struttura interna di una stored procedure costituito che accetta un ID account, l'account chiusura id, e un indirizzo IP e quindi li utilizza per aggiornare in modo appropriato. Il delimitatore è già stato impostato su $$:
BEGIN
# Helper variables
DECLARE r_code INT UNSIGNED;
DECLARE r_message VARCHAR(128);
DECLARE it_exists INT UNSIGNED;
DECLARE n_affected INT UNSIGNED;
# Exception handler - for when you have written bad code
# - or something really bad happens to the server
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
SELECT 0 as `id`, 10001 as `code`, CONCAT(r_message, ' Failed with exception') as `message`;
END;
# Warning handler - to tell you exactly where problems are
DECLARE CONTINUE HANDLER FOR SQLWARNING
BEGIN
SET r_code = 20001, r_message = CONCAT(r_message, 'WARNING');
END;
SET r_code = 0, r_message = '', it_exists = 0, n_affected = 0;
# STEP 1 - Obvious basic sanity checking (no table scans needed)
IF (0 = i_account_id) THEN
SET r_code = 40001, r_message = 'You must specify an account to close';
ELSEIF (0 = i_updated_by_id) THEN
SET r_code = 40002, r_message = 'You must specify the account doing the closing';
END IF;
# STEP 2 - Any checks requiring table scans
# Given account must exist in system
IF (0 = r_code) THEN
SELECT COUNT(id) INTO it_exists
FROM account
WHERE id = i_account_id;
IF (0 = it_exists) THEN
SET r_code = 40001, r_message = 'Account to close does not exist in the system';
END IF;
END IF;
# Given account must not already be closed
# - if already closed, we simply treat the call as a success
# - and don't bother with further processing
IF (0 = r_code) THEN
SELECT COUNT(id) INTO it_exists
FROM account
WHERE id = i_account_id AND status_id = 2;
IF (0 < it_exists) THEN
SET r_code = 1, r_message = 'already closed';
END IF;
END IF;
# Given closer account must be valid
IF (0 = r_code) THEN
SELECT COUNT(id) INTO it_exists
FROM account
WHERE id = i_updated_by_id;
END IF;
# STEP 3 - The actual update and related updates
# r-message stages are used in case of warnings to tell exactly where a problem occurred
IF (0 = r_code) THEN
SET r_message = CONCAT(r_message, 'a');
START TRANSACTION;
# Add the unmodified account record to our log
INSERT INTO account_log (field_list)
SELECT field_list
FROM account
WHERE id = i_account_id;
IF (0 = r_code) THEN
SET n_affected = ROW_COUNT();
IF (0 = n_affected) THEN
SET r_code = 20002, r_message = 'Failed to create account log record';
END IF;
END IF;
# Update the account now that we have backed it up
IF (0 = r_code) THEN
SET r_message = CONCAT(r_message, 'b');
UPDATE account
SET
status_id = 2,
updated_by_id = i_updated_by_id,
updated_by_ip = i_updated_by_ip
WHERE id = i_account_id;
IF (0 = r_code) THEN
SET n_affected = ROW_COUNT();
IF (0 = n_affected) THEN
SET r_code = 20003, r_message = 'Failed to update account status';
END IF;
END IF;
END IF;
# Delete some related data
IF (0 = r_code) THEN
SET r_message = CONCAT(r_message, 'c');
DELETE FROM something
WHERE account_id = i_account_id;
END IF;
# Commit or roll back our transaction based on our current code
IF (0 = r_code) THEN
SET r_code = 1, r_message = 'success';
COMMIT;
ELSE
ROLLBACK;
END IF;
END IF;
SELECT
r_code as `code`,
r_message as `message`,
n_affected as `affected`;
END$$
significati codice di stato:
- 0: non dovrebbe mai accadere - cattivo risultato
- 1: successo - il conto è stato sia già chiuso o correttamente chiusa
- 2xxxx - problemi di logica o sintassi
- 3xxxx - problemi con valori di dati imprevisti nel sistema
- 4XXXX - campi mancanti mancanti
Piuttosto che fidarsi dei programmatori che non hanno familiarità con i database (o semplicemente non hanno familiarità con lo schema), è molto più semplice fornire loro interfacce.
Invece di fare tutti i controlli di cui sopra, si può semplicemente utilizzare:
CALL account_close_by_id(23);
e quindi controllare il codice risultato e prendere i provvedimenti opportuni.
Personalmente, credo che se si ha accesso alle stored procedure e non le si sta utilizzando, allora dovresti davvero utilizzarle.
Questo argomento SO è rilevante, anche se sta utilizzando lo stack C#/MSSQL. La domanda è la stessa: stored procedure o SQL dinamico: http://stackoverflow.com/questions/15142/what-are-the-pros-and-cons-to-keeping-sql-in-stored-procs-versus- codice – leepowers
Molto da vedere per entrambi i campi. Non è un caso chiaro per entrambi. – Wrikken
Lettura consigliata: http://www.paragoncorporation.com/ArticleDetail.aspx?ArticleID=28 – NullUserException