2010-10-11 5 views
1

Quel est le meilleur moyen de boucler sur les lignes d'une table de base de données dans SQL Server 2008 R2?Quelle est la meilleure façon de faire une boucle sur les lignes d'une table?

Je cherche quelque chose qui est assez similaire à l'écriture foreach() et assez performant.

Merci

+3

Vous souhaitez un CURSEUR? (Ugly "non-set" SQL ;-) –

+0

SQL n'a pas vraiment été conçu pour cela. Une raison particulière pour laquelle vous parcourez des lignes? – LittleBobbyTables

+0

SQL est intrinsèquement basé sur SET, pas basé sur ROW. Si vous pouvez répondre à vos besoins en termes de traitement d'ensemble, vous n'aurez pas la «dissonance cognitive» qui consiste à essayer de forcer des opérations en rangée sur un conteneur défini par l'utilisateur. – DaveE

Répondre

4

La plus performante: ne boucle pas sur les lignes d'une table. Utilisez des opérations basées sur des ensembles.

est ici a good discussion of WHY

1

Peut-être que vous voulez un curseur? Voir SQL Server Cursor Examples (fournit également des liens et discute des problèmes/alternatives/raisons). Il peut ou peut ne pas correspondre à la définition de 'meilleur' ​​- SQL DQL aime vraiment travailler avec 'set operations' (et c'est ce à quoi il est destiné, il y a quelques restrictions avec l'utilisation de curitors).

Bonne codage.

Modifier (pour marc_s): Vous pourriez vouloir un curseur (en particulier si la génération SQL dynamique un peu - beurk, mais quand même). La raison de cette opération n'a pas été spécifiée et donc la réponse ci-dessus essaie d'être neutre (bien que le libellé et les informations dans le lien jettent une ombre sur l'utilisation des curseurs en général). Alors que les curseurs ont quelques problèmes (et ne correspondent pas vraiment à d'autres constructions DQL), ils peuvent être la meilleure (ou la seule) façon d'effectuer certaines opérations.

+0

YIKES! Vous ** ne voulez pas ** un curseur - si vous le faites - pensez encore à la façon de le faire correctement sans curseur. –

0

Bien que la lecture en boucle d'enregistrements dans T-SQL ne soit pas recommandée pour le code de production, il est parfois nécessaire de le faire. Un couple de grands exemples sont disponibles sur le site de support de Microsoft (dont aucune utiliser les curseurs): http://support.microsoft.com/kb/111401

Et voici une liste des méthodes:

Une méthode est l'utilisation des tables temporaires. Avec cette méthode, vous créez un "snapshot" de l'instruction SELECT initiale et l'utilisez comme base pour "cursoring". Par exemple:

/********** example 1 **********/ 

declare @au_id char(11) 

set rowcount 0 
select * into #mytemp from authors 

set rowcount 1 

select @au_id = au_id from #mytemp 

while @@rowcount <> 0 
begin 
    set rowcount 0 
    select * from #mytemp where au_id = @au_id 
    delete #mytemp where au_id = @au_id 

    set rowcount 1 
    select @au_id = au_id from #mytemp<BR/> 
end 
set rowcount 0 

Une deuxième méthode consiste à utiliser la fonction min pour "parcourir" une table une ligne à la fois. Cette méthode intercepte les nouvelles lignes ajoutées après l'exécution de la procédure stockée, à condition que la nouvelle ligne ait un identifiant unique supérieur à la ligne en cours de traitement dans la requête. Par exemple:

/********** example 2 **********/ 

declare @au_id char(11) 

select @au_id = min(au_id) from authors 

while @au_id is not null 
begin 
    select * from authors where au_id = @au_id 
    select @au_id = min(au_id) from authors where au_id > @au_id 
end 

REMARQUE: Les exemples 1 et 2 supposent qu'un identificateur unique existe pour chaque ligne de la table source. Dans certains cas, aucun identifiant unique ne peut exister. Si c'est le cas, vous pouvez modifier la méthode de table temporaire pour utiliser une colonne de clé nouvellement créée. Par exemple:

/********** example 3 **********/ 

set rowcount 0 
select NULL mykey, * into #mytemp from authors 

set rowcount 1 
update #mytemp set mykey = 1 

while @@rowcount > 0 
begin 
    set rowcount 0 
    select * from #mytemp where mykey = 1 
    delete #mytemp where mykey = 1 
    set rowcount 1 
    update #mytemp set mykey = 1 
end 
set rowcount 0 
+0

tandis que les boucles partagent tous les mêmes problèmes de performance des curseurs. Ils sont aussi quelque chose que vous ne devriez pas faire si vous pouvez l'aider. – HLGEM

Questions connexes