Implémentation SQL Server 2005 de MySQL REPLACE INTO?

MySQL a cette commande SQL REPLACE INTO incroyablement utile mais convenable.

Cela peut-il être facilement émulé dans SQL Server 2005?

Commencer une nouvelle Transaction, faire un Select() puis UPDATE ou INSERT et COMMIT est toujours un peu peu de peine, surtout quand on le fait dans l'application et donc toujours garder 2 versions de la déclaration.

Je me demande s'il existe un moyen facile et universel d'implémenter une telle fonction dans SQL Server 2005?

0
ajouté édité
Vues: 2

4 Réponses

Qu'est-ce que l'upsert / fusion est en train de faire est quelque chose à l'effet de ...

IF EXISTS (SELECT * FROM [Table] WHERE Id = X)
   UPDATE [Table] SET...
ELSE
   INSERT INTO [Table]

Donc, j'espère que la combinaison de ces articles et de ce pseudo code peut faire bouger les choses.

0
ajouté

La fonctionnalité que vous recherchez est traditionnellement appelée UPSERT. Atleast sachant comment ça s'appelle pourrait vous aider à trouver ce que vous cherchez.

I don't think SQL Server 2005 has any great ways of doing this. 2008 introduces the MERGE statement that can be used to accomplish this as shown in: http://www.databasejournal.com/features/mssql/article.php/3739131 or http://blogs.conchango.com/davidportas/archive/2007/11/14/SQL-Server-2008-MERGE.aspx

La fusion était disponible dans la version bêta de 2005, mais ils l'ont supprimée dans la version finale.

0
ajouté

J'ai écrit un article sur ce sujet .

L'essentiel est que si vous voulez des mises à jour à bas prix ... et vous voulez être en sécurité pour une utilisation simultanée. essayer:

update t
set hitCount = hitCount + 1
where pk = @id

if @@rowcount < 1 
begin 
   begin tran
      update t with (serializable)
      set hitCount = hitCount + 1
      where pk = @id
      if @@rowcount = 0
      begin
         insert t (pk, hitCount)
         values (@id,1)
      end
   commit tran
end

De cette façon, vous avez 1 opération pour les mises à jour et un maximum de 3 opérations pour les insertions. Donc, si vous mettez généralement à jour c'est une option sûre et bon marché.

Je serais également très prudent de ne pas utiliser tout ce qui est dangereux pour une utilisation simultanée. Il est vraiment facile d'obtenir des violations de clés primaires ou des lignes en double dans la production.

0
ajouté

C'est quelque chose qui m'énerve à propos de MSSQL ( rant sur mon blog ). Je souhaite que MSSQL soit supporté par upsert .

Le code de @ Dillie-O est un bon moyen pour les anciennes versions de SQL (+1 vote), mais il reste fondamentalement deux opérations d'E / S (le existe et la update ou < code> insérer )

Il y a un peu mieux sur cet article , essentiellement:

--try an update
update tablename 
set field1 = 'new value',
    field2 = 'different value',
    ...
where idfield = 7

--insert if failed
if @@rowcount = 0 and @@error = 0
    insert into tablename 
           ( idfield, field1, field2, ... )
    values ( 7, 'value one', 'another value', ... )

Cela le réduit à une opération d'E / S si c'est une mise à jour, ou deux si une insertion.

MS Sql2008 introduit merge du standard SQL: 2003:

merge tablename as target
using (values ('new value', 'different value'))
    as source (field1, field2)
    on target.idfield = 7
when matched then
    update
    set field1 = source.field1,
        field2 = source.field2,
        ...
when not matched then
    insert ( idfield, field1, field2, ... )
    values ( 7,  source.field1, source.field2, ... )

Maintenant, c'est juste une opération IO, mais un code terrible :-(

0
ajouté
Grand merci! Enregistre le Select et n'a souvent même pas besoin d'une teransaction dans des situations où je peux être sûr qu'entre Update et "my" insert, il n'y a pas d'autre insert pour cette clé.
ajouté l'auteur Michael Stum, source
@Michael Il vaut mieux avoir un index unique sur cette table et gérer les erreurs de clé en double si vous allez utiliser cette solution.
ajouté l'auteur Sam Saffron, source
Oui, comme indiqué ici: weblogs.sqlteam.com/dang/archive/2009/01/31/… MERGE n'est pas atomique. Il supprime un verrou de mise à jour implicite, mais le libère avant d'effectuer une insertion, ce qui provoque une condition de concurrence pouvant entraîner des violations de clé primaire. Vous devez utiliser un HOLDLOCK explicite en plus de l'UPDLOCK implicite pour que l'opération soit atomique. À l'heure actuelle, ce n'est pas atomique, même s'il semble ê
ajouté l'auteur Triynko, source
@Keith Votre instruction de fusion ne fonctionne pas. MERGE ne supporte pas la clause WHERE , vous devez réécrire cela en utilisant USING et ON . De plus, à moins d'ajouter WITH (HOLDLOCK) , il y a une course et des INSERT simultanés peuvent se produire, l'un d'entre eux échouant en raison du conflit de clé.
ajouté l'auteur Eugene Beresovsky, source
La syntaxe MERGE est incorrecte et elle est corrigée dans une réponse plus récente du même auteur: stackoverflow.com/a/243670/24472</ a>
ajouté l'auteur Larry, source
L'insertion ci-dessus, suivie d'une mise à jour peut toujours échouer. Avec une clé unique, vous pouvez obtenir des exceptions de clé en double sur l'insertion. Je recommande d'ajouter à votre instruction de mise à jour: Table UPDATE WITH (SERIALIZABLE) SET ...
ajouté l'auteur Elan, source