essayez de ne jamais boucler, travaillez sur des ensembles de données.
Vous pouvez insérer, mettre à jour, supprimer plusieurs lignes à la fois. ici dans un exemple insérer de plusieurs lignes:
INSERT INTO YourTable
(col1, col2, col3, col4)
SELECT
cola, colb+Colz, colc, @X
FROM ....
LEFT OUTER JOIN ...
WHERE...
vous pouvez même insérer dans plusieurs tables en une seule instruction:
INSERT INTO YourTable
(col1, col2, col3, col4)
OUTPUT INSERTED.PK, Inserted.Col2
INTO OtherTable (ColA, ColB)
SELECT
cola, colb+Colz, colc, @X
FROM ....
LEFT OUTER JOIN ...
WHERE...
Lorsque l'on regarde une boucle voir ce qu'il fait à l'intérieur. S'il s'agit simplement d'insertions/suppressions/mises à jour, réécrivez pour utiliser des commandes uniques. S'il y a des IF, voyez s'il peut s'agir d'instructions CASE ou de conditions WHERE sur inserts/deletes/updates. Si c'est le cas, supprimez la boucle et utilisez les commandes set.
J'ai pris des boucles et les ai remplacées par les commandes basées sur l'ensemble et réduit le temps d'exécution de quelques minutes à quelques secondes. J'ai pris des procédures avec de nombreuses boucles imbriquées et des appels de procédure et j'ai gardé les boucles (impossible d'utiliser seulement des insertions/suppressions/mises à jour), mais j'ai enlevé le curseur, et j'ai vu moins de blocage/blocage. Voici deux méthodes de mise en boucle qui sont mieux que les boucles curseur ...
si vous avez en boucle, sur un ensemble faire quelque chose comme ceci:
--this looks up each row for every iteration
DECLARE @msg VARCHAR(250)
DECLARE @hostname sysname
--first select of currsor free loop
SELECT @hostname= min(RTRIM(hostname))
FROM master.dbo.sysprocesses (NOLOCK)
WHERE hostname <> ''
WHILE @hostname is not null
BEGIN
--just some example of some odd task that requires a loop
set @msg='exec master.dbo.xp_cmdshell "net send '
+ RTRIM(@hostname) + ' '
+ 'testing "'
print @msg
--EXEC (@msg) --<<will not actually send the messages
--next select of cursor free loop
SELECT @hostname= min(RTRIM(hostname))
FROM master.dbo.sysprocesses (NOLOCK)
WHERE hostname <> ''
and hostname > @hostname
END
si vous avez un ensemble raisonnable d'articles (non 100 000) pour faire une boucle, vous pouvez le faire:
--this will capture each Key to loop over
DECLARE @msg VARCHAR(250)
DECLARE @From int
DECLARE @To int
CREATE TABLE #Rows --use a table @variable depending on the number of rows to handle
(
RowID int not null primary key identity(1,1)
,hostname varchar(100)
)
INSERT INTO #Rows
SELECT DISTINCT hostname
FROM master.dbo.sysprocesses (NOLOCK)
WHERE hostname <> ''
SELECT @From=0,@[email protected]@ROWCOUNT
WHILE @From<@To
BEGIN
SET @[email protected]+1
--just some example of some odd task that requires a loop
SELECT @msg='exec master.dbo.xp_cmdshell "net send '
+ RTRIM(hostname) + ' '
+ 'testing "'
FROM #Rows
WHERE [email protected]
print @msg
--EXEC (@msg) --<<will not actually send the messages
END
Pouvez-vous expliquer "certaines opérations"? – Andomar
Il y a 2 flèches à côté de chaque réponse. Si vous aimez la réponse, si c'est un peu utile, c'est une bonne pratique de cliquer sur le bouton up (upvote), et si la réponse est totalement fausse, vous pourriez la rétrograder, bien que les gens n'aiment pas, et vous aussi perdez la réputation points. Si votre question a reçu une réponse correcte, vous DEVEZ la marquer comme telle (le signe de vérification vert sous les flèches à côté de la réponse).C'est une «responsabilité» qui vient avec le droit de poser une question. Si vous ne le faites pas, les gens seront moins désireux de vous aider dans le futur. – AlexanderMP