Esto es algo que me molesta acerca de MSSQL (rant on my blog). Deseo que MSSQL sea compatible con upsert
.
@ código de Dillie-O es una buena manera en las versiones de SQL mayores (1 voto), pero sigue siendo básicamente dos operaciones de IO (el exists
y luego el update
o insert
)
hay una manera un poco mejor en this post, 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 reduce a una operación IO si se trata de una actualización, o dos si una inserción.
MS SQL2008 introduce merge
del SQL: 2003 estándar:
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 no deja de ser una operación IO, pero el código horrible :-(
Genial, gracias! Guarda la selección y, a menudo, ni siquiera necesita una transacción de Teran en situaciones donde puedo estar seguro de que entre la actualización y la inserción "mi", no hay otra inserción para esa tecla. –
@Michael Será mejor que tenga un índice único en esta tabla y que maneje errores clave duplicados si va a utilizar esta solución. –
@Keith Su declaración de fusión no funciona. 'MERGE' no admite la cláusula' WHERE', tiene que volver a escribir eso usando 'USING' y' ON'. Además, a menos que agregue 'WITH (HOLDLOCK)', hay una carrera y podría suceder un 'INSERT' concurrente, con uno de ellos fallando debido al choque de claves. –