2009-02-25 14 views
6

OK, so che si può fare, lo faccio abbastanza spesso, ma perché è così difficile fare un ciclo in T-SQL? Posso pensare a un sacco di motivi che vorrei analizzare attraverso un set di risultati di query e fare qualcosa che semplicemente non può essere fatto senza un ciclo, eppure il codice per impostare ed eseguire il mio ciclo è> 20 righe.Perché è così difficile fare un ciclo in T-SQL

Sono sicuro che altri hanno opinioni simili, quindi perché siamo ancora senza un modo semplice per eseguire un ciclo?

Una parte: abbiamo finalmente ottenuto un UPSERT (ovvero MERGE) in SQL2008, quindi forse tutte le speranze non sono perse.

risposta

22

SQL è un set-based, declarative language; non procedurale o imperative language. T-SQL prova a cavalcare i due, ma è ancora costruito su un paradigma basato fondamentalmente su un set.

+0

Hai preso la strada giusta? – AnthonyWJones

+0

Whoops! hai ragione, ho incollato i miei collegamenti nell'ordine sbagliato :) grazie –

1

Perché SQL è un linguaggio basato su set. La potenza di sql è trovare un gruppo più piccolo all'interno di un gruppo più ampio di dati in base a caratteristiche specifiche. Per gestire questa attività, il looping è in gran parte inutile. Ovviamente è stato aggiunto per comodità di gestione di alcune situazioni, ma l'uso previsto del linguaggio rende questa funzionalità irrilevante.

2

T-SQL non è progettato per essere una lingua imperativa. È progettato per essere dichiarativo. La sua natura dichiarativa consente al optomizer di suddividere i vari compiti e di eseguirli in parallelo e in altri modi di fare le cose in un ordine che è più efficiente.

-2

Non sono un esperto di DB, ma credo che la natura atomica delle transazioni di database renderebbe difficile il raggiungimento di cicli perché la transazione è completa o non dovrebbe verificarsi affatto. Mantenere lo stato può essere fastidioso!

Wikipedia Article on Atomicity

0

SQL è un sistema basato SET, non un procedurale (anello) uno. Generalmente è considerata una cattiva pratica utilizzare i loop in SQL perché hanno prestazioni scarse rispetto ai loro equivalenti basati su set.

MENTRE è la struttura più comune looping, cursori possono essere utilizzati anche, ma hanno i loro problemi (dimenticando di/chiudere deallocare)

... un esempio di WHILE (potrebbe non essere necessario, ma altri possono)

DECLARE @iterator INT 
SET @iterator = 0 

WHILE @iterator < 20 
BEGIN 
    SELECT * FROM table WHERE rowKey = @iterator 
/*do stuff*/ 
    @iterator = @iterator + 1 
END 

La vera domanda è "Che cosa si sta tentando di fare che semplicemente non può essere fatto in un modo basato su set?"

10

mi viene in mente un sacco di ragioni che vorrei analizzare attraverso un risultato della query e fare qualcosa che semplicemente non può essere fatto senza un ciclo

E per la stragrande maggioranza dei quelli che posso mostrarti come farlo in un'operazione basata su set o spiegare perché dovrebbe essere fatto nel tuo codice cliente piuttosto che nel database. La necessità di eseguire un ciclo in sql è estremamente rara.

+1

Sono d'accordo che dovrebbero essere fatti nel codice cliente; tuttavia, quando elaboriamo milioni di record è 100x (1000x?) più veloce per fare tutto nel database anche se questo non è il "luogo" giusto per farlo. –

+1

Un esempio: esegui il ciclo attraverso ogni "adattamento" nel database ed esegui una stored procedure che si inserisce in una tabella e ne aggiorna un'altra in base ai valori del montaggio. Dobbiamo eseguirlo regolarmente, perché le tabelle che i valori vengono calcolati fuori cambiano regolarmente. Codice client = 1 giorno, SQL = 1 ora. –

+1

> "Sono d'accordo che dovrebbero essere fatte nel codice client, tuttavia," ... Questa è solo una parte di esso. L'altro è il refactoring da impostare in base. Per il tuo esempio di "montaggio", dovresti essere in grado di riscrivere la procedura memorizzata per operare sull'intera tabella. –

1

quasi tutto può essere fatto set base, provare a utilizzare una tabella di serie

Perché 20 righe? Questo è tutto ciò che serve

select *,identity(int, 1,1) as Someid into #temp 
from sysobjects 

declare @id int, @MaxId int 
select @id = 1,@MaxId = max(Someid) from #temp 

while @id < @MaxId 
begin 
-- do your stuff here 
print @id 
set @id [email protected] + 1 
end 
1

dipende da ciò che si desidera fare in un ciclo.utilizzando un ciclo while non è affatto difficile:

declare @i int 
set @i = 20 
while @i>0 begin 
... do some stuff 
set @i = @i-1 
end 

diventa ingombrante solo quando si utilizzano i cursori, che dovrebbero essere evitati comunque.

1

Si potrebbe provare a utilizzare le funzioni definite dall'utente per eseguire la maggior parte del lavoro invece di adottare un approccio basato sul ciclo. Ciò preserverebbe l'intenzione del linguaggio SQL su cui è impostato.

+0

mi piace questo. Ho intenzione di indagare. –

Problemi correlati