UPSERT
https://www.dataprix.com/
esTips para realizar UPSERTs o updates con insert en SQL Server
https://www.dataprix.com/blog-it/carlos/tips-para-realizar-upserts-o-updates-con-insert-en-sql-server
<span class="field field--name-title field--type-string field--label-hidden">Tips para realizar UPSERTs o updates con insert en SQL Server</span>
<div class="field field--name-field-tecnologia field--type-entity-reference field--label-hidden field--entity-reference-target-type-taxonomy-term clearfix field__items">
<div class="field__item"><a href="/tecnologia/plataforma-de-datos" hreflang="es">Plataforma de datos</a></div>
</div>
<span class="field field--name-uid field--type-entity-reference field--label-hidden"><a title="Ver perfil del usuario." href="/user/carlos" lang="" about="/user/carlos" typeof="schema:Person" property="schema:name" datatype="" class="username">Carlos</a></span>
<span class="field field--name-created field--type-created field--label-hidden">30 Abril, 2012 - 14:34</span>
<div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>En muchas ocasiones, especialmente en procesos ETL o de carga de datos para un data warehouse, por ejemplo, interesa hacer en una sola sentencia o en un solo paso la comprobación de si un registro existe, y si existe actualizarlo, y si no insertarlo. A esta combinación se le ha apodado UPSERT, aunque en SQL existe una sentencia específica para hacerlo, que es MERGE.</p>
<p><span> </span><img src="/files/uploads/2image/blog/SQL-Merge.jpg" alt="Merge SQL" /></p>
<p> </p>
<p>Reúno en este post algunas soluciones sencillas para hacer, con SQL Server, INSERTS o UPDATES en función de la existencia o no de los registros entrantes. Cambiando un poco la sintaxis se puede hacer lo mismo en otros motores de base de datos, como Oracle, o MySQL.</p>
<p> </p>
<h2>UPSERT en SQL Server</h2>
<p>La intrucción SQL que permite '<em>mezclar</em>' datos de dos tablas en una es <strong>MERGE</strong>. Tiene la particularidad de que su sintaxis permite especificar una sentencia SQL para el caso de que el registro que se va a insertar ya exista (si hay coincidencia en los campos que se definan), y otra sentencia diferente en el caso de que no haya ningún registro en la tabla destino con coincidencia de valores en los campos especificados. Lo normal es definir un update en el caso de que el registro ya exista y un insert en el caso contrario.</p>
<p> </p>
<h2>Merge para actualizar/insertar un registro</h2>
<p>Quedará más claro con este ejemplo de cómo <strong>Insertar o actualizar valores fijos para un registro</strong> en concreto, cosa que podría ser útil, en un entorno DWH for example, para insertar en una dimensión el registro ficticio correspondiente a id's no encontrados (o dummy):</p>
MERGE Tabla_Destino WITH(HOLDLOCK) as target
using (values ('valor1', 'valor2'))
as source (campo1, campo2)
on target.idregistro = 23
when matched then
update
set campo1_dest = source.campo1,
campo2_dest = source.campo2
when not matched then
insert ( idregistro, campo1_dest, campo2_dest)
values ( 23, source.campo1, source.codempresa);<br /><p>Si el registro con <em>idregistro=23</em> existe, se actualizan los campos <em>campo1_dest</em> y <em>campo2_dest</em> con los valores 'valor1' y 'valor2', respectivamente. <br />
Si no existe, se inserta un registro con <em>idregistro=23</em>, valor1_dest='valor1' y <em>valor2_dest</em>='valor2' </p>
<p> </p>
<h3>Transacciones para actualizar/insertar un registro</h3>
<p>Otra solución sencilla para <strong>insertar/actualizar un registro</strong>, pero utilizando <strong>transacciones</strong> en lugar de la instrucción MERGE sería la siguiente:</p>
<p>(Con un cursor y parámetros se puede implementar fácilmente para actualizar/insertar más registros)</p>
BEGIN TRAN
SELECT idRegistro FROM Tabla_Destino WHERE idRegistro=23
IF @@ROWCOUNT = 0
insert ( idregistro, campo1_dest, campo2_dest)
values ( 23, ‘valor1’, ‘valor2’);
COMMIT TRAN<br /><p>Se hace un update de la tabla. Si no se ha actualizado es que no existe el registro, y entonces se hace un insert. </p>
<p> </p>
<h3>Merge para actualizar/insertar varios registros</h3>
<p>El merge anterior insertaba un sólo registro, pero MERGE sirve para tomar como origen de datos tablas completas, o simplemente registros resultado de cualquier sentencia de selección (SELECT), con lo que podemos crear sentencias más potentes, para ejecutar eficientes operaciones que trabajan a nivel de conjunto, y que normalmente van a ser más rápidas que opciones como la transacción anterior.</p>
<p>Por ejemplo, para <strong>Insertar o actualizar valores que provengan de una tabla</strong> o vista:</p>
MERGE Tabla_Destino WITH(HOLDLOCK) as target
using (select idregistro, campo1, campo2 from Tabla_Origen)
as source (campo1, campo2)
on (target.idregistro = source.idregistro)
when matched then
update
set campo1_dest = source.campo1,
campo2_dest = source.campo2
when not matched then
insert ( idregistro, campo1, campo2)
values ( source.idregistro, source.campo1, source.campo2);
<p> </p>
<h3>Referencias</h3>
<p>Finalizo enlazando algunas referencias para el que quiera ampliar información:</p>
<ul><li>Información sobre MERGE y UPSERT, en Wikipedia<br /><a href="https://en.wikipedia.org/wiki/Upsert" rel="nofollow">MERGE (SQL)</a></li>
<p> </p>
<li>Soluciones para INSERT o UPDATE, en Stackoverflow<br /><a href="https://stackoverflow.com/questions/108403/solutions-for-insert-or-update-on-sql-server" rel="nofollow">Solutions for INSERT or UPDATE on SQL Server</a></li>
<p> </p>
<li>Comparativa de rendimiento en SQL Server para sentencias MERGE, en MSSQLTips<br /><a href="https://www.mssqltips.com/sqlservertip/2651/comparing-performance-for-the-merge-statement-to-select-insert-update-or-delete/" rel="nofollow">Comparing performance for the MERGE statement to SELECT, INSERT, UPDATE or DELETE</a></li>
<p> </p>
<li>Sintaxis de la sentencia MERGE, en la librería Microsoft MSDN<br /><a href="https://msdn.microsoft.com/es-es/library/bb510625.aspx" rel="nofollow">MERGE (Transact-SQL)</a></li>
<p> </p>
<li>Cómo utilizar MERGE en Oracle, y como evitar un error muy común:<br /><a href="https://www.dataprix.com/es/update-join-oracle" rel="nofollow">UPDATE con JOIN en Oracle<br /></a><a href="https://www.dataprix.com/es/el-error-ora-30926-como-resultado-una-operaci-n-merge" rel="nofollow">El error ORA-30926 como resultado de una operación Merge</a></li>
</ul><p> </p>
<p> </p>
<p><em>Por Carlos Fernández</em></p>
<p> </p>
<span>Si te ha gustado este post compártelo. Con el botón de 'SHARE' son sólo unos segundos.</span></div>
<div class="field field--name-field-it-tags field--type-entity-reference field--label-hidden field--entity-reference-target-type-taxonomy-term clearfix field__items">
<div class="field__item"><a href="/it-tags/upsert" hreflang="es">UPSERT</a></div>
<div class="field__item"><a href="/it-tags/update" hreflang="es">Update</a></div>
<div class="field__item"><a href="/it-tags/sql-server" hreflang="es">SQL Server</a></div>
<div class="field__item"><a href="/it-tags/oracle-0" hreflang="es">Oracle</a></div>
<div class="field__item"><a href="/it-tags/merge" hreflang="es">merge</a></div>
</div>
<span class="a2a_kit a2a_kit_size_32 addtoany_list" data-a2a-url="https://www.dataprix.com/blog-it/carlos/tips-para-realizar-upserts-o-updates-con-insert-en-sql-server" data-a2a-title="Tips para realizar UPSERTs o updates con insert en SQL Server"><a class="a2a_button_x"></a><a class="a2a_button_linkedin"></a><a class="a2a_button_facebook"></a><a class="a2a_button_buffer"></a></span>
<section class="field field--name-comment-node-blog field--type-comment field--label-hidden comment-wrapper">
</section>
Mon, 30 Apr 2012 12:34:02 +0000Carlos8680 at https://www.dataprix.com