Pregunta Implementación de SQL Server 2005 de MySQL REPLACE INTO?


MySQL tiene esto increíblemente útil pero adecuado REPLACE INTO Comando SQL.

¿Se puede emular esto fácilmente en SQL Server 2005?

Comenzar una nueva transacción, haciendo una Select() y luego UPDATE o INSERT y COMMIT siempre es un poco molesto, especialmente cuando lo haces en la aplicación y, por lo tanto, siempre conservas 2 versiones de la declaración.

Me pregunto si hay un fácil y universal forma de implementar dicha función en SQL Server 2005?


74
2017-08-01 22:13


origen


Respuestas:


Esto es algo que me molesta acerca de MSSQL (despotricar en mi blog) Deseo que MSSQL sea compatible upsert.

El código de @Dillie-O es una buena forma en las versiones anteriores de SQL (+1 voto), pero aún así son básicamente dos operaciones IO (el exists y luego el update o insert)

Hay una manera un poco mejor de esta publicación, básicamente:

--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', ... )

Esto lo reduce a una operación IO si es una actualización, o dos si es una inserción.

MS Sql2008 presenta merge del estándar 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, ... )

Ahora es realmente solo una operación IO, pero un código horrible :-(


54
2017-08-15 12:50



La funcionalidad que está buscando se llama tradicionalmente UPSERT. Al menos saber cómo se llama puede ayudarlo a encontrar lo que está buscando.

No creo que SQL Server 2005 tenga ninguna buena manera de hacerlo. 2008 introduce la declaración MERGE que se puede usar para lograr esto como se muestra en: http://www.databasejournal.com/features/mssql/article.php/3739131 o http://blogs.conchango.com/davidportas/archive/2007/11/14/SQL-Server-2008-MERGE.aspx

Merge estuvo disponible en la versión beta de 2005, pero lo eliminaron en la versión final.


22
2017-08-01 22:22



Lo que el upsert / merge está haciendo es algo en el sentido de ...

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

Así que con suerte la combinación de esos artículos y este pseudo código pueden hacer que las cosas se muevan.


16
2017-08-01 22:31



Escribí un entrada de blog sobre este problema.

La conclusión es que si quieres actualizaciones baratas ... y quieres estar seguro para el uso concurrente. tratar:

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 esta forma tiene 1 operación para actualizaciones y un máximo de 3 operaciones para inserciones. Entonces, si generalmente está actualizando, esta es una opción segura y económica.

También sería muy cuidadoso de no utilizar nada que no sea seguro para el uso simultáneo. Es muy fácil obtener violaciones de clave primaria o filas duplicadas en producción.


9
2017-09-21 22:05