web-dev-qa-db-fra.com

Si existe-t-il avant de mettre à jour ou de supprimer?

  1. Avant d'écrire une déclaration de mise à jour, devrais-je vérifier s'il existe?

    Quelqu'un m'a dit de faire ça

    1. Il évite donc d'écrire inutilement au journal des transactions pour une valeur qui existe déjà,

    2. Et prend uniquement un verrou partagé permettant d'autres lectures par rapport à un verrou exclusif.
      [.____] Ils ont dit imaginer une transaction fonctionnant comme ce plusieurs temps pour différentes valeurs, vous recevriez des verrous exclusifs tout le temps plutôt que des serrures partagées.

    3. Collaborateur mentionné, en regardant Tableau de compatibilité de verrouillage , il ne peut y avoir deux serrures de mise à jour lors de la recherche, mais il peut y avoir deux serrures partagées. Ainsi, lorsque vous "recherchez des lignes à mettre à jour" lorsque ce ne sont pas de valeurs à mettre à jour, une fausse verrouillage de la mise à jour peut bloquer une véritable mise à jour. Quelqu'un peut-il invalider cette réclamation?

      if not exists 
      (
          select FavoriteColor 
          from dbo.Person 
          where Name = 'Bob' 
          and FavoriteColor = 'Green'
      )
      update dbo.Person
      set FavoriteColor = 'Green'
      where Name = 'Bob'
      
  2. Même question, à l'exception de la suppression maintenant, devrais-je vérifier s'il existe?

    if exists 
    (
        select FavoriteColor 
        from dbo.Person 
        where Name = 'Bob' 
        and FavoriteColor = 'Green'
    )
    delete dbo.Person
    where Name = 'Bob' and FavoriteColor = 'Green'
    

Nous utilisons SQL Server 2016.

1
user129291

Généralement, ce modèle est plus efficace et beaucoup moins susceptible de conduire à des blocages ou à d'autres problèmes de concurrence:

UPDATE dbo.Person
  SET FavoriteColor = 'Green'
  WHERE Name = 'Bob'
  AND COALESCE(FavoriteColor, '') <> 'Green';

DELETE dbo.Person
  WHERE Name = 'Bob' 
  AND FavoriteColor = 'Green';

... Tout simplement parce que vous devez seulement vérifier la ligne une fois. Vous pouvez également écrire le UPDATE comme:

UPDATE dbo.Person
  SET FavoriteColor = 'Green'
  WHERE Name = 'Bob'
  AND (FavoriteColor IS NULL OR FavoriteColor <> 'Green');

... qui peut être plus adapté à l'index dans certains cas.

Les verrous exclusifs pour les opérations d'écriture ne sont pas prises avant juste avant la modification d'une ligne à modifier. Tandis que SQL Server est recherche pour les lignes à mettre à jour, il utilise des serrures de mise à jour, qui ne sont pas en conflit avec des lectures simultanées. Le verrou de mise à jour est libéré immédiatement si SQL Server détermine que la ligne en cours de vérification ne se qualifie pas pour la mise à jour.

La seule raison pour laquelle je peux penser à l'utilisation de l'if exists méthode est s'il y a UPDATE/DELETE déclenche dans la table que vous souhaitez éviter d'être tirés, surtout si vous avez INSTEAD OF déclencheurs qui peuvent prendre des mesures avant que toute mise à jour ou toute suppression soit réellement tentée.

Il est normalement préférable d'écrire DML de sorte que seules les lignes nécessitant un changement sont affectées.

6
Aaron Bertrand