Cambia los datos de una tabla o vista.
La instrucción UPDATE se registra; sin embargo, 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", a continuación.
Se pueden utilizar instrucciones UPDATE en el cuerpo de las funciones definidas por el usuario sólo si la tabla que se modifica es una variable table.
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 agrupado hace que el tamaño del índice agrupado y de la fila supere 8.060 bytes, la actualización no se produce y se devuelve un mensaje de error.
Si la instrucción UPDATE pudo cambiar más de una fila durante la actualización de la clave de agrupación 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.
Todas las columnas char y nchar se rellenan a la derecha hasta la longitud definida.
La configuración de la opción SET ROWCOUNT se omite para las instrucciones UPDATE de tablas remotas y vistas locales y remotas con particiones.
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 sólo 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 obtener más información, vea SET ANSI_PADDING (Transact-SQL).
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 utilice una cláusula WHERE <search_condition> 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.
Utilizar UPDATE con la cláusula FROM
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 sólo 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 de la siguiente secuencia de comandos, 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 AdventureWorks;
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);
INSERT INTO dbo.Table1 VALUES(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 AdventureWorks;
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);
INSERT INTO dbo.Table2 VALUES (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
Actualizar 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';
-
Invocar un método, marcado como mutator, 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 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.
|
-
Modificar el valor de un miembro de propiedad registrado o un miembro de datos público 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 Cities
SET Location.X = 23.5
WHERE Name = 'Anchorage';
Para modificar diferentes propiedades de la misma columna de tipo definido por el usuario, emita varias instrucciones UPDATE o invoque un método mutador del tipo.
Actualizar tipos de datos de valores grandes
Utilice la cláusula .WRITE (expression, @Offset, @Length) para realizar una actualización parcial o completa de los tipos 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 sólo los 200 primeros caracteres de la columna, 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 por medio de registros de operaciones masivas o el modelo de recuperación simple. Tenga en cuenta que el registro mínimo no se utiliza cuando se actualizan valores existentes. Para obtener más información, vea Operaciones registradas mínimamente.
El SQL Server 2005 Database Engine (Motor de base de datos de SQL Server 2005) 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 agrupado 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 caracteres para el tipo de datos nvarchar. Se calculan los desplazamientos correspondientes para las intercalaciones del juego de caracteres de doble byte (DBCS).
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 en una cláusula OUTPUT se hace referencia a la columna modificada por la cláusula .WRITE, se devuelve el valor completo de la columna, bien la imagen anterior de deleted.column_name o bien la imagen posterior de inserted.column_name, en la columna especificada en la variable de tabla. Vea el ejemplo G a continuación.
Para obtener la misma funcionalidad de .WRITE con otros tipos de datos de carácter o binarios, utilice STUFF (Transact-SQL).
Actualizar 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 grandes bloques de datos text, ntext o image, utilice WRITETEXT o UPDATETEXT en lugar de la instrucción UPDATE.
Utilizar desencadenadores INSTEAD OF en acciones UPDATE
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 sólo 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 tiene definido un desencadenador INSTEAD OF. Para obtener más información acerca de los desencadenadores INSTEAD OF, vea CREATE TRIGGER (Transact-SQL).
Configurar variables y columnas
Es posible utilizar nombres de variables en las instrucciones UPDATE para mostrar los valores nuevos y antiguos afectados, pero sólo 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, utilice la cláusula OUTPUT.
A. Utilizar una instrucción UPDATE simple
En los ejemplos siguientes se muestra cómo se pueden ver afectadas todas las filas si no se utiliza 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 Bonus, CommissionPct y SalesQuota de todas las filas de la tabla SalesPerson.
USE AdventureWorks;
GO
UPDATE Sales.SalesPerson
SET Bonus = 6000, CommissionPct = .10, SalesQuota = NULL;
GO
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.
USE AdventureWorks ;
GO
UPDATE Production.Product
SET ListPrice = ListPrice * 2;
GO
B. Utilizar 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. Por ejemplo, Adventure Works Cycles vende su modelo de bicicleta Road-250 en dos colores: rojo y negro. La compañía ha decidido cambiar el color rojo de este modelo por el rojo metalizado. La instrucción siguiente actualiza las filas de la tabla Production.Product para todos los productos Road-250 de color rojo.
USE AdventureWorks;
GO
UPDATE Production.Product
SET Color = N'Metallic Red'
WHERE Name LIKE N'Road-250%' AND Color = N'Red';
GO
C. Utilizar 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 AdventureWorks;
GO
UPDATE Sales.SalesPerson
SET SalesYTD = SalesYTD + SubTotal
FROM Sales.SalesPerson AS sp
JOIN Sales.SalesOrderHeader AS so
ON sp.SalesPersonID = so.SalesPersonID
AND so.OrderDate = (SELECT MAX(OrderDate)
FROM Sales.SalesOrderHeader
WHERE SalesPersonID =
sp.SalesPersonID);
GO
En el ejemplo anterior se asume que sólo 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 este ejemplo:
USE AdventureWorks;
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.SalesPersonID = so.SalesPersonID
GROUP BY so.SalesPersonID);
GO
D. Utilizar UPDATE con la cláusula TOP
En el ejemplo siguiente se actualiza un 25 por ciento la columna VacationHours en 10 filas aleatorias de la tabla Employee.
USE AdventureWorks;
GO
UPDATE TOP (10) HumanResources.Employee
SET VacationHours = VacationHours * 1.25 ;
GO
E. Utilizar UPDATE con la cláusula OUTPUT
En el ejemplo siguiente se actualiza un 25 por ciento la columna VacationHours de las 10 primeras filas de la tabla Employee. 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 table @MyTableVar.
A continuación, dos instrucciones SELECT devuelven los valores de @MyTableVar y los resultados de la operación de actualización en la tabla Employee. Observe que los resultados de la columna INSERTED.ModifiedDate son diferentes de los valores de la columna ModifiedDate de la tabla Employee . Esto se debe a que el desencadenador AFTER UPDATE que actualiza el valor de ModifiedDate con la fecha actual se define en la tabla Employee. Sin embargo, las columnas devueltas de OUTPUT reflejan los datos antes de activarse los desencadenadores. Para obtener más ejemplos donde se utiliza la cláusula OUTPUT, vea OUTPUT (cláusula de Transact-SQL).
USE AdventureWorks;
GO
DECLARE @MyTableVar table(
EmpID int NOT NULL,
OldVacationHours int,
NewVacationHours int,
ModifiedDate datetime);
UPDATE TOP (10) HumanResources.Employee
SET VacationHours = VacationHours * 1.25
OUTPUT INSERTED.EmployeeID,
DELETED.VacationHours,
INSERTED.VacationHours,
INSERTED.ModifiedDate
INTO @MyTableVar;
--Display the result set of the table variable.
SELECT EmpID, OldVacationHours, NewVacationHours, ModifiedDate
FROM @MyTableVar;
GO
--Display the result set of the table.
--Note that ModifiedDate reflects the value generated by an
--AFTER UPDATE trigger.
SELECT TOP (10) EmployeeID, VacationHours, ModifiedDate
FROM HumanResources.Employee;
GO
F. Utilizar UPDATE con la cláusula WITH common_table_expression
En el ejemplo siguiente se actualiza el valor de VacationHours un 25 por ciento para todos los empleados que mantienen informado a ManagerID 12 directa o indirectamente. La expresión de tabla común devuelve una lista jerárquica de los empleados que dependen directamente de ManagerID 12 y los empleados que dependen de esos empleados, y así sucesivamente. Sólo se modifican las filas devueltas por la expresión de tabla común. Para obtener información sobre las expresiones de tabla comunes recursivas, vea Consultas recursivas mediante expresiones de tabla comunes.
USE AdventureWorks;
GO
WITH DirectReports(EmployeeID, NewVacationHours, EmployeeLevel)
AS
(SELECT e.EmployeeID, e.VacationHours, 1
FROM HumanResources.Employee AS e
WHERE e.ManagerID = 12
UNION ALL
SELECT e.EmployeeID, e.VacationHours, EmployeeLevel + 1
FROM HumanResources.Employee as e
JOIN DirectReports AS d ON e.ManagerID = d.EmployeeID
)
UPDATE HumanResources.Employee
SET VacationHours = VacationHours * 1.25
FROM HumanResources.Employee AS e
JOIN DirectReports AS d ON e.EmployeeID = d.EmployeeID;
GO
G. Utilizar UPDATE con la cláusula .WRITE para modificar los datos de una columna de tipo nvarchar(max)
En el ejemplo siguiente se utiliza 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 featuresal especificar 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 se utiliza también la cláusula OUTPUT para devolver las imágenes anterior y posterior de la columna DocumentSummary en la variable table @MyTableVar.
USE AdventureWorks;
GO
DECLARE @MyTableVar table (
DocumentID int NOT NULL,
SummaryBefore nvarchar(max),
SummaryAfter nvarchar(max));
UPDATE Production.Document
SET DocumentSummary .WRITE (N'features',28,10)
OUTPUT INSERTED.DocumentID,
DELETED.DocumentSummary,
INSERTED.DocumentSummary
INTO @MyTableVar
WHERE DocumentID = 3 ;
SELECT DocumentID, SummaryBefore, SummaryAfter
FROM @MyTableVar;
GO
H. Utilizar 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 utilizar la cláusula .WRITE para modificar una columna NULL, primero se llena la columna con datos temporales. Después, estos datos se sustituyen 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 AdventureWorks;
GO
-- Replacing NULL value with temporary data.
UPDATE Production.Document
SET DocumentSummary = N'Replacing NULL value'
WHERE DocumentID = 1;
GO
SELECT DocumentSummary
FROM Production.Document
WHERE DocumentID = 1;
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 DocumentID = 1;
GO
SELECT DocumentSummary
FROM Production.Document
WHERE DocumentID = 1;
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 DocumentID = 1;
GO
SELECT DocumentSummary
FROM Production.Document
WHERE DocumentID = 1;
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 DocumentID = 1;
GO
SELECT DocumentSummary
FROM Production.Document
WHERE DocumentID = 1;
GO
-- Removing partial data beginning at position 9 and ending at
-- position 21.
UPDATE Production.Document
SET DocumentSummary .WRITE ('',9, 12)
WHERE DocumentID = 1;
GO
SELECT DocumentSummary
FROM Production.Document
WHERE DocumentID = 1;
GO
I. Utilizar 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). Se utiliza la función OPENROWSET 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 AdventureWorks;
GO
UPDATE Production.ProductPhoto
SET ThumbNailPhoto = (
SELECT *
FROM OPENROWSET(BULK 'c:\Tires.jpg', SINGLE_BLOB)AS x )
WHERE ProductPhotoID = 1;
GO