UPDATE (Transact-SQL)
Cambia los datos de una tabla o vista de SQL Server. Para obtener ejemplos, vea Ejemplos.
Sintaxis
-- Syntax for SQL Server and Azure SQL Database [ WITH [. n] ] UPDATE [ TOP ( expression ) [ PERCENT ] ] < < table_alias | | rowset_function_limited [ WITH ( [ . n ] ) ] > | @table_variable > SET < column_name = < expression | DEFAULT | NULL >| < udt_column_name.< < property_name = expression | field_name = expression >| method_name ( argument [ . n ] ) > > | column_name < .WRITE ( expression , @Offset , @Length ) >| @variable = expression | @variable = column = expression | column_name < += | -= | *= | /= | %= | &= | ^= | |= >expression | @variable < += | -= | *= | /= | %= | &= | ^= | |= >expression | @variable = column < += | -= | *= | /= | %= | &= | ^= | |= >expression > [ . n ] [ ] [ FROM < > [ . n ] ] [ WHERE < | < [ CURRENT OF < < [ GLOBAL ] cursor_name >| cursor_variable_name > ] > > ] [ OPTION ( [ . n ] ) ] [ ; ] ::=
-- Syntax for Azure Synapse Analytics and Microsoft Fabric [ WITH [ . n ] ] UPDATE [ database_name . [ schema_name ] . | schema_name . ] table_name SET < column_name = < expression | NULL >> [ . n ] FROM [ database_name . [ schema_name ] . | schema_name . ] table_name JOIN >[ . n ] ON [ WHERE ] [ OPTION ( LABEL = label_name ) ] [;] ::= < [ database_name . [ schema_name ] . | schema_name . ] table_or_view_name [ AS ] table_or_view_alias [ ] | derived_table [ AS ] table_alias [ ( column_alias [ . n ] ) ] >
-- Syntax for Parallel Data Warehouse UPDATE [ database_name . [ schema_name ] . | schema_name . ] table_name SET < column_name = < expression | NULL >> [ . n ] [ FROM from_clause ] [ WHERE ] [ OPTION ( LABEL = label_name ) ] [;]
Para ver la sintaxis de Transact-SQL para SQL Server 2014 y versiones anteriores, consulte Versiones anteriores de la documentación.
Argumentos
WITH
Especifica la vista o el conjunto de resultados temporal indicado, que también se conoce como expresión de tabla común (CTE), definido en el ámbito de la instrucción UPDATE. El conjunto de resultados CTE se deriva de una consulta simple. La instrucción UPDATE hace referencia al conjunto de resultados.
Las expresiones de tabla comunes también se pueden utilizar con las instrucciones SELECT, INSERT, DELETE y CREATE VIEW. Para más información, consulte WITH common_table_expression (Transact-SQL).
TOP (expression) [ PERCENT ]
Especifica el número o porcentaje de filas que se va a actualizar. expression puede ser un número o un porcentaje de las filas.
Las filas a las que se hace referencia en la expresión TOP utilizada con INSERT, UPDATE o DELETE no se ordenan.
En las instrucciones INSERT, UPDATE y DELETE, se deben usar paréntesis para delimitar expression en TOP. Para obtener más información, vea TOP (Transact-SQL).
table_alias
Alias especificado en la cláusula UPDATE que representa la tabla o vista de la que se van a actualizar las filas.
server_name
Es el nombre del servidor (un nombre de servidor vinculado o la función OPENDATASOURCE como nombre de servidor) en el que se encuentra la tabla o la vista. Si se especifica server_name, se requiere database_name y schema_name.
database_name
Es el nombre de la base de datos.
schema_name
Es el nombre del esquema al que pertenece la tabla o la vista.
table_or_view_name
Es el nombre de la tabla o vista cuyas filas se deben actualizar. La vista a la que hace referencia table_or_view_name debe poderse actualizar y debe hacer referencia exactamente a una tabla base de la cláusula FROM de la vista. Para más información sobre las vistas actualizables, vea CREATE VIEW (Transact-SQL).
rowset_function_limited
Es la función OPENQUERY u OPENROWSET, según las funciones del proveedor.
WITH ()
Especifica una o varias sugerencias de tabla que están permitidas en una tabla de destino. La palabra clave WITH y los paréntesis son obligatorios. NOLOCK, READUNCOMMITTED, NOEXPAND y otros no están permitidos. Para información sobre las sugerencias de tabla, vea Sugerencias de tabla (Transact-SQL).
@table_variable
Especifica una variable table como origen de la tabla.
SET
Especifica la lista de nombres de variable o de columna que se van a actualizar.
column_name
Es una columna que contiene los datos que se van a cambiar. column_name debe existir en table_or view_name. Las columnas de identidad no se pueden actualizar.
expression
Es una variable, un valor literal, una expresión o una instrucción de subselección entre paréntesis que devuelve un solo valor. El valor devuelto por expression sustituye al valor existente en column_name o variable.
Cuando se hace referencia a los tipos de datos de caracteres Unicode nchar, nvarchar y ntext, debe agregarse como prefijo la letra mayúscula «N» a «expression». Si no se especifica ‘N’, SQL Server convierte la cadena a la página de códigos que se corresponde con la intercalación predeterminada de la base de datos o columna. Los caracteres que no se encuentren en esta página de códigos se perderán.
DEFAULT
Especifica que el valor predeterminado definido para la columna debe reemplazar al valor existente en esa columna. Esta operación también puede utilizarse para cambiar la columna a NULL si no tiene asignado ningún valor predeterminado y se ha definido para aceptar valores NULL.
< += | -= | *= | /= | %= | &= | ^= | |= >
Operador de asignación compuesta:
+= Sumar y asignar
-= Restar y asignar
*= Multiplicar y asignar
/= Dividir y asignar
%= Módulo y asignar
&= AND bit a bit y asignar
^= XOR bit a bit y asignar
|= OR bit a bit y asignar
udt_column_name
Es una columna de un tipo definido por el usuario.
property_name | field_name
Es un miembro de propiedad público o un miembro de datos público de un tipo definido por el usuario.
method_name(argument [ ,. n] )
Es un método mutador público no estático de udt_column_name que usa uno o varios argumentos.
.WRITE (expression,@Offset,@Length)
Especifica que se va a modificar una sección del valor de column_name. expression sustituye a unidades @Length a partir de @Offset de column_name. Solo se pueden especificar con esta cláusula columnas de tipo varchar(max) , nvarchar(max) o varbinary(max) . column_name no puede ser NULL y no se puede calificar con un nombre de tabla o un alias de tabla.
expression es el valor que se copia en column_name. expression se debe evaluar, o bien se debe poder convertir implícitamente al tipo column_name. Si expression se establece en NULL, @Length se omitirá y el valor en column_name se truncará en el valor @Offset especificado.
@Offset es el punto inicial del valor almacenado en column_name en el que se escribe expression. @Offset es una posición de byte ordinal de base cero, es de tipo bigint y no puede ser un número negativo. Si @Offset es NULL, la operación de actualización anexa expressional final del valor de column_name existente y @Length no se tiene en cuenta. Si @Offset es mayor que la longitud de bytes del valor de column_name, Motor de base de datos devuelve un error. Si la suma de @Offset y @Length excede el final del valor subyacente de la columna, se elimina todo hasta el último carácter del valor.
@Length es la longitud de la sección de la columna, a partir de @Offset, que se reemplaza por expression. @Length es de tipo bigint y no puede ser un número negativo. Si @Length es NULL, la operación de actualización quita todos los datos de @Offset hasta el final del valor de column_name.
@variable
Es una variable declarada que se establece en el valor devuelto por expression.
SET @variable = column = expression establece la variable en el mismo valor que la columna. Esto difiere de SET @variable = column, column = expression, que establece la variable en el valor previo a la actualización de la columna.
Devuelve datos actualizados o expresiones basadas en ellos como parte de la operación UPDATE. La cláusula OUTPUT no se admite en instrucciones DML dirigidas a tablas o vistas remotas. Para más información sobre los argumentos y el comportamiento de esta cláusula, vea Cláusula OUTPUT (Transact-SQL).
FROM
Especifica que se utiliza un origen de tabla, vista o tabla derivada para proporcionar los criterios de la operación de actualización. Para obtener más información, vea FROM (Transact-SQL).
Si el objeto que se actualiza es el que se indica en la cláusula FROM y solo hay una referencia al objeto en ella, puede especificarse o no un alias de objeto. Si el objeto que se actualiza aparece más de una vez en la cláusula FROM, una única referencia al objeto no debe especificar un alias de tabla. Todas las demás referencias al objeto de la cláusula FROM deben incluir un alias de objeto.
Una vista con un desencadenador INSTEAD OF UPDATE no puede ser el destino de UPDATE con una cláusula FROM.
Las llamadas a OPENDATASOURCE, OPENQUERY u OPENROWSET en la cláusula FROM se evalúan por separado y de forma independiente de otras llamadas a estas funciones utilizadas como destino de la actualización, incluso si se han suministrado argumentos idénticos a las dos llamadas. En particular, las condiciones de filtro o combinación aplicadas en el resultado de una de esas llamadas no tienen ningún efecto en los resultados de la otra llamada.
WHERE
Especifica las condiciones que limitan las filas que se actualizan. Hay dos modos de actualización, dependiendo del formato de cláusula WHERE que se utilice:
- Las actualizaciones por búsqueda especifican una condición de búsqueda para calificar las filas que se van a eliminar.
- Las actualizaciones posicionadas utilizan la cláusula CURRENT OF para especificar un cursor. La operación de actualización se produce en la posición actual del cursor.
Especifica la condición que debe cumplirse para que se actualicen las filas. La condición de búsqueda también puede ser la condición en la que se basa una combinación. No hay límite en el número de predicados que se pueden incluir en una condición de búsqueda. Para más información sobre los predicados y las condiciones de búsqueda, vea Condición de búsqueda (Transact-SQL).
CURRENT OF
Indica que la actualización se realice en la posición actual del cursor especificado.
Una actualización posicionada que utiliza una cláusula WHERE CURRENT OF actualiza la fila que se encuentra en la posición actual del cursor. Este método puede ser más preciso que una actualización por búsqueda que use una cláusula WHERE para calificar las filas que se deben actualizar. Una actualización por búsqueda modifica varias filas cuando la condición de búsqueda no identifica una sola fila de forma exclusiva.
GLOBAL
Especifica que cursor_name hace referencia a un cursor global.
cursor_name
Es el nombre del cursor abierto desde el que se debe realizar la captura. Si hay un cursor global y otro local con el nombre cursor_name, este argumento hace referencia al cursor global si se especifica GLOBAL; de lo contrario, hace referencia al cursor local. El cursor debe permitir actualizaciones.
cursor_variable_name
Es el nombre de una variable de cursor. cursor_variable_name debe hacer referencia a un cursor que permita realizar actualizaciones.
OPTION ( [ ,. n ] )
Especifica que se utilizan las sugerencias del optimizador para personalizar el modo en que el Motor de base de datos procesa la instrucción. Para obtener más información, consulte Sugerencias de consulta (Transact-SQL).
Procedimientos recomendados
Use la función @@ROWCOUNT para devolver el número de filas insertadas a la aplicación cliente. Para más información, consulte @@ROWCOUNT(Transact-SQL).
Es posible utilizar nombres de variables en las instrucciones UPDATE para mostrar los valores nuevos y antiguos afectados, pero solo se recomienda cuando la instrucción UPDATE afecta a un único registro. Si la instrucción UPDATE afecta a varios registros, para devolver los valores nuevos y antiguos de cada registro, use la cláusula OUTPUT.
Actúe con precaución al especificar la cláusula FROM para proporcionar los criterios de la operación de actualización. Los resultados de una instrucción UPDATE están sin definir si la instrucción incluye una cláusula FROM que no se especifica de manera que solo haya un valor disponible para cada caso de columna que se actualice, es decir, si la instrucción UPDATE no es determinista. Por ejemplo, en la instrucción UPDATE del siguiente script, las dos filas de Table1 cumplen los requisitos de la cláusula FROM de la instrucción UPDATE, pero no se define qué fila de Table1 se utiliza para actualizar la fila de Table2.
USE AdventureWorks2022; GO IF OBJECT_ID ('dbo.Table1', 'U') IS NOT NULL DROP TABLE dbo.Table1; GO IF OBJECT_ID ('dbo.Table2', 'U') IS NOT NULL DROP TABLE dbo.Table2; GO CREATE TABLE dbo.Table1 (ColA INT NOT NULL, ColB DECIMAL(10,3) NOT NULL); GO CREATE TABLE dbo.Table2 (ColA INT PRIMARY KEY NOT NULL, ColB DECIMAL(10,3) NOT NULL); GO INSERT INTO dbo.Table1 VALUES(1, 10.0), (1, 20.0); INSERT INTO dbo.Table2 VALUES(1, 0.0); GO UPDATE dbo.Table2 SET dbo.Table2.ColB = dbo.Table2.ColB + dbo.Table1.ColB FROM dbo.Table2 INNER JOIN dbo.Table1 ON (dbo.Table2.ColA = dbo.Table1.ColA); GO SELECT ColA, ColB FROM dbo.Table2;
Puede ocurrir el mismo problema cuando se combinan las cláusulas FROM y WHERE CURRENT OF . En el ejemplo siguiente, las dos filas de Table2 cumplen los requisitos de la cláusula FROM de la instrucción UPDATE . No se ha definido qué fila de Table2 se utilizará para actualizar la fila de Table1 .
USE AdventureWorks2022; GO IF OBJECT_ID ('dbo.Table1', 'U') IS NOT NULL DROP TABLE dbo.Table1; GO IF OBJECT_ID ('dbo.Table2', 'U') IS NOT NULL DROP TABLE dbo.Table2; GO CREATE TABLE dbo.Table1 (c1 INT PRIMARY KEY NOT NULL, c2 INT NOT NULL); GO CREATE TABLE dbo.Table2 (d1 INT PRIMARY KEY NOT NULL, d2 INT NOT NULL); GO INSERT INTO dbo.Table1 VALUES (1, 10); INSERT INTO dbo.Table2 VALUES (1, 20), (2, 30); GO DECLARE abc CURSOR LOCAL FOR SELECT c1, c2 FROM dbo.Table1; OPEN abc; FETCH abc; UPDATE dbo.Table1 SET c2 = c2 + d2 FROM dbo.Table2 WHERE CURRENT OF abc; GO SELECT c1, c2 FROM dbo.Table1; GO
Soporte de compatibilidad
En una versión futura de SQL Server se quitará el uso de las sugerencias READUNCOMMITTED y NOLOCK en la cláusula FROM que se aplican a la tabla de destino de una instrucción UPDATE o DELETE. Evite usar estas sugerencias en este contexto en el nuevo trabajo de desarrollo y planee modificar las aplicaciones que las usan actualmente.
Tipos de datos
Todas las columnas char y nchar se rellenan a la derecha hasta la longitud definida.
Si ANSI_PADDING se establece en OFF, se quitan todos los espacios finales de los datos insertados en las columnas varchar y nvarchar, excepto en las cadenas que contienen solo espacios. Estas cadenas se truncan en una cadena vacía. Si ANSI_PADDING se establece en ON, se insertan espacios al final. El controlador ODBC de Microsoft SQL Server y el proveedor OLE DB para SQL Server establecen automáticamente SET ANSI_PADDING en ON para cada conexión. Se puede configurar en orígenes de datos ODBC o mediante atributos o propiedades de conexión. Para más información, consulte SET ANSI_PADDING (Transact-SQL).
Actualización de columnas de tipo text, ntext e image
Al modificar una columna text, ntext o image con UPDATE, se inicializa la columna, se le asigna un puntero de texto válido y se le asigna al menos una página de datos, a menos que la columna se actualice con NULL.
Para reemplazar o modificar bloques grandes de datos de tipo text, ntext o image, use WRITETEXT o UPDATETEXT en lugar de la instrucción UPDATE.
Si la instrucción UPDATE ha podido cambiar más de una fila durante la actualización de la clave de agrupación en clústeres y una o varias columnas text, ntext o image, la actualización parcial de estas columnas se ejecuta como una sustitución completa de los valores.
Los tipos de datos ntext, text e image se quitarán en una versión futura de SQL Server. Evite su uso en nuevos trabajos de desarrollo y piense en modificar las aplicaciones que los usan actualmente. Use nvarchar(max), varchar(max)y varbinary(max) en su lugar.
Actualización de tipos de datos de valores grandes
Use la cláusula .WRITE (expression,@Offset,@Length) para realizar una actualización parcial o completa de los tipo de datos varchar(max), nvarchar(max) y varbinary(max).
Por ejemplo, la actualización parcial de una columna varchar(max) podría eliminar o modificar solo los 200 primeros bytes de la columna (200 caracteres si se usan los caracteres ASCII), mientras que una actualización completa eliminaría o modificaría todos los datos de la columna. Las actualizaciones .WRITE que insertan o anexan datos nuevos se registran mínimamente si se ha establecido para la base de datos el modelo de recuperación optimizado para cargas masivas de registros o el modelo de recuperación simple. El registro mínimo no se utiliza cuando se actualizan los datos existentes. Para más información, consulte El registro de transacciones (SQL Server).
El Motor de base de datos convierte una actualización parcial en actualización completa cuando la instrucción UPDATE realiza una de estas acciones:
- Cambia una columna de clave de la tabla o vista con particiones.
- Modifica más de una fila y también actualiza la clave de un índice clúster no único en un valor no constante.
No se puede usar la cláusula .WRITE para actualizar una columna NULL o establecer el valor de column_name como NULL.
@Offset y @Length se especifican en bytes para los tipos de datos varbinary y varchar, y en pares de bytes para el tipo de datos nvarchar. Para obtener más información sobre las longitudes de tipos de datos de cadena, vea char y varchar (Transact-SQL) y nchar y nvarchar (Transact-SQL).
Para que el rendimiento sea óptimo, se recomienda insertar o actualizar los datos en tamaños de fragmento que sean múltiplos de 8.040 bytes.
Si se hace referencia en una cláusula OUTPUT a la columna modificada por la cláusula .WRITE, el valor completo de la columna, ya sea la imagen anterior de deleted.column_name o la imagen posterior de inserted.column_name, se devuelve en la columna que se ha especificado en la variable de la tabla. Vea el ejemplo R a continuación.
Para obtener la misma funcionalidad de .WRITE con otros tipos de datos de carácter o binarios, use STUFF (Transact-SQL).
Actualización de columnas de tipos definidos por el usuario
Hay varios métodos para actualizar los valores de columnas de tipos definidos por el usuario:
-
Suministrar un valor de un tipo de datos del sistema de SQL Server, siempre y cuando el tipo definido por el usuario admita la conversión implícita o explícita desde ese tipo. En el ejemplo siguiente se muestra cómo actualizar un valor de una columna de tipo Point , definido por el usuario, mediante la conversión explícita de una cadena.
UPDATE Cities SET Location = CONVERT(Point, '12.3:46.2') WHERE Name = 'Anchorage';
UPDATE Cities SET Location.SetXY(23.5, 23.5) WHERE Name = 'Anchorage';
Nota SQL Server devuelve un error si se invoca un método mutador en un valor NULL de Transact-SQL, o si un nuevo valor producido por un método mutador es NULL.
UPDATE Cities SET Location.X = 23.5 WHERE Name = 'Anchorage';
Actualización de datos FILESTREAM
Puede utilizar la instrucción UPDATE para actualizar un campo FILESTREAM de forma que tenga un valor nulo, un valor vacío o una cantidad relativamente pequeña de datos insertados. Sin embargo, se envía una gran cantidad de datos de manera más eficaz en un archivo si se utilizan interfaces de Win32. Al actualizar un campo FILESTREAM, modifica los datos de BLOB subyacentes en el sistema de archivos. Cuando un campo FILESTREAM está establecido en NULL, se eliminan los datos de BLOB asociados al campo. No se puede usar .WRITE() para realizar actualizaciones parciales de datos FILESTREAM. Para obtener más información, vea FILESTREAM (SQL Server).
Control de errores
Si la actualización de una fila infringe una restricción o una regla, infringe la configuración de valores NULL de la columna o, si el nuevo valor es de un tipo de datos incompatible, se cancela la instrucción, se devuelve un error y no se actualiza ningún registro.
Cuando una instrucción UPDATE encuentra un error aritmético (error de desbordamiento, división por cero o de dominio) durante la evaluación de la expresión, la actualización no se lleva a cabo. El resto del lote no se ejecuta y se devuelve un mensaje de error.
Si la actualización de una o varias columnas que participan en un índice clúster hace que el tamaño del mismo y de la fila supere 8.060 bytes, la actualización no se produce y se devuelve un mensaje de error.
Interoperabilidad
Se pueden utilizar instrucciones UPDATE en el cuerpo de las funciones definidas por el usuario solamente si la tabla que se modifica es una variable de tabla.
Cuando se define un desencadenador INSTEAD OF para las acciones UPDATE de una tabla, se ejecuta el desencadenador en lugar de la instrucción UPDATE. En versiones anteriores de SQL Server solo se admite la definición de desencadenadores AFTER en instrucciones UPDATE y otras instrucciones de modificación de datos. No se puede especificar la cláusula FROM en una instrucción UPDATE que haga referencia, directa o indirectamente, a una vista que tenga definido un desencadenador INSTEAD OF . Para más información sobre los desencadenadores INSTEAD OF, vea CREATE TRIGGER (Transact-SQL).
Actualmente, la cláusula FROM no se puede especificar en las instrucciones UPDATE en Warehouse en Microsoft Fabric. Se admiten instrucciones UPDATE de tabla única.
Limitaciones y restricciones
No se puede especificar la cláusula FROM en una instrucción UPDATE que haga referencia, directa o indirectamente, a una vista que tenga definido un desencadenador INSTEAD OF . Para obtener más información sobre los desencadenadores INSTEAD OF , vea CREATE TRIGGER (Transact-SQL).
Cuando una expresión de tabla común (CTE) es el destino de una instrucción UPDATE, todas las referencias a la CTE de la instrucción deben coincidir. Por ejemplo, si la CTE tiene asignado un alias en la cláusula FROM, el alias se debe utilizar para obtener todas las otras referencias a la CTE. Se requieren referencias CTE inequívocas porque una CTE no tiene un objeto ID, que utiliza SQL Server para reconocer la relación implícita entre un objeto y su alias. Sin esta relación, el plan de consulta puede producir un comportamiento de la unión inesperado y resultados imprevistos de la consulta. Los ejemplos siguientes muestran métodos correctos e incorrectos de especificar una CTE cuando la CTE es el objeto de destino de la operación de actualización.
USE tempdb; GO -- UPDATE statement with CTE references that are correctly matched. DECLARE @x TABLE (ID INT, Value INT); DECLARE @y TABLE (ID INT, Value INT); INSERT @x VALUES (1, 10), (2, 20); INSERT @y VALUES (1, 100),(2, 200); WITH cte AS (SELECT * FROM @x) UPDATE x -- cte is referenced by the alias. SET Value = y.Value FROM cte AS x -- cte is assigned an alias. INNER JOIN @y AS y ON y.ID = x.ID; SELECT * FROM @x; GO
El conjunto de resultados es el siguiente:
ID Value ------ ----- 1 100 2 200 (2 row(s) affected)
Instrucción UPDATE con referencias CTE que se hacen coincidir de forma incorrecta.
USE tempdb; GO DECLARE @x TABLE (ID INT, Value INT); DECLARE @y TABLE (ID INT, Value INT); INSERT @x VALUES (1, 10), (2, 20); INSERT @y VALUES (1, 100),(2, 200); WITH cte AS (SELECT * FROM @x) UPDATE cte -- cte is not referenced by the alias. SET Value = y.Value FROM cte AS x -- cte is assigned an alias. INNER JOIN @y AS y ON y.ID = x.ID; SELECT * FROM @x; GO
El conjunto de resultados es el siguiente:
ID Value ------ ----- 1 100 2 100 (2 row(s) affected)
Comportamiento de bloqueo
Una instrucción UPDATE realiza un bloqueo exclusivo (X) en todas las filas que modifica, y retiene esos bloqueos hasta que se completa la transacción. Dependiendo del plan de consulta de la instrucción UPDATE, del número de filas que se modifiquen y del nivel de aislamiento de la transacción, los bloqueos se pueden realizar en el nivel PAGE o TABLE en lugar de en el nivel ROW. Para impedir que estos bloqueos de nivel superior se produzcan, considere la posibilidad de dividir en lotes las instrucciones UPDATE que afecten a miles de filas o más, y asegúrese de que los índices admitan las condiciones de combinación y de filtro. Vea el artículo sobre el bloqueo del motor de base de datos para obtener más información sobre la mecánica de bloqueo en SQL Server.
Comportamiento del registro
La instrucción UPDATE se registra, pero las actualizaciones parciales de tipos de datos de valores grandes mediante la cláusula .WRITE se registran mínimamente. Para obtener más información, vea “Actualizar tipos de datos de valores grandes” en la sección anterior “Tipos de datos”.
Seguridad
Permisos
Se requieren permisos UPDATE en la tabla de destino. También se requieren permisos SELECT para la tabla que se actualiza si la instrucción UPDATE contiene una cláusula WHERE o en el caso de que el argumento expression de la cláusula SET use una columna de la tabla.
Los permisos UPDATE se adjudican de forma predeterminada a los miembros del rol fijo de servidor sysadmin , a los roles fijos de base de datos db_owner y db_datawriter , y al propietario de la tabla. Los miembros de los roles sysadmin , db_owner y db_securityadmin , y el propietario de la tabla pueden transferir permisos a otros usuarios.
Ejemplos
| Category | Elementos de sintaxis ofrecidos |
|---|---|
| Sintaxis básica | UPDATE |
| Limitar las filas que se actualizan | WHERE * TOP * WITH expresión de tabla común * WHERE CURRENT OF |
| Establecer valores de columna | computed values * compound operators * default values * subqueries |
| Especificar objetos de destino que no sean tablas estándar | views * table variables * table aliases |
| Actualizar los datos basados en datos de otras tablas | FROM |
| Actualizar las filas de una tabla remota | linked server * OPENQUERY * OPENDATASOURCE |
| Actualizar tipos de datos de objetos grandes | .WRITE * OPENROWSET |
| Actualizar tipos definidos por el usuario | Tipos definidos por el usuario |
| Invalidar el comportamiento predeterminado del optimizador de consultas mediante sugerencias | table hints * query hints |
| Capturar los resultados de la instrucción UPDATE | Cláusula OUTPUT |
| Usar UPDATE en otras instrucciones | Stored Procedures * TRY. CATCH |
Sintaxis básica
Los ejemplos de esta sección demuestran la funcionalidad básica de la instrucción UPDATE con la sintaxis mínima requerida.
A. Usar una instrucción UPDATE simple
En el ejemplo siguiente se actualiza un solo valor de columna para todas las filas de la tabla Person.Address .
USE AdventureWorks2022; GO UPDATE Person.Address SET ModifiedDate = GETDATE();
B. Actualizar varias columnas
En el siguiente ejemplo se actualizan los valores de las columnas Bonus , CommissionPct y SalesQuota para todas las filas de la tabla SalesPerson .
USE AdventureWorks2022; GO UPDATE Sales.SalesPerson SET Bonus = 6000, CommissionPct = .10, SalesQuota = NULL; GO
Limitar las filas que se actualizan
En los ejemplos de esta sección se muestran varias formas de limitar el número de filas afectadas por la instrucción UPDATE.
C. Usar la cláusula WHERE
En el ejemplo siguiente se utiliza la cláusula WHERE para especificar las filas que se van a actualizar. La instrucción actualiza el valor de la columna Color de la tabla Production.Product para todas las filas con un valor existente de ‘Red’ en la columna Color y con un valor que comience por ‘Road-250’ en la columna Name .
USE AdventureWorks2022; GO UPDATE Production.Product SET Color = N'Metallic Red' WHERE Name LIKE N'Road-250%' AND Color = N'Red'; GO
D. Usar la cláusula TOP
En los siguientes ejemplos use la cláusula TOP para limitar el número de filas que se modifican en una instrucción UPDATE. Cuando se usa una cláusula TOP (n) con UPDATE, la operación de actualización se realiza en una selección aleatoria de un número de filas n. En el ejemplo siguiente se actualiza un 25 por ciento la columna VacationHours en 10 filas aleatorias de la tabla Employee .
USE AdventureWorks2022; GO UPDATE TOP (10) HumanResources.Employee SET VacationHours = VacationHours * 1.25 ; GO
Si debe usar TOP para aplicar actualizaciones por orden cronológico, debe utilizarla junto con ORDER BY en una instrucción de subselección. En el siguiente ejemplo se actualizan las horas de vacaciones de los 10 empleados cuyas fechas de alta son más antiguas.
UPDATE HumanResources.Employee SET VacationHours = VacationHours + 8 FROM (SELECT TOP 10 BusinessEntityID FROM HumanResources.Employee ORDER BY HireDate ASC) AS th WHERE HumanResources.Employee.BusinessEntityID = th.BusinessEntityID; GO
E. Usar la cláusula WITH common_table_expression
En el siguiente ejemplo se actualiza el valor PerAssemblyQty para todas las partes y componentes que se utilizan directamente o indirectamente para crear el ProductAssemblyID 800 . La expresión de tabla común devuelve una lista jerárquica de partes que se usan directamente para compilar ProductAssemblyID 800 y las partes que se usan para compilar esos componentes, etc. Solo se modifican las filas devueltas por la expresión de tabla común.
USE AdventureWorks2022; GO WITH Parts(AssemblyID, ComponentID, PerAssemblyQty, EndDate, ComponentLevel) AS ( SELECT b.ProductAssemblyID, b.ComponentID, b.PerAssemblyQty, b.EndDate, 0 AS ComponentLevel FROM Production.BillOfMaterials AS b WHERE b.ProductAssemblyID = 800 AND b.EndDate IS NULL UNION ALL SELECT bom.ProductAssemblyID, bom.ComponentID, p.PerAssemblyQty, bom.EndDate, ComponentLevel + 1 FROM Production.BillOfMaterials AS bom INNER JOIN Parts AS p ON bom.ProductAssemblyID = p.ComponentID AND bom.EndDate IS NULL ) UPDATE Production.BillOfMaterials SET PerAssemblyQty = c.PerAssemblyQty * 2 FROM Production.BillOfMaterials AS c JOIN Parts AS d ON c.ProductAssemblyID = d.AssemblyID WHERE d.ComponentLevel = 0;
F. Usar la cláusula WHERE CURRENT OF
En el siguiente ejemplo se usa la cláusula WHERE CURRENT OF para actualizar solo la fila en la que se coloca el cursor. Cuando un cursor se basa en una combinación, solo se modifica el table_name especificado en la instrucción UPDATE. Las demás tablas que participan en el cursor no se ven afectadas.
USE AdventureWorks2022; GO DECLARE complex_cursor CURSOR FOR SELECT a.BusinessEntityID FROM HumanResources.EmployeePayHistory AS a WHERE RateChangeDate <> (SELECT MAX(RateChangeDate) FROM HumanResources.EmployeePayHistory AS b WHERE a.BusinessEntityID = b.BusinessEntityID) ; OPEN complex_cursor; FETCH FROM complex_cursor; UPDATE HumanResources.EmployeePayHistory SET PayFrequency = 2 WHERE CURRENT OF complex_cursor; CLOSE complex_cursor; DEALLOCATE complex_cursor; GO
Establecer valores de columna
En los ejemplos de esta sección se muestra la actualización de columnas mediante valores calculados, subconsultas y valores DEFAULT.
G. Especificar un valor calculado
En los siguientes ejemplos se usan valores calculados en una instrucción UPDATE. En el ejemplo se duplica el valor de la columna ListPrice para todas las filas de la tabla Product .
USE AdventureWorks2022; GO UPDATE Production.Product SET ListPrice = ListPrice * 2; GO
H. Especificar un operador compuesto
En el ejemplo siguiente se usa la variable @NewPrice para incrementar el precio de todas las bicicletas rojas, tomando como base el precio actual y sumándole 10.
USE AdventureWorks2022; GO DECLARE @NewPrice INT = 10; UPDATE Production.Product SET ListPrice += @NewPrice WHERE Color = N'Red'; GO
En el siguiente ejemplo se usa el operador compuesto += para anexar los datos ‘ — tool malfunction’ al valor existente de la columna Name de las filas que tienen un valor de ScrapReasonID comprendido entre 10 y 12.
USE AdventureWorks2022; GO UPDATE Production.ScrapReason SET Name += ' - tool malfunction' WHERE ScrapReasonID BETWEEN 10 and 12;
I. Especificar una subconsulta en la cláusula SET
En el siguiente ejemplo se usa una subconsulta en la cláusula SET para determinar el valor usado para actualizar la columna. La subconsulta debe devolver solo un valor escalar. Es decir, un solo valor por fila. En el ejemplo se modifica la columna SalesYTD de la tabla SalesPerson para reflejar las ventas más recientes registradas en la tabla SalesOrderHeader . La subconsulta suma las ventas de cada vendedor en la instrucción UPDATE .
USE AdventureWorks2022; GO UPDATE Sales.SalesPerson SET SalesYTD = SalesYTD + (SELECT SUM(so.SubTotal) FROM Sales.SalesOrderHeader AS so WHERE so.OrderDate = (SELECT MAX(OrderDate) FROM Sales.SalesOrderHeader AS so2 WHERE so2.SalesPersonID = so.SalesPersonID) AND Sales.SalesPerson.BusinessEntityID = so.SalesPersonID GROUP BY so.SalesPersonID); GO
J. Actualizar las filas con valores DEFAULT
En el siguiente ejemplo se establece la columna CostRate en su valor predeterminado (0.00) para todas las filas que tengan un valor de CostRate mayor que 20.00 .
USE AdventureWorks2022; GO UPDATE Production.Location SET CostRate = DEFAULT WHERE CostRate > 20.00;
Especificar objetos de destino que no sean tablas estándar
En los ejemplos de esta sección se muestra cómo actualizar filas especificando una vista, un alias de tabla o una variable de tabla.
K. Especificar una vista como el objeto de destino
En el siguiente ejemplo se actualizan las filas de la tabla especificando una vista como el objeto de destino. La definición de la vista hace referencia a varias tablas, sin embargo, la instrucción UPDATE se ejecuta correctamente porque hace referencia a columnas de una sola de las tablas subyacentes. Se produciría un error en la instrucción UPDATE si se especificaran columnas de ambas tablas. Para más información, vea Modificar datos mediante una vista.
USE AdventureWorks2022; GO UPDATE Person.vStateProvinceCountryRegion SET CountryRegionName = 'United States of America' WHERE CountryRegionName = 'United States';
L. Especificar un alias de tabla como el objeto de destino
En el siguiente ejemplo se actualizan las filas de la tabla Production.ScrapReason . El alias de tabla asignado a ScrapReason de la cláusula FROM se especifica como el objeto de destino de la cláusula UPDATE.
USE AdventureWorks2022; GO UPDATE sr SET sr.Name += ' - tool malfunction' FROM Production.ScrapReason AS sr JOIN Production.WorkOrder AS wo ON sr.ScrapReasonID = wo.ScrapReasonID AND wo.ScrappedQty > 300;
M. Especificar una variable de tabla como el objeto de destino
En el siguiente ejemplo se actualizan las filas de una variable de tabla.
USE AdventureWorks2022; GO -- Create the table variable. DECLARE @MyTableVar TABLE ( EmpID INT NOT NULL, NewVacationHours INT, ModifiedDate DATETIME); -- Populate the table variable with employee ID values from HumanResources.Employee. INSERT INTO @MyTableVar (EmpID) SELECT BusinessEntityID FROM HumanResources.Employee; -- Update columns in the table variable. UPDATE @MyTableVar SET NewVacationHours = e.VacationHours + 20, ModifiedDate = GETDATE() FROM HumanResources.Employee AS e WHERE e.BusinessEntityID = EmpID; -- Display the results of the UPDATE statement. SELECT EmpID, NewVacationHours, ModifiedDate FROM @MyTableVar ORDER BY EmpID; GO
Actualizar los datos basados en datos del resto de las tablas
En los ejemplos de esta sección se muestran métodos para actualizar las filas de una tabla basada en la información de otra.
Hora Usar la instrucción UPDATE con información de otra tabla
En este ejemplo se modifica la columna SalesYTD de la tabla SalesPerson para reflejar las ventas más recientes registradas en la tabla SalesOrderHeader .
USE AdventureWorks2022; GO UPDATE Sales.SalesPerson SET SalesYTD = SalesYTD + SubTotal FROM Sales.SalesPerson AS sp JOIN Sales.SalesOrderHeader AS so ON sp.BusinessEntityID = so.SalesPersonID AND so.OrderDate = (SELECT MAX(OrderDate) FROM Sales.SalesOrderHeader WHERE SalesPersonID = sp.BusinessEntityID); GO
En el ejemplo anterior se asume que solo se registra una venta para un determinado vendedor en una fecha determinada y que las actualizaciones son recientes. Si se puede registrar más de una venta para un vendedor determinado el mismo día, el ejemplo que se muestra no funcionará correctamente. Se ejecuta sin errores, pero cada valor de SalesYTD se actualiza con una sola venta, independientemente del número de ventas que se produjeron ese día realmente. Esto es debido a que una sola instrucción UPDATE nunca actualiza la misma fila dos veces.
Si puede haber más de una venta el mismo día para un vendedor especificado, todas las ventas de cada vendedor se deben agregar en la instrucción UPDATE , tal como se muestra en el ejemplo siguiente:
USE AdventureWorks2022; GO UPDATE Sales.SalesPerson SET SalesYTD = SalesYTD + (SELECT SUM(so.SubTotal) FROM Sales.SalesOrderHeader AS so WHERE so.OrderDate = (SELECT MAX(OrderDate) FROM Sales.SalesOrderHeader AS so2 WHERE so2.SalesPersonID = so.SalesPersonID) AND Sales.SalesPerson.BusinessEntityID = so.SalesPersonID GROUP BY so.SalesPersonID); GO
Actualización de las filas de una tabla remota
En los ejemplos de esta sección se muestra cómo actualizar las filas de una tabla de destino remota mediante un servidor vinculado o una función de conjunto de filas para hacer referencia a la tabla remota.
O. Actualizar datos en una tabla remota con un servidor vinculado
En el ejemplo siguiente se actualiza una tabla en un servidor remoto. En el ejemplo primero se crea un vínculo al origen de datos remoto mediante sp_addlinkedserver. El nombre del servidor vinculado, MyLinkedServer , se especifica después como parte del nombre de objeto de cuatro partes con el formato servidor.catálogo.esquema.objeto. Observe que debe especificar un nombre de servidor válido para @datasrc .
USE master; GO -- Create a link to the remote data source. -- Specify a valid server name for @datasrc as 'server_name' or 'server_nameinstance_name'. EXEC sp_addlinkedserver @server = N'MyLinkedServer', @srvproduct = N' ', @provider = N'SQLNCLI10', @datasrc = N'', @catalog = N'AdventureWorks2022'; GO USE AdventureWorks2022; GO -- Specify the remote data source using a four-part name -- in the form linked_server.catalog.schema.object. UPDATE MyLinkedServer.AdventureWorks2022.HumanResources.Department SET GroupName = N'Public Relations' WHERE DepartmentID = 4;
P. Actualizar datos en una tabla remota con la función OPENQUERY
En el ejemplo siguiente se actualiza una fila de una tabla remota mediante la especificación de la función de conjunto de filas OPENQUERY. En este ejemplo se usa el nombre del servidor vinculado creado en el ejemplo anterior.
UPDATE OPENQUERY (MyLinkedServer, 'SELECT GroupName FROM HumanResources.Department WHERE DepartmentID = 4') SET GroupName = 'Sales and Marketing';
Q. Actualizar datos en una tabla remota con la función OPENDATASOURCE
En el ejemplo siguiente se actualiza una fila de una tabla remota mediante la especificación de la función de conjunto de filas OPENDATASOURCE. Especifique un nombre de servidor válido para el origen de datos con el formato server_name o server_name\instance_name. Quizá deba configurar la instancia de SQL Server para las consultas distribuidas ad hoc. Para más información, vea Opción de configuración del servidor ad hoc distributed queries.
UPDATE OPENDATASOURCE('SQLNCLI', 'Data Source=;Integrated Security=SSPI').AdventureWorks2022.HumanResources.Department SET GroupName = 'Sales and Marketing' WHERE DepartmentID = 4;
Actualización de tipos de datos de objetos grandes
En los ejemplos de esta sección se muestran los métodos de actualización de los valores de columnas definidos con tipos de datos de objetos grandes (LOB).
R. Usar UPDATE con .WRITE para modificar los datos de una columna de tipo nvarchar(max)
En el ejemplo siguiente se usa la cláusula .WRITE para actualizar un valor parcial de DocumentSummary , una columna de tipo nvarchar(max) de la tabla Production.Document . La palabra components se sustituye por la palabra features especificando la palabra sustituta, la ubicación inicial (desplazamiento) de la palabra que se va a sustituir en los datos existentes y el número de caracteres que se va a sustituir (longitud). En el ejemplo también se usa la cláusula OUTPUT para devolver las imágenes anterior y posterior de la columna DocumentSummary a la variable de tabla @MyTableVar .
USE AdventureWorks2022; GO DECLARE @MyTableVar TABLE ( SummaryBefore NVARCHAR(max), SummaryAfter NVARCHAR(max)); UPDATE Production.Document SET DocumentSummary .WRITE (N'features',28,10) OUTPUT deleted.DocumentSummary, inserted.DocumentSummary INTO @MyTableVar WHERE Title = N'Front Reflector Bracket Installation'; SELECT SummaryBefore, SummaryAfter FROM @MyTableVar; GO
S. Usar UPDATE con .WRITE para agregar y quitar datos en una columna de tipo nvarchar(max)
En los ejemplos siguientes se agregan y quitan datos en una columna de tipo nvarchar(max) que tiene un valor establecido actualmente en NULL. Dado que no se puede usar la cláusula .WRITE para modificar una columna NULL, primero se llena la columna con datos temporales. Después, estos datos se reemplazan por los datos correctos mediante la cláusula .WRITE. En los demás ejemplos se anexan datos al final del valor de la columna, se quitan (truncan) los datos de la columna y, por último, se quitan los datos parciales de la columna. Las instrucciones SELECT muestran la modificación de datos resultante de cada instrucción UPDATE.
USE AdventureWorks2022; GO -- Replacing NULL value with temporary data. UPDATE Production.Document SET DocumentSummary = N'Replacing NULL value' WHERE Title = N'Crank Arm and Tire Maintenance'; GO SELECT DocumentSummary FROM Production.Document WHERE Title = N'Crank Arm and Tire Maintenance'; GO -- Replacing temporary data with the correct data. Setting @Length to NULL -- truncates all existing data from the @Offset position. UPDATE Production.Document SET DocumentSummary .WRITE(N'Carefully inspect and maintain the tires and crank arms.',0,NULL) WHERE Title = N'Crank Arm and Tire Maintenance'; GO SELECT DocumentSummary FROM Production.Document WHERE Title = N'Crank Arm and Tire Maintenance'; GO -- Appending additional data to the end of the column by setting -- @Offset to NULL. UPDATE Production.Document SET DocumentSummary .WRITE (N' Appending data to the end of the column.', NULL, 0) WHERE Title = N'Crank Arm and Tire Maintenance'; GO SELECT DocumentSummary FROM Production.Document WHERE Title = N'Crank Arm and Tire Maintenance'; GO -- Removing all data from @Offset to the end of the existing value by -- setting expression to NULL. UPDATE Production.Document SET DocumentSummary .WRITE (NULL, 56, 0) WHERE Title = N'Crank Arm and Tire Maintenance'; GO SELECT DocumentSummary FROM Production.Document WHERE Title = N'Crank Arm and Tire Maintenance'; GO -- Removing partial data beginning at position 9 and ending at -- position 21. UPDATE Production.Document SET DocumentSummary .WRITE ('',9, 12) WHERE Title = N'Crank Arm and Tire Maintenance'; GO SELECT DocumentSummary FROM Production.Document WHERE Title = N'Crank Arm and Tire Maintenance'; GO
T. Usar UPDATE con OPENROWSET para modificar una columna de tipo varbinary(max)
En el ejemplo siguiente se sustituye por una imagen nueva una imagen almacenada en una columna de tipo varbinary(max) . La función OPENROWSET se usa con la opción BULK para cargar la imagen en la columna. En este ejemplo se da por supuesto que hay un archivo denominado Tires.jpg en la ruta de acceso especificada.
USE AdventureWorks2022; GO UPDATE Production.ProductPhoto SET ThumbNailPhoto = ( SELECT * FROM OPENROWSET(BULK 'c:Tires.jpg', SINGLE_BLOB) AS x ) WHERE ProductPhotoID = 1; GO
U. Usar UPDATE para modificar datos FILESTREAM
En el siguiente ejemplo se usa la instrucción UPDATE para modificar los datos del archivo del sistema de archivos. No se recomienda este método para transmitir grandes cantidades de datos a un archivo. Use las interfaces de Win32 adecuadas. En el ejemplo siguiente se reemplaza cualquier texto del registro del archivo por el texto Xray 1 . Para obtener más información, vea FILESTREAM (SQL Server).
UPDATE Archive.dbo.Records SET [Chart] = CAST('Xray 1' as VARBINARY(max)) WHERE [SerialNumber] = 2;
Actualizar tipos definidos por el usuario
En los siguientes ejemplos se modifican valores de columnas de tipo definido por el usuario (UDT) CLR. Se muestran tres métodos. Para más información sobre las columnas definidas por el usuario, vea Tipos definidos por el usuario CLR.
V. Usar un tipo de datos del sistema
Puede actualizar un UDT suministrando un valor en un tipo de datos del sistema de SQL Server, siempre que el tipo definido por el usuario admita la conversión implícita o explícita desde ese tipo. En el ejemplo siguiente se muestra cómo actualizar un valor de una columna de tipo Point , definido por el usuario, mediante la conversión explícita de una cadena.
UPDATE dbo.Cities SET Location = CONVERT(Point, '12.3:46.2') WHERE Name = 'Anchorage';
Hora Invocar un método
Puede actualizar un UDT invocando un método, marcado como mutador, del tipo definido por el usuario, para realizar la actualización. En el ejemplo siguiente se invoca un método mutador de tipo Point denominado SetXY . Esto actualiza el estado de la instancia del tipo.
UPDATE dbo.Cities SET Location.SetXY(23.5, 23.5) WHERE Name = 'Anchorage';
X. Modificar el valor de una propiedad o miembro de datos
Puede actualizar un UDT modificando el valor de un miembro de datos público o de un miembro de propiedad registrado del tipo definido por el usuario. La expresión que suministra el valor debe poder convertirse implícitamente al tipo de la propiedad. En el ejemplo siguiente se modifica el valor de la propiedad X del tipo Point definido por el usuario.
UPDATE dbo.Cities SET Location.X = 23.5 WHERE Name = 'Anchorage';
Invalidar el comportamiento predeterminado del optimizador de consultas mediante sugerencias
En los ejemplos de esta sección se muestra cómo usar sugerencias de tabla y de consulta para invalidar de forma temporal el comportamiento predeterminado del optimizador de consultas cuando se procesa la instrucción UPDATE.
Como el optimizador de consultas de SQL Server suele seleccionar el mejor plan de ejecución de una consulta, se recomienda que únicamente los administradores de bases de datos y desarrolladores experimentados utilicen las sugerencias como último recurso.
Y. Especificar una sugerencia de tabla
En el ejemplo siguiente se especifica la sugerencia de tabla TABLOCK. Esta sugerencia especifica que se aplique un bloqueo compartido a la tabla Production.Product y que se mantenga hasta que finalice la instrucción UPDATE.
USE AdventureWorks2022; GO UPDATE Production.Product WITH (TABLOCK) SET ListPrice = ListPrice * 1.10 WHERE ProductNumber LIKE 'BK-%'; GO
Z. Especificar una sugerencia de consulta
En el ejemplo siguiente se especifica la sugerencia de consulta OPTIMIZE FOR (@variable) en la instrucción UPDATE. Esta sugerencia indica al optimizador de consultas que use un valor concreto para una variable local cuando la consulta se compile y optimice. El valor se utiliza solo durante la optimización de la consulta y no durante la ejecución de la misma.
USE AdventureWorks2022; GO CREATE PROCEDURE Production.uspProductUpdate @Product NVARCHAR(25) AS SET NOCOUNT ON; UPDATE Production.Product SET ListPrice = ListPrice * 1.10 WHERE ProductNumber LIKE @Product OPTION (OPTIMIZE FOR (@Product = 'BK-%') ); GO -- Execute the stored procedure EXEC Production.uspProductUpdate 'BK-%';
Captura de los resultados de la instrucción UPDATE
En los ejemplos de esta sección se muestra cómo usar la cláusula OUTPUT para devolver información de cada fila afectada por una instrucción UPDATE o de expresiones que se basan en esta instrucción. Estos resultados se pueden devolver a la aplicación de procesamiento para que los utilice en mensajes de confirmación, archivado y otros requisitos similares de una aplicación.
AA. Usar UPDATE con la cláusula OUTPUT
En el siguiente ejemplo se actualiza la columna VacationHours de la tabla Employee en un 25 % para los empleados con menos de 10 horas de vacaciones. Además, se establece el valor de la columna ModifiedDate en la fecha actual. La cláusula OUTPUT devuelve el valor de VacationHours antes de aplicar la instrucción UPDATE en la columna deleted.VacationHours y el valor actualizado en la columna inserted.VacationHours en la variable de tabla @MyTableVar .
Las dos instrucciones SELECT que le siguen devuelven los valores en @MyTableVar y los resultados de la operación de actualización en la tabla Employee . Para más ejemplos en los que se usa la cláusula OUTPUT, vea Cláusula OUTPUT (Transact-SQL).
USE AdventureWorks2022; GO --Display the initial data of the table to be updated. SELECT BusinessEntityID, VacationHours, ModifiedDate, HireDate FROM HumanResources.Employee WHERE VacationHours < 10 GO DECLARE @MyTableVar TABLE ( EmpID int NOT NULL, OldVacationHours smallint, NewVacationHours smallint, ModifiedDate datetime); UPDATE HumanResources.Employee SET VacationHours = VacationHours * 1.25, ModifiedDate = GETDATE() OUTPUT inserted.BusinessEntityID, deleted.VacationHours, inserted.VacationHours, inserted.ModifiedDate INTO @MyTableVar WHERE VacationHours < 10 --Display the result set of the table variable. SELECT EmpID, OldVacationHours , NewVacationHours, ModifiedDate FROM @MyTableVar; GO --Display the result set of the table. SELECT BusinessEntityID, VacationHours, ModifiedDate, HireDate FROM HumanResources.Employee WHERE VacationHours < 10 GO
Usar UPDATE en otras instrucciones
En los ejemplos de esta sección se muestra cómo usar UPDATE en otras instrucciones.
AB. Usar UPDATE en un procedimiento almacenado
En el ejemplo siguiente se usa una instrucción UPDATE en un procedimiento almacenado. El procedimiento toma un parámetro de entrada @NewHours y un parámetro de salida @RowCount . El valor del parámetro @NewHours se usa en la instrucción UPDATE para actualizar la columna VacationHours de la tabla HumanResources.Employee . El parámetro de salida @RowCount se usa para devolver el número de filas afectadas a una variable local. La expresión CASE se utiliza en la cláusula SET para determinar el valor que está establecido para VacationHours condicionalmente. Cuando se paga al empleado por hora ( SalariedFlag = 0), VacationHours se establece en el número actual de horas más el valor especificado en @NewHours ; de lo contrario, VacationHours se establece en el valor especificado en @NewHours .
USE AdventureWorks2022; GO CREATE PROCEDURE HumanResources.Update_VacationHours @NewHours SMALLINT AS SET NOCOUNT ON; UPDATE HumanResources.Employee SET VacationHours = ( CASE WHEN SalariedFlag = 0 THEN VacationHours + @NewHours ELSE @NewHours END ) WHERE CurrentFlag = 1; GO EXEC HumanResources.Update_VacationHours 40;
AC. Usar UPDATE en un bloque TRY…CATCH
En el ejemplo siguiente, se usa una instrucción UPDATE en un bloque TRY…CATCH para administrar los errores de ejecución que se puedan producir durante la operación de actualización.
USE AdventureWorks2022; GO BEGIN TRANSACTION; BEGIN TRY -- Intentionally generate a constraint violation error. UPDATE HumanResources.Department SET Name = N'MyNewName' WHERE DepartmentID BETWEEN 1 AND 2; END TRY BEGIN CATCH SELECT ERROR_NUMBER() AS ErrorNumber ,ERROR_SEVERITY() AS ErrorSeverity ,ERROR_STATE() AS ErrorState ,ERROR_PROCEDURE() AS ErrorProcedure ,ERROR_LINE() AS ErrorLine ,ERROR_MESSAGE() AS ErrorMessage; IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION; END CATCH; IF @@TRANCOUNT > 0 COMMIT TRANSACTION; GO
Ejemplos: Azure Synapse Analytics y Sistema de la plataforma de análisis (PDW)
AD. Usar una instrucción UPDATE simple
En los ejemplos siguientes se muestra cómo se pueden ver afectadas todas las filas si no se usa una cláusula WHERE para especificar la fila o las filas que se deben actualizar.
En este ejemplo se actualizan los valores de las columnas EndDate y CurrentFlag de todas las filas de la tabla DimEmployee .
-- Uses AdventureWorks UPDATE DimEmployee SET EndDate = '2010-12-31', CurrentFlag='False';
También se pueden utilizar valores calculados en una instrucción UPDATE. En el ejemplo siguiente se duplica el valor de la columna ListPrice para todas las filas de la tabla Product .
-- Uses AdventureWorks UPDATE DimEmployee SET BaseRate = BaseRate * 2;
AE. Usar la instrucción UPDATE con una cláusula WHERE
En el ejemplo siguiente se utiliza la cláusula WHERE para especificar las filas que se van a actualizar.
-- Uses AdventureWorks UPDATE DimEmployee SET FirstName = 'Gail' WHERE EmployeeKey = 500;
AF. Usar la instrucción UPDATE con una etiqueta
En el ejemplo siguiente se muestra el uso de LABEL para la instrucción UPDATE.
-- Uses AdventureWorks UPDATE DimProduct SET ProductSubcategoryKey = 2 WHERE ProductKey = 313 OPTION (LABEL = N'label1');
AG. Usar la instrucción UPDATE con información de otra tabla
En este ejemplo se crea una tabla para almacenar las ventas totales por año. Actualiza las ventas totales del año 2004 mediante la ejecución de una instrucción SELECT en la tabla FactInternetSales.
-- Uses AdventureWorks CREATE TABLE YearlyTotalSales ( YearlySalesAmount MONEY NOT NULL, Year SMALLINT NOT NULL ) WITH ( DISTRIBUTION = REPLICATE ); INSERT INTO YearlyTotalSales VALUES (0, 2004); INSERT INTO YearlyTotalSales VALUES (0, 2005); INSERT INTO YearlyTotalSales VALUES (0, 2006); UPDATE YearlyTotalSales SET YearlySalesAmount= (SELECT SUM(SalesAmount) FROM FactInternetSales WHERE OrderDateKey >=20040000 AND OrderDateKey < 20050000) WHERE Year=2004; SELECT * FROM YearlyTotalSales;
AH. Unión de ANSI para las instrucciones de actualización
En este ejemplo se muestra cómo actualizar datos en función del resultado de la combinación con otra tabla.
CREATE TABLE dbo.Table1 (ColA INT NOT NULL, ColB DECIMAL(10,3) NOT NULL); GO CREATE TABLE dbo.Table2 (ColA INT NOT NULL, ColB DECIMAL(10,3) NOT NULL); GO INSERT INTO dbo.Table1 VALUES(1, 10.0); INSERT INTO dbo.Table2 VALUES(1, 0.0); GO UPDATE dbo.Table2 SET dbo.Table2.ColB = dbo.Table2.ColB + dbo.Table1.ColB FROM dbo.Table2 INNER JOIN dbo.Table1 ON (dbo.Table2.ColA = dbo.Table1.ColA); GO SELECT ColA, ColB FROM dbo.Table2; GO
Какой метод класса statement надо использовать для посылки sql команды update table set x 5 y 6
Изучение интерфейсов Statement, PrepareStatement и CallableStatement.
Интерфейсы Statement, PrepareStatement и CallableStatement определяют методы и свойства, позволяющие выдавать запросы и команды в базу данных, а также получать результаты выполнения запросов. Они также предусматривают методы, упрощающие процедуру преобразования типов данных JAVA-SQL. В качестве примера можно привести тип данных integer. В java данные типа integer не могут принимать значение NULL. В базе данных напротив пустые значения любых типов представляются NULL значением.
Первым в иерархии стоит интерфейс Statement. Интерфейс PrepareStatement расширяет интерфейс Statement. Интерфейс CallableStatement в свою очередь расширяет интерфейс PrepareStatement. Производители JDBC драйверов применяют перечисленные выше интерфейсы в классах поставляемых ими драйверов и реализуют соответствующие методы. Таким образом, без регистрации конкретного драйвера невозможно создать объект с использованием перечисленных выше интерфейсов.
Statement интерфейс используют в случае выполнения статических запросов к базе данных. Такие запросы не могут содержать изменяемые параметры.
PrepareStatemet интерфейс используют в случае многократного выполнения одного и того же запроса с динамически меняющимися параметрами.
CallableStatement интерфейс используется для доступа к хранимым в базе данных процедурам. Этот интерфейс тоже может использоваться с динамически изменяемыми параметрами.
Объекты, созданные с использованием данных интерфейсов, имею четыре основных метода для выполнения запросов к базе данных:
1. executeQuery() - используется для выполнения команды SELECT и возвращает ResultSet.
2. executeUpdate() - используется при выполнении команд INSERT, UPDATE и DELETE возвращая при этом количество обработанных ими строк, или DDL SQL предложений возвращая при этом значение 0.
3. execute() - используется для выполнения любых DDL или DML команд возвращая при этом один или несколько объектов типа ResultSet и/или количество обработанных строк (в зависимости от типа выполняемого запроса). Данный метод является наиболее гибки и в тоже время наиболее сложным в обработке результатов запроса.
4. executeBatch() - используется для объединения нескольких запросов в одно обращение к базе данных. Удобен для организации обработки транзакций.
Для использования этих методов прежде всего необходимо создать сам объект типа Statement методом createStatement() объекта типа Connection. Метод executeQuery(), равно как и шаги, предшествующие его выполнению, подробно рассмотрены в материалах к занятию №1. Ниже приведен пример использования метода executeUpdate() для дополнения учебной базы данных двумя таблицами и заполнения их небольшим количеством демонстрационных данных.
//Занятие 2, пример 2-1
public static void createTables() throws SQLException
String operatorsql = "CREATE TABLE операторы_связи "
+ "(ид NUMBER(3) CONSTRAINT ПК_ОС PRIMARY KEY,"
String telefonsql = "CREATE TABLE номера_телефонов "
+ "(ид_л NUMBER(9) CONSTRAINT ВК_Л REFERENCES н_люди(ид),"
+ "ид_ос NUMBER(3) CONSTRAINT ВК_ОС REFERENCES операторы_связи(ид))" ;
st.executeUpdate( "DROP TABLE операторы_связи CASCADE CONSTRAINTS" );
> catch (SQLException se)
//Игнорировать ошибку удаления таблицы
String msg = se.getMessage();
System.out.println( "Ошибка при удалении таблицы: " +msg);
//Создание таблицы операторы_связи
System.out.println( "Таблица операторы_связи создана. " );
st.executeUpdate( "DROP TABLE номера_телефонов" );
> catch (SQLException se)
//Игнорировать ошибку удаления таблицы
String msg = se.getMessage();
System.out.println( "Ошибка при удалении таблицы: " +msg);
//Создание таблицы номера_телефонов
System.out.println( "Таблица номера_телефонов создана. " );
public static void insertData() throws SQLException
//Загрузка данных в таблицу операторы_связи
st.executeUpdate("INSERT INTO операторы_связи VALUES(1,'Мегафон')");
st.executeUpdate("INSERT INTO операторы_связи VALUES(2,'МТС')");
st.executeUpdate("INSERT INTO операторы_связи VALUES(3,'Би Лайн')");
st.executeUpdate("INSERT INTO операторы_связи VALUES(4,'SkyLink')");
//Загрузка данных в таблицу номера_телефонов
st.executeUpdate("INSERT INTO номера_телефонов VALUES(125704,'9363636',,1)");
st.executeUpdate("INSERT INTO номера_телефонов VALUES(125704,'2313131',,2)");
st.executeUpdate("INSERT INTO номера_телефонов VALUES(125704,'1151515',,4)");
st.executeUpdate("INSERT INTO номера_телефонов VALUES(120848,'4454545',,3)");
st.executeUpdate("INSERT INTO номера_телефонов VALUES(120848,'1161616',,4)");
System.out.println("Загрузка данных закончена. ");
Для изучения примера необходимо создать класс, использующий main метод для регистрации драйвера, создания соединения с базой данных, создания объекта типа Statement и обработки соответствующих исключений. Для создания таблиц и заполнения их данными необходимо использовать отдельные методы (аналогичные приведенным в примере).
При заполнении таблицы номера_телефонов данные о дате регистрации телефона указываются с использованием JDBC SQL escape последовательности, которая имеет следующий формат: . В данном примере ключевым словом является символ d, который сообщает драйверу о необходимости преобразования указанной в качестве параметра даты в формат даты ORACLE.
Метод execute() является наиболее универсальным методом выполнения запросов, так как он позволяет выполнять любые запросы и возвращать множественные результаты запросов типа ResultSet и количество обновлений типа integer. Такая универсальность ведет к определенной сложности обработки результатов, так как заранее может быть неизвестно какое количество объектов типа ResultSet и какое количество значений типа integer и в какой последовательности будет получено. В любом случае метод execute() возвращает значение типа boolean. Значение true означает, что результат выполнения запроса может быть получен методом getResultSet() и помещен в объект типа ResultSet. После обработки результата запроса необходимо проверить наличие следующего результата используя метод getMoreResults(). Значение типа false означает отсутствие результата запроса типа ResultSet. В этом случае необходимо проверить наличие количественного значения методом getUpdateCount(). Значение большее или равное 0 означает наличие количественного значения сделанных обновлений (например: вставленных или обновленных строк). Если метод getUpdateCount() возвращает значение -1, это означает, что все результаты исчерпаны и обработку можно завершать. В общем случае алгоритм обработки результатов выполнения метода execute() можно представить следующим фрагментом программного кода:
Statement st = conn.createStatement();
st.execute( любой SQL-запрос );
//Вывести результат запроса
//Вывести количество обработанных строк
if ((st.getMoreResults() == false) && (get.UpdateCount == -1))
Для изучения этого метода необходимо создать класс, в методе main которого выполнить следующий фрагмент кода:
//Занятие 2, пример 2-2
Connection conn = null;
Statement st = null;
ResultSet rs = null;
//Начало блока обработки исключений (try)
//Регистрация драйвера, и создание соединения
String sql = "INSERT INTO номера_телефонов VALUES(121018,'9999999',,1)";
sql = "SELECT фамилия, имя, номер_телефона, дата_регистрации, оператор "
+"FROM н_люди л, номера_телефонов т, операторы_связи о "
+"WHERE л.ид = т.ид_л AND т.ид_ос = о.ид";
>//Блок обработки исключений (catch, finally)
Обработку результатов, полученных методом execute() реализовать отдельным метод:
public static void processExecute(Statement st,
boolean executeResult) throws SQLException
//Код обработки результатов
>//end of processExecute metod
Использование метода executeBatch() тесно связано с использованием технологии транзакций. Этот метод позволяет выполнить за одно обращение к базе данных группу заранее подготовленных запросов. В случае неудачи выполнения одного из запросов можно отменить (откатить) все изменения, сделанные данной группой запросов с помощью метода rollback(). Ниже приведен фрагмент программного кода, иллюстрирующий данную возможность:
//Занятие 2, пример 2-3
public static void batchInsert() throws SQLException
//Загрузка данных в таблицу операторы_связи
st.addBatch("INSERT INTO операторы_связи VALUES(1,'Мегафон')");
st.addBatch("INSERT INTO операторы_связи VALUES(2,'МТС')");
st.addBatch("INSERT INTO операторы_связи VALUES(3,'Би Лайн')");
st.addBatch("INSERT INTO операторы_связи VALUES(4,'SkyLink')");
//Загрузка данных в таблицу номера_телефонов
st.addBatch("INSERT INTO номера_телефонов VALUES(125704,'9363636',,1)");
st.addBatch("INSERT INTO номера_телефонов VALUES(125704,'2313131',,2)");
st.addBatch("INSERT INTO номера_телефонов VALUES(125704,'1151515',,4)");
st.addBatch("INSERT INTO номера_телефонов VALUES(120848,'4454545',,3)");
st.addBatch("INSERT INTO номера_телефонов VALUES(120848,'1161616',,4)");
System.out.println("Пакет загрузки данных подготовлен. ");
int[] count = st.executeBatch();
Формирование пакета запросов осуществляется методом addBatch() с параметром типа String. При необходимости, для аннулирования уже сформированного пакета запросов можно использовать метод clearBatch(). В этом случае весь пакет будет аннулирован и его можно начать формировать заново. Перед выполнением пакета для использования режима транзакций необходимо отменить автоматическое подтверждение изменений в результате выполнения каждого запроса, то есть выполнить метод setAutoCommit(false). После выполнения метода executeBatch() необходимо выполнить метод commit() для подтверждения сделанных в базе изменений. В случае неудачного выполнения одного из запросов будет получено исключение типа SQLException. В блоке обработки исключения можно использовать метод rollback() для отмены (отката) сделанных в базе данных изменений. Для изучения перечисленных выше методов необходимо в созданном для примера 2-1 классе заменить метод insertDate() на метод batchInsert() данного примера и выполнить его.
Для более гибкого управления ходом выполнения транзакций существует возможность установки логических точек отката изменений, сделанных в базе в процессе выполнения последовательности транзакций. Для этого используется метод setSavepoint(String Имя точки отката ). Для аннулирования ранее установленной точки отката можно использовать метод releaseSavepoint(Savepoint svpt). В случае возникновения исключения при выполнении транзакции можно либо отменить все начатые изменения в базе данных с момента последнего выполнения метода setAutoCommit(false), либо отменить их до установленной логической точки отката методом rollback(Savepoint svpt). Ниже приведен фрагмент программного кода, на примере которого необжодимо изучить данную возможность, дополнив его до полноценного класса.
//Занятие 2, пример 2-4
public class RollBackMethod
public static void main(String[] args)
//Регистрация драйвера, и создание соединения
if(!conn.getAutoCommit()) System.out.println("Auto-Commit отменен. ");
String sql = "INSERT INTO операторы_связи VALUES(5,'TELE2')";
sql = "INSERT INTO номера_телефонов VALUES(130777,'2223322',,5)";
> catch (SQLException se)
System.out.println("SQLException сообщение: "+se.getMessage());
System.out.println("Начнем откат изменений. ");
> catch (SQLException rse)
System.out.println("Откат изменений закончен. ");
> catch (Exception e)
> catch (SQLException se)
При создании объекта типа PreparedStatement указанное ему в качестве параметра SQL-предложение передается СУБД, которая разбирает его, компилирует и создает план выполнения запроса. Запрос сохраняется готовым для выполнения пока остается открытым данное соединение или пока не закроется данный созданный объект. В отличии от объекта типа Statement объект типа PreparedStatement создается методом prepareStatement() объекта типа Connection. Передаваемое данному методу SQL-предложение в местах подстановки переменных значений содержит знак ?, который является частью синтаксиса и указывает на местоположение подставляемого параметра.
Существует три типа параметров: IN, OUT и INOUT. Объекты типа PreparedStatemet используют только параметры типа IN. Перед выполнением запроса необходимо установить все параметры методом setXXX(), где XXX заменяется на соответствующее типу данных параметра ключевое слово, например: setInt(), setString(), setDate(), setTime(). Если какой либо из параметров не установлен, то будет выдано исключение типа SQLEception. При установке параметра указывается его номер по порядку, начиная с 1, как он встречается в SQL-предложении, и его значение. Посла выполнения подготовленного таким образом запроса установленные параметры не сбрасываются. Их можно сбросить методом clearParameters() или переустановить упомянутыми выше методами setXXX().
В случае использования метода executeBatch() после каждого утановки каждого полного комплекта параметров выполняется метод addBatch() без аргументов.
Для изучения интерфейса PrepareStatemet и применения его методов необходимо выполнить приведенный ниже пример, дополнив его реализацией необходимых методов:
//Занятие 2, пример 2-5
public class PrepStatDB
static Connection conn = null;
public static void main(String[] args)
//Регистрация драйвера, и создание соединения
System.out.println("Создание базы данных закончено. ");
> catch (SQLException se)
> catch (Exception e)
> catch (SQLException se)
public static void createTables() throws SQLException
Statement st = conn.createStatement();
//Программный код создания таблиц базы данных (см. пример 1-1)
public static void insertData() throws SQLException
//Загрузка данных в таблицу операторы_связи
String sql = "INSERT INTO операторы_связи VALUES(. )";
PreparedStatement prst = conn.prepareStatement(sql);
prst.setInt(1,1); prst.setString(2,"Мегафон"); count = prst.executeUpdate();
System.out.println("Запись \"Мегафон\" добавлена");
prst.setInt(1,2); prst.setString(2,"МТС"); count = prst.executeUpdate();
System.out.println("Запись \"МТС\" добавлена");
prst.setInt(1,3); prst.setString(2,"Би Лайн"); count = prst.executeUpdate();
System.out.println("Запись \"Би Лайн\" добавлена");
prst.setInt(1,4); prst.setString(2,"SkyLink"); count = prst.executeUpdate();
System.out.println("Запись \"SkyLink\" добавлена");
//Загрузка данных в таблицу номера_телефонов
sql = "INSERT INTO номера_телефонов VALUES(. )";
prst.setInt(1,125704); prst.setString(2,"9363636"); prst.setDate(3,Date.valueOf("2000-9-15")); prst.setInt(4,1); prst.addBatch();
prst.setInt(1,125704); prst.setString(2,"2313131"); prst.setDate(3,Date.valueOf("2001-2-25")); prst.setInt(4,2); prst.addBatch();
prst.setInt(1,125704); prst.setString(2,"1151515"); prst.setDate(3,Date.valueOf("2002-6-17")); prst.setInt(4,4); prst.addBatch();
prst.setInt(1,120848); prst.setString(2,"4454545"); prst.setDate(3,Date.valueOf("2003-7-30")); prst.setInt(4,3); prst.addBatch();
prst.setInt(1,120848); prst.setString(2,"1161616"); prst.setDate(3,Date.valueOf("2004-1-16")); prst.setInt(4,4); prst.addBatch();
int[] countb = prst.executeBatch();
System.out.println("\n"+"Загрузка данных закончена. ");
При работе с данными типа CLOB и BLOB значения параметров можно задавать и получать используя потоки ввода и вывода. При этом используются следующие методы:
setAsciiStream() - используется для больших ASCII объектов;
setCharacterStream() - используется для больших UNICODE объектов;
setBinaryStream() - используется для больших двоичных объектов.
В качестве параметров методам setXXXStream() указывается номер по порядку, объект типа InputStream и длина объекта. Получение потока данных производится методами getXXXStream(). Ниже приведен пример записи ASCII файла в поле предварительно созданной таблицы readme.
//Занятие 2, пример 2-6
public class StreamMethod
public static void main(String[] args)
Connection conn = null;
Statement st = null;
PreparedStatement prst = null;
ResultSet rs = null;
//Регистрация драйвера, и создание соединения
File f = new File("/etc/passwd");
long fileLength = f.length();
FileInputStream fis = new FileInputStream(f);
String sql = "INSERT INTO readme VALUES(. )";
sql = "SELECT * FROM readme WHERE >
InputStream is = rs.getAsciiStream(2);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while ((c = is.read()) != -1) baos.write(c);
> catch (SQLException se)
> catch (Exception e)
> catch (SQLException se)
public static void createReadmeTable(Statement st) throws Exception
String sql = "CREATE TABLE readme (id INTEGER, data LONG)";
st.executeUpdate("DROP TABLE readme");
> catch (SQLException se)
//Игнорировать ошибку удаления таблицы
String msg = se.getMessage();
System.out.println("Ошибка при удалении таблицы: "+msg);
System.out.println("Таблица readme создана. ");
Объекты типа CallableStatement создается методом prepareCall() объекта типа Connection и позволяют выполнять хранимые в базе данных процедуры. При этом могу использоваться параметры всех трех типов: IN, OUT и INOUT. SQL-предложение при этом подготавливается в виде JDBC SQL escape последовательности:
call ключевое слово escape-последовательности;
proc_name имя хранимой процедуры;
? - не обязательные параметры.
Ниже приведен пример создания хранимой процедуры, использующей функцию человек учебной базы данных, которая по номеру сотрудника выдает его фамилию и инициалы.
//Занятие 2, пример 2-7
public static void createProc() throws SQLException
Statement st = conn.createStatement();
String sql = "CREATE PROCEDURE get_fio "
+"(id IN NUMBER, fio OUT VARCHAR) AS "
+"SELECT человек(id, 'И', 9) INTO fio FROM DUAL; "
st.executeUpdate("DROP PROCEDURE get_fio");
> catch (SQLException se)
//Игнорировать ошибку удаления процедуры
String msg = se.getMessage();
System.out.println("Ошибка при удалении процедуры: "+msg);
System.out.println("Процедура get_fio создана. ");
public static void executeProc() throws SQLException
CallableStatement cst = conn.prepareCall(sql);
System.out.println("Результат запроса: "+cst.getString(2));
Для изучения интерфейса CallabeStatement необходимо создать класс использующий main метод для регистрации драйвера и создания соединения с базой данных. Для создания таблицы и заполнения ее данными необходимо использовать отдельные методы (аналогичные приведенным в примере).
Sentencia SQL Update — Ejemplo de Consultas para Actualizar los Valores de una Tabla
Juan Carrillo

SQL (pronunciado Seequel) significa lenguaje de consulta estructurado (Structured Query Language). Es un lenguaje de consulta fuertemente tipado (los tipos se comprueban antes del tiempo de ejecución) y estático que apareció por primera vez en 1974 (¡Woah, 46 años!), pero no se publicó inicialmente hasta 1986.
Podrías pensar que una herramienta tan "vieja" tienes sus mejores días detrás de ella, pero estarías lejos de estar en lo cierto. En 2019, a través de la encuesta de Scale Grid DeveloperWeek, SQL fue utilizado por el 60.5% de los encuestados, mientras que NoSQL fue utilizado por solo el 39.5% de los encuestados.
Para ser claros, la categoría SQL se dividió en varias subcategorías que incluían MySQL, PostgreSQL, SQL Server, etc., mientras que la categoría NoSQL se dividió en subcategorías que contenían MongoDB, Cassandra, etc.
Incluso en 2017, según la Stack Overflow Developer's Survey, el segundo lenguaje más utilizado fue SQL (justo detrás de JavaScript) con el 50% de los 64,000 encuestados diciendo que todavía utilizan SQL en alguna forma.
Su popularidad se debe, al menos en parte, a la simplicidad del lenguaje, al hecho de que fue construido con datos relacionales en mente, y porque ha demostrado ser fiable para buscar, unir y filtrar datos.
Basta con decir que SQL no sólo está vivito y coleando, sino que prospera entre la comunidad de desarrollo de hoy en día.
¡Ahora vamos a ver por qué!
Las partes divertidas
SQL Server es el sabor preferido de SQL que utilizo en mis actividades cotidianas en el trabajo, por lo que los ejemplos siguientes se ajustarán a esas normas.
Una de las cosas que más me gusta hacer es actualizar varios registros dentro de una tabla. Ahora podría hacer este registro de uno en uno, pero SQL nos da la capacidad de actualizar múltiples (miles y miles si es necesario) registros a la vez a través de la declaración UPDATE .
La declaración UPDATE puede utilizarse para actualizar una sola columna, un conjunto más amplio de registros (mediante el uso de condiciones), y/o toda la tabla en una base de datos. La(s) condición(es) puede(n) ser un booleano, una verificación de cadena de texto o una secuencia matemática que se resuelve en un booleano (mayor que, menos que, etc.).
Aunque puede variar ligeramente de un sabor a otro, la sintaxis general es la siguiente:
UPDATE nombre-de-la-tabla SET nombre-de-la-columna = valor[, nombre-de-la-columna=valor] [WHERE condición]
Los corchetes ( [] ) de arriba denotan adiciones opcionales a la consulta.
***Es muy importante tener en cuenta que sin la condición de WHERE, TODOS los registros de la tabla se actualizarán tan pronto como se ejecute la consulta.***
Consultas de ejemplo
Como nuestro conjunto de datos, usaré esta tabla llamada Work_Tickets:
| SalesOrderNum | WorkTicketNum | Customer_Code | Customer_Contact | UnitCost | Billed | ParentLineKey | Qty_Ordered | Qty_Shipped |
| 00061356 | 000931 | 1250 | sales@wayneindustries.com | 0.00 | False | 079777 | 12.0 | 0 |
| 00061357 | 000932 | 1251 | contact@starkindustries.com | 0.00 | False | 085695 | 196.5 | 0 |
| 00061358 | 000933 | 1252 | animation@acmetoons.com | 0.00 | False | 085569 | 17.5 | 0 |
Consulta simple sin condiciones
Aquí hay una consulta de actualización muy simple que cambiará todos los campos de UnitCost al número 131.6152 :
UPDATE Work_Tickets SET UnitCost = 131.6152
Nota que no hay cláusula de WHERE , así que cada línea de la tabla se actualizará y nuestro conjunto de datos se verá así:
| SalesOrderNum | WorkTicketNum | Customer_Code | Customer_Contact | UnitCost | Billed | ParentLineKey | Qty_Ordered | Qty_Shipped |
| 00061356 | 000931 | 1250 | sales@wayneindustires.com | 131.6152 | False | 079777 | 12.0 | 0 |
| 00061357 | 000932 | 1251 | contact@starkindustries.com | 131.6152 | False | 085695 | 196.5 | 0 |
| 00061358 | 000933 | 1252 | animation@acmetoons.com | 131.6152 | False | 085569 | 17.5 | 0 |
Consultas simples con condición(es)
Aquí hay una simple consulta con una declaración de condición:
UPDATE Work_Tickets SET Billed = true WHERE UnitCost <> 0.00
Esta consulta actualizará el campo de Billed para que sea true en cada línea que coincida con la condición de UnitCost no igual a 0. Después de ejecutar nuestra consulta, el conjunto de datos se verá así:
| SalesOrderNum | WorkTicketNum | Customer_Code | Customer_Contact | UnitCost | Billed | ParentLineKey | Qty_Ordered | Qty_Shipped |
| 00061356 | 000931 | 1250 | sales@wayneindustires.com | 131.6152 | True | 079777 | 12.0 | 0 |
| 00061357 | 000932 | 1251 | contact@starkindustries.com | 131.6152 | True | 085695 | 196.5 | 0 |
| 00061358 | 000933 | 1252 | animation@acmetoons.com | 131.6152 | True | 085569 | 17.5 | 0 |
Abajo hay una consulta en la que cambiamos el ParentLineKey por la cadena 000134 en la que el SalesOrderNum y el WorkTicketNum coinciden con las cadenas dadas.
UPDATE Work_Tickets SET ParentLineKey = 000134 WHERE SalesOrderNum = 00061358 and WorkTicketNumber = 000933
Así que, el 085569 en el campo ParentLineKey será reemplazado por 000134 y nuestro conjunto de datos ahora se ve así:
| SalesOrderNum | WorkTicketNum | Customer_Code | Customer_Contact | UnitCost | Billed | ParentLineKey | Qty_Ordered | Qty_Shipped |
| 00061356 | 000931 | 1250 | sales@wayneindustires.com | 131.6152 | True | 079777 | 12.0 | 0 |
| 00061357 | 000932 | 1251 | contact@starkindustries.com | 131.6152 | True | 085695 | 196.5 | 0 |
| 00061358 | 000933 | 1252 | animation@acmetoons.com | 131.6152 | True | 000134 | 17.5 | 0 |
Actualizando múltiples campos
Digamos que tienes un conjunto de datos mucho más grande que el que estamos usando actualmente y tienes varios campos para actualizar.
Sería tedioso y aburrido actualizarlos con diferentes declaraciones de actualización. Por suerte para nosotros también es posible actualizar varios campos a la vez con una declaración de actualización (update), siempre y cuando separemos los nombres de las columnas con una coma:
UPDATE Work_Tickets SET UnitCost = 129.8511, Qty_Ordered = 72, Qty_Shipped = 72 WHERE SalesOrderNum = 00061358
Y aquí está el resultado con los campos actualizados después de ejecutar la consulta:
| SalesOrderNum | WorkTicketNum | Customer_Code | Customer_Contact | UnitCost | Billed | ParentLineKey | Qty_Ordered | Qty_Shipped |
| 00061356 | 000931 | 1250 | sales@wayneindustires.com | 131.6152 | True | 079777 | 12.0 | 0 |
| 00061357 | 000932 | 1251 | contact@starkindustries.com | 131.6152 | True | 085695 | 196.5 | 0 |
| 00061358 | 000933 | 1252 | animation@acmetoons.com | 129.8511 | True | 000134 | 72 | 72 |
Usando Update en una subconsulta
Los ejemplos anteriores son perfectos si se trabaja con una sola fuente de datos. Sin embargo, la mayoría de tus datos no se almacenarán en una sola tabla. Ahí es donde el uso de UPDATE con múltiples fuentes de datos es útil.
La sintaxis para actualizar una columna/tabla cambia un poco si queremos traer datos de otra tabla:
UPDATE nombre-de-la-tabla SET nombre-de-la-columna = (SELECT nombre de columna(s) FROM nombre-de-la-tabla2 WHERE condición(es)) [WHERE condición]
Y aquí están las dos tablas que usaremos para esta consulta - la tabla Work_Tickets:
| SalesOrderNum | WorkTicketNum | Customer_Code | Customer_Contact | UnitCost | Billed | ParentLineKey | Qty_Ordered | Qty_Shipped |
| 00061356 | 000931 | 1250 | sales@wayneindustires.com | 131.6152 | True | 079777 | 12.0 | 0 |
| 00061357 | 000932 | 1251 | contact@starkindustries.com | 131.6152 | True | 085695 | 196.5 | 0 |
| 00061358 | 000933 | 1252 | animation@acmetoons.com | 129.8511 | True | 000134 | 72 | 72 |
y la tabla Customer_Info:
| Name | Industry | Code | Address | City | Discount | PhoneNumber | |
| Wayne Enterprises | Defense,weaponry,aerospace,enginerring | NULL | 1631 Dark Knight Way | Gotham | 19.75 | 5556614000 | sales@wayneindustires.com |
| Stark Industries | Defense,weaponry,protection | 1251 | 5641 Iron Dr | Undisclosed | 19.73 | 9993126156 | contact@starkindustries.com |
| Acme Corp | Comedy,laughter,animation | 1252 | 24569 Smiling St | Toon Town | 17.53 | 3216549877 | animation@acmetoons.com |
La declaración UPDATE con la subconsulta se ve así:
UPDATE Customer_Info SET Code = (SELECT Customer_Code FROM Work_Tickets WHERE Work_Tickets.Customer_Contact = Customer_Info.Email) FROM Work_Tickets WHERE Code IS NULL
Este ejemplo actualizará el campo Code de la tabla Customer_Info donde la dirección de correo electrónico coincide con la de ambas tablas. Y así es como se ve ahora nuestra tabla Customer_Info:
| Name | Industry | Code | Address | City | Discount | PhoneNumber | |
| Wayne Enterprises | Defense,weaponry,aerospace,enginerring | 1250 | 1631 Dark Knight Way | Gotham | 19.75 | 5556614000 | sales@wayneindustires.com |
| Stark Industries | Defense,weaponry,protection | 1251 | 5641 Iron Dr | Undisclosed | 19.73 | 9993126156 | contact@starkindustries.com |
| Acme Corp | Comedy,laughter,animation | 1252 | 24569 Smiling St | Toon Town | 17.53 | 3216549877 | animation@acmetoons.com |
Concluyendo
Espero que este artículo te haya sido útil para entender cómo funciona la declaración UPDATE en SQL.
¡Ahora estás listo para escribir tus propias sentencias SQL UPDATE como un campeón! ¡Después de hacerlo, me encantará que lo compartieras conmigo en redes sociales!
No olvides visitar mi blog donde frecuentemente publico artículos sobre desarrollo web.
Ya que estás allí, ¿por qué no te inscribes en mi boletín de noticias? Puedes hacerlo en la parte superior derecha de la página principal del blog. Me gusta enviar artículos interesantes (míos y de otros), recursos y herramientas para desarrolladores de vez en cuando.
Si tienes preguntas sobre este artículo o en general, mis MDs están abiertos - ven a saludar en Twitter o en cualquiera de mis otras cuentas de redes sociales que puedes encontrar debajo del botón de suscripción del boletín de noticias en la página principal de mi blog o en mi perfil aquí en fCC 🙂
¡Qué tengas un día increíble y feliz día programando, amigo!
Список вопросов базы знаний
Что будет видно в окне, созданном при помощи приведенного кода?
import java.awt.*;
public class My public static void main(String arg[]) Frame f=new Frame();
f.setLayout(new CardLayout());
f.add(new Button("A"),"First");
f.add(new Button("B"),"Second");
f.add(new Button("C"),"Thead");
f.setSize(200,200);
f.setVisible(true);
>
>
?) Ничего в окне не появится
?) Кнопки "A","B","C" в одну строчку
?) Кнопки "A","B","C" в один столбик
Вопрос id:11352
Тема/шкала: Пакет NET
Какой менеджер компоновок позволяет разместить компоненты в таблице с ячейками равного размера?
?) GridLayout
?) BorderLayout
?) CardLayout
?) FlowLayout
Вопрос id:11353
Тема/шкала: Классы
Какой класс является родительским для потоков ввода данных?
?) DataStream
?) OutputStream
?) InputStream
?) FileInputStream
Вопрос id:11354
Тема/шкала: Основы синтаксиса
Каково максимальное значение для переменной типа byte?
?) зависит от интерпретатора
?) зависит от компилятора
Вопрос id:11355
Тема/шкала: Потоки ввода-вывода
Какой класс пакета java.io позволяет создать поток вывода текстовых данных с учетом кодировки?
?) FilterOutputStream
?) CharArrayWriter
?) OutputStreamWriter
?) OutputStream
Вопрос id:11356
Тема/шкала: Сервлеты / JSP
Какие результаты можно увидеть в окне при попытке компиляции и запуска следующей программы?
import java.awt.*;
public class My extends Frame public void paint(Graphics g) Font f=new Font(“Gothic”,Font.BOLD,24);
g.setFont(f);
g.drawString(“Hello”,20,20);
>
public static void main(String arg[]) My m=new My();
m.setSize(200,200);
m.setVisible(true);
>
>
?) программа откомпилируется и в окне появится слово Hello выведенное шрифтом по умолчанию
?) программа не откомпилируется, так как шрифт Gothic не определен в Java
?) программа откомпилируется, но при попытке запуска возникнет исключительная ситуация типа NullPointerException
?) программа откомпилируется и в окне появится слово Hello выведенное шрифтом Gothic
Вопрос id:11357
Тема/шкала: Потоки ввода-вывода
Исключительная ситуация какого типа возможна при открытии сокетного соединения следующим образом: Socket s=new Socket("www.specialist.ru",80);
?) только BadURLException
?) IOException и UnknownHostException
?) только IOException
?) только MalformedURLException
?) только UnknownHostException
?) IOException и MalformedURLException
Вопрос id:11358
Тема/шкала: Основы синтаксиса
Какие имена переменных допустимы?
Вопрос id:11359
Тема/шкала: Потоки ввода-вывода
Экземпляром какого класса является поле System.in?
?) java.io.InputStream
?) java.io.InputStreamWriter
?) java.io.PrintStream
?) java.lang.System
?) java.io.BufferedInputStream
Вопрос id:11360
Тема/шкала: Пакет NET
Какое выравнивание используется по умолчанию для компоновки FlowLayout?
?) FlowLayout.LEFT
?) FlowLayout.RIGHT
?) FlowLayout.MIDDLE
?) FlowLayout.CENTER
?) Выравнивание надо всегда указывать явно
Вопрос id:11361
Тема/шкала: Классы
Экземпляром какого класса является поле System.err?
?) java.io.PrintStream
?) java.io.OutputStream
?) java.lang.System
?) java.io.ErrorStream
Вопрос id:11362
Тема/шкала: Сервлеты / JSP
Что будет видно в окне, созданном при помощи нижеприведенного кода?
import java.awt.*;
public class My public static void main(String arg[]) Frame f=new Frame();
f.setLayout(new GridLayout(1,3,3,1));
f.add(new Button("A"),"First");
f.add(new Button("B"),"Second");
f.add(new Button("C"),"Thead");
f.setSize(400,400);
f.setVisible(true);
>
>
?) Ничего в окне не появится
?) Кнопки "A","B","C" в один столбик
?) Кнопки "A","B","C" в одну строчку
Вопрос id:11363
Тема/шкала: Основы синтаксиса
Сколько бит оперативной памяти занимает переменная типа char?
?) Объем выделяемой памяти зависит от компилятора
?) Объем выделяемой памяти зависит от интерпретатора
Вопрос id:11364
Тема/шкала: Сервлеты / JSP
Какие результаты можно увидеть на экране при попытке компиляции и запуска следующей программы?
class First int sum(int x,int y) return(x+y);
>
>
public class Second extends First public static void main(String a[]) Second s=new Second();
System.out.println("Summa answer_variants">
?) Программа не откомпилируется из-за того что метод sum не унаследуется классом Second
?) Программа не откомпилируется из-за невозможности создать объект экземпляр класса Second внутри класса Second
?) Программа не откомпилируется из-за отсутствия спецификатора доступа public в описании класса First
Вопрос id:11365
Тема/шкала: Потоки ввода-вывода
Какой класс необходимо использовать клиенту для соединения с сокетом сервера?
?) SocketServer
?) ServerSocket
Вопрос id:11366
Тема/шкала: Пакет SQL
Сколько типов драйверов баз данных различают в JDBC?
?) Никаких различий в типах драйверов не существует
Вопрос id:11367
Тема/шкала: Сервлеты / JSP
Какие результаты можно увидеть на экране при попытке компиляции и запуска следующей программы?
public class My int x=5, y=6;
class MyToo int sum() return(My.this.x+My.this.y);
>
>
public static void main(String arg[]) My m=new My();
My.MyToo mt=m.new MyToo();
System.out.println("sum answer_variants">
?) программа не откомпилируется, так как поля x и y не доступны внутри класса MyToo
?) программа откомпилируется и при выполнении вернет null
?) программа откомпилируется и при выполнении вернет 11
?) программа откомпилируется и при выполнении вернет сообщение о ошибке
?) программа не откомпилируется, так как неправильно создается объект экземпляр класса MyToo
?) программа не откомпилируется, так как метод sum вложенного класса должен иметь спецификатор доступа static
?) программа не откомпилируется, так как методы вложенного класса не имеют спецификатора доступа public
Вопрос id:11368
Тема/шкала: Сервлеты / JSP
В каком пакете находится интерфейс Servlet?
?) В пакете java.http
?) В пакете java.servlet
?) В пакете javax.servlet
?) В пакете javax.servlet.http
Вопрос id:11369
Тема/шкала: Основы синтаксиса
Какой результат появится на экране после выполнения следующей прграммы?
public class My public static void main(String arg[]) cko:
for(int i=0;i
?) Программа не откомпилируется из-за недопустимости присваивания значений полям интерфейсного класса
?) Программа не откомпилируется из-за недопустимости описания полей внутри интерфейсного класса
?) Программа не откомпилируется из-за недопустимости присваивания нового значения полю a, так как это поле имеет спецификатор доступа final
?) Программа не откомпилируется из-за отсутствия спецификатора доступа public в описании интерфейса First
?) Программа не откомпилируется из-за недопустимости использования нестатических полей внутри статического метода
?) Программа не откомпилируется из-за отсутствия спецификатора доступа public в описании поля a внутри интерфейса First
Вопрос id:11377
Тема/шкала: Классы
Какие результаты можно увидеть на экране при попытке компиляции и запуска следующей программы?
final class My public static void main(String a[]) System.out.println("Hello!");
>
>
