Anche i codici di errore sono errati nelle query SQL?

1

Ho una query SQL che fa diverse cose contemporaneamente¹: fa più controlli e poi, se i controlli passano, aggiorna alcuni dati. Senza entrare nei dettagli specifici del dominio, ecco un esempio immaginario:

-- The user password should be updated only if the user account is not removed and
-- not locked, and the threshold was not exceeded.
if exists (select * from [People].[User] where [UserId] = @UserId)
begin
    if exists (select * from [People].[User] where [UserId] = @UserId and [IsLocked] = 0)
    begin
        if exists (select * from [People].[User]
                   where [UserId] = @UserId and [IsRemoved] = 0)
        begin
            update [People].[User] set [PasswordHash] = @Hash where [UserId] = @UserId
            select 0 -- Success.
        end
        else
        begin
            select 3 -- The account doesn't exist any longer.
        end
    end
    else
    begin
        select 2 -- The account is locked.
    end
end
else
begin
    select 1 -- The user cannot be found.
end

La query viene quindi utilizzata in questo modo:

var errorCode = new SqlDataQuery(query, Program.ConnectionString)
    .With(new { UserId = this.Id, Hash = this.ComputeHash() })
    .ReadValue<int>();

// Error codes are used only between the database and code, and transformed into exceptions
// as soon as possible.
switch (errorCode)
{
    case 1: throw new UserNotFoundException();
    case 2: throw new AccountPermissionException();
    case 3: throw new AccountRemovedException();
}

Nella programmazione generale, i codici di errore sono considerati negativi e dovrebbero essere sostituiti da procedure convenzionali di gestione degli errori, incluse le eccezioni.

È anche cattivo utilizzarli nelle query SQL? Se sì, come dovrei riscrivere la query per seguire le best practice?

¹ Dati i requisiti non funzionali relativi al carico e alle prestazioni, non c'è modo di fare più query consecutive. Tutti i controlli e l'aggiornamento devono essere eseguiti in una singola query.

    
posta Arseni Mourzenko 29.04.2013 - 23:26
fonte

2 risposte

1

A seconda dell'implementazione SQL, potresti avere un RAISE , RAISERROR o un'istruzione simile che puoi usare nella tua query per fallire l'operazione con un risultato simile a un'eccezione. Questa è la migliore risposta.

    
risposta data 30.04.2013 - 00:07
fonte
1

Invece di affidarti alla logica del controllo del flusso nel tuo database, perché non recuperare i dati e gestirli nel codice dell'app?

select userid, islocked, isremoved from [People].[User] where [UserId] = @UserId

In base alla presenza o meno di un record o ai valori di IsLocked e IsRemvoed, è possibile aggiornare i dati o generare errori.

Non conosco altri RDBS, ma SQL Server ha blocchi Try / Catch che possono anche gestire vari tipi di errori.

    
risposta data 30.04.2013 - 20:23
fonte

Leggi altre domande sui tag