Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Actualizacion de Datos SQL
Actualizacion de Datos SQL
nb_NuevaTabla es el nombre de la tabla que se va a crear, si en la base de datos ya hay una tabla con
ese nombre, el sistema genera un error y no se ejecuta la sentencia.
En la nueva tabla las columnas tendrn el mismo tipo y tamao que las columnas del resultado de la
SELECT, se llamarn con el nombre de alias de la columna o en su defecto con el nombre de la
columna, pero no se transfiere ninguna otra propiedad del campo o de la tabla como por ejemplo las
claves e ndices.
Si retomamos el ejemplo del punto anterior:
CREATE TABLE trabajo (col1 INT, col2 VARCHAR(20), col3 MONEY);
INSERT INTO trabajo SELECT oficina, ciudad, ventas
FROM oficinas
WHERE region = 'Centro';
Se podra obtener el mismo resultado con una sola instruccin:
SELECT oficina AS col1, ciudad AS col2, ventas AS col3
INTO trabajo
FROM oficinas
WHERE region = 'Centro'
Si se tiene poca experiencia en esta instruccin, lo mejor es primero escribir la SELECT que permite
obtener las filas a insertar y una vez la tenemos aadir la clusula INTO destino delante de FROM.
Objetivo
Crear una tabla a partir de los datos de otra, con SELECT ... INTO.
<destino> ::=
{
[nbBaseDatos.nbEsquema. | nbEsquema.]nbTablaVista
}
Con esta instruccin podemos insertar una fila de valores determinados o un conjunto de filas
derivadas de otra consulta.
En este caso hemos indicado slo dos columnas y dos valores, las dems columnas se rellenan con el
valor por defecto si lo tiene (DEFAULT) o con NULL. Si alguna columna no nombrada no admite nulos ni
tiene clusula DEFAULT definida, la instruccin dar error.
INSERT INTO oficinas
VALUES (27,'Mstoles','Centro',default ,null, default)
Aqu no hemos indicado una lista de columnas luego los valores se tienen que indicar en el mismo
orden que las columnas dentro de la tabla, si nos equivocamos de orden, el valor se guardar en una
columna errnea (si los tipos son compatibles) o generar un mensaje de error y la fila no se insertar
(si los tipos no son compatibles).
Objetivo
Insertar una fila de datos en una tabla ya existente.
Si los valores que queremos insertar los tenemos en otras tablas, podemos insertar varias filas a la vez
indicando una consulta que genere las filas de valores a insertar. En este caso utilizamos la sintaxis:
INSERT [INTO] <destino> [(lista_columnas)]
tabla_derivada [;]
<destino> y lista_columnas funcionan igual que en el punto anterior.
Tabla_derivada es cualquier instruccin SELECT vlida que devuelva filas con los datos que se van a
cargar en el destino.
Cada fila devuelta por la SELECT es una lista de valores que se intentar insertar como con la clusula
VALUES, por lo que las columnas devueltas por la SELECT debern cumplir las mismas reglas que los
valores de la lista de valores anteriores.
Ejemplo:
CREATE TABLE trabajo (col1 INT, col2 VARCHAR(20), col3 MONEY);
Creamos una tabla trabajo de 3 columnas
INSERT INTO trabajo SELECT oficina, ciudad, ventas
FROM oficinas
WHERE region = 'Centro';
Insertamos en trabajo el resultado de la SELECT (el nmero de oficina, ciudad y ventas de las
oficinas del Centro).
En este caso no hemos incluido una lista de columnas, por lo que en la SELECT tenemos que generar
los valores en el mismo orden que en trabajo.
Si hubiesemos escrito:
INSERT INTO trabajo SELECT ciudad, oficina, ventas
FROM oficinas
WHERE region = 'Centro';
Hubiese dado error porque la columna col1 es INT y el valor a asignar es texto (el nombre de la ciudad
de la oficina).
INSERT INTO trabajo (col2, col1)
SELECT ciudad, oficina
FROM oficinas
Objetivo
Copiar un conjunto de filas de una tabla ya existente a otra.
En una misma sentencia podemos actualizar varias columnas, slo tenemos que indicar las distintas
asignaciones separadas por comas:
UPDATE oficinas SET ventas = 0, objetivo = 0;
Los nombres de columna pueden especificarse en cualquier orden.
Si no queremos actualizar todas las filas de la tabla sino unas cuantas, utilizaremos la clusula TOP, o
unas determinadas, utilizaremos la clusula WHERE.
TOP ( expresion ) [ PERCENT ]
Especifica el nmero o porcentaje de filas aleatorias que se van a modificar.
expression debe generar un valor numrico e indica el nmero de filas a modificar empezando por el
principio. Como en la SELECT, si aadimos la palabra PERCENT, el nmero representado por expresin
se refiere al porcentaje de filas a modificar sobre el total. La clusula TOP funciona casi igual que en la
SELECT pero en este caso, las filas no se ordenan, y la expresin debe ir entre parntesis.
Por ejemplo:
UPDATE TOP (10) PERCENT oficinas
SET ventas = 0;
Actualiza el 10% de filas de la tabla oficinas.
[ WHERE <condicion> ]
Utilizamos la clusula WHERE para filtrar las filas a actualizar. Se actualizarn todas las filas que
cumplan la condicin. Por ejemplo si queremos actualizar slo las oficinas del Este:
UPDATE oficinas
SET ventas = 0
WHERE region = 'Este';
Cuando para la condicin de la clusula WHERE necesitamos un dato de otra tabla podemos utilizar
una subconsulta:
UPDATE empleados SET ventas = 0
WHERE oficina IN (SELECT oficina
FROM oficinas
WHERE region = 'Este');
Cuando el campo de la otra tabla se utiliza para la clusula SET, entonces debemos utilizar la clusula
FROM.
La clusula FROM permite definir un origen de datos basado en varias tablas, y ese origen ser el
utilizado para realizar la actualizacin.
Por ejemplo queremos actualizar el importe de los pedidos con el precio de la tabla productos.
UPDATE pedidos SET importe = cant * precio
FROM pedidos INNER JOIN productos
ON fab = idfab AND producto = idproducto;
Modificamos la tabla pedidos dejando en la columna importe el resultado de multiplicar la cantidad del
pedido por el precio del producto que se encuentra en la tabla productos.
Si la actualizacin de una fila infringe una restriccin o una regla, infringe la configuracin de valores
NULL de la columna o si el nuevo valor es de un tipo de datos incompatible con la columna, se cancela
la instruccin, se devuelve un error y no se actualiza ningn registro.
Cuando una instruccin UPDATE encuentra un error aritmtico (error de desbordamiento, divisin por
cero o de dominio) durante la evaluacin de la expresin, la actualizacin no se lleva a cabo. El resto
del lote no se ejecuta y se devuelve un mensaje de error.
Adems del permiso de UPDATE, se requieren permisos SELECT para la tabla que se actualiza si la
instruccin UPDATE contiene una clusula WHERE o en el caso de que el argumento expression de la
clusula SET utilice una columna de la tabla, y permisos SELECT para la tabla del origen si utilizamos
una clusula FROM o un WHERE con subconsulta.
Objetivo
Modificar los datos de una tabla.
xk47
3,73
qsa
xk48
1,41
qsa
xk48a
1,55
Poner a cero las ventas y cuota del empleado Luis Garcia, si hay varios con el mismo nombre
actualizarlos todos. (1 filas afectadas)
UPDATE empleados set ventas=0, cuota=0
WHERE nombre = 'Luis Garcia';
Cambiar los empleados de la oficina 40 a la oficina 30. (3 filas afectadas)
UPDATE empleados SET oficina = 30
WHERE oficina = 40;
Actualizar los pedidos del fabricante rei dejando como representante el empleado asignado al cliente
(2 filas afectadas). Lo ms cmodo es, primero sacar la consulta que obtiene los pedidos a actualizar, y
despus convertirla a UPDATE.
UPDATE pedidos SET rep=numemp
FROM pedidos inner join (clientes inner join empleados ON repclie=numemp) ON clie=numclie
WHERE rep <> numemp and fab ='rei'
Estos son los pedidos afectados y cmo deben quedar, los pedidos en los que el representante ya es el
correcto no se tienen que actualizar:
codigo numpedido clie
rep fab
20
113042
2113
104
rei
21
113045
2112
108
rei
Actualizar el campo objetivo de la oficina 30 con las cuotas de los empleados asignados a ella.
UPDATE oficinas set oficinas.objetivo =(SELECT SUM (cuota)
from empleados where oficinas.oficina= empleados.oficina)
where oficina=30;
Actualizar el precio de los productos de BIC obteniendo el nuevo valor del precio medio del artculo
vendido en los pedidos (si hay pedidos). Primero sacamos la lista y despus redactar la UPDATE. Se puede
hacer de dos formas, actualizando nicamente los productos de BIC que tienen pedidos, o actualizando
todos los productos de BIC. En cualquiera de los dos casos los productos debern acabar con el precio
que aparece en la columna Nuevo.
UPDATE productos SET precio = round(ISNULL((SELECT avg(importe/cant) FROM pedidos WHERE
fab=idfab and producto=idproducto),precio),2)
WHERE idfab='bic';
Estos son los productos que tenemos de BIC, precio es el precio actual, media es el precio medio de
pedidos, y nuevo el valor que deber quedar en precio despus de actualizar:
idfab idproducto precio media nuevo
bic
41003
6,52
5,1566
5,16
bic
41089
2,25
NULL
2,25
bic
41672
1,80
NULL
1,80
La segunda clusula FROM sirve para indicar un origen que permita una condicin de WHERE sobre
una tabla diferente de destino.
La instruccin bsica sera pues:
DELETE oficinas;
Equivalente a:
DELETE FROM oficinas;
Con esta instruccin eliminamos todas las filas de la tabla oficinas.
La clusula WHERE permite eliminar determinadas filas, indica una condicin que deben cumplir las
filas que se eliminan.
Por ejemplo:
DELETE oficinas
WHERE region = Este;
Elimina las oficinas del Este.
TOP ( expresion ) [ PERCENT ]
Especifica el nmero o porcentaje de filas aleatorias que se van a eliminar.
expression debe generar un valor numrico e indica el nmero de filas a eliminar empezando por el
principio. Como en la SELECT, si aadimos la palabra PERCENT, el nmero representado por expresin
se refiere al porcentaje de filas a eliminar sobre el total. La clusula TOP funciona casi igual que en la
SELECT pero en este caso, las filas no se ordenan, y la expresin debe ir entre parntesis.
Por ejemplo:
DELETE TOP (10) PERCENT
FROM oficinas;
Elimina el 10% de filas de la tabla oficinas.
Originalmente slo se poda indicar una tabla en la clusula FROM, pero ahora podemos indicar un
origen basado en varias tablas.
Si utilizamos un origen basado en varias tablas, se debe de utilizar una extensin de TRANSACT-SQL
que consiste en escribir dos clusulas FROM, una indica la tabla de donde eliminamos las filas y la otra
el origen que utilizamos para eliminar.
Este caso se produce cuando las filas a eliminar dependen de un valor que est en otra tabla. Por
ejemplo queremos eliminar los empleados de las oficinas del Este. Como la regin de la oficina no est
en empleados, habra que aadir al origen la tabla oficinas para poder formular la condicin del
WHERE:
DELETE FROM empleados
FROM empleados INNER JOIN oficinas
ON empleados.oficina = oficinas.oficina
WHERE region = 'Este';
En el origen tenemos las dos tablas y en la primera FROM indicamos de qu tabla queremos borrar.
Esto se poda haber resuelto, como toda la vida, mediante una subconsulta:
DELETE FROM empleados
WHERE oficina IN (SELECT oficina
FROM oficinas
WHERE region = 'Este');
Para finalizar no debemos olvidar que para poder ejecutar un DELETE se requieren permisos DELETE en
la tabla de donde vamos a eliminar, y tambin se requieren los permisos para utilizar SELECT si la
instruccin contiene una clusula WHERE.
Muy importante siempre que actualicemos datos en nuestras tablas, no debemos olvidar tampoco las
reglas de integridad referencial. Si la tabla afectada interviene como tabla principal en una relacin con
otra tabla, no se podrn eliminar sus filas que estn relacionadas con registros de la otra tabla (no se
pueden eliminar padres que tengan hijos ). Si se van a eliminar varias filas y al menos una no se
puede eliminar por infringir las reglas de integridad, entonces la operacin abortar y no se eliminar
ninguna fila.
En el ejemplo anterior, si un empleado asignado a una oficina del Este tiene pedidos, no se podr
eliminar y entonces no se eliminar ningn empleado.
Objetivo
Eliminar registros de una tabla utilizando DELETE.
Pero no todo son ventajas, no se puede utilizar TRUNCATE TABLE en las siguientes tablas:
Tablas a las que se hace referencia mediante una restriccin FOREIGN KEY (las tablas que entran
como principales en una relacin).
Tablas que participan en una vista indizada.
1. Aadir a la oficina 40 otro empleado, Luis Valverde, con nmero de empleado 436, con los
mismos datos que el anterior pero su jefe ser el director de la oficina 40 (no sabemos qu nmero
tiene).
2. Pasar los pedidos de octubre 1989 a diciembre 2008. (3 filas afectadas)
3. Queremos actualizar el importe de los pedidos del mes actual con el precio almacenado en la
tabla productos.
Ayuda: En un primer paso obtener los pedidos del mes actual obteniendo tambin el precio unitario
dentro del pedido y el precio del producto de la tabla de productos.
codigo numpedido
fechapedido
110036
2008-12-12 00:00:00.000
22,50
2,50
NULL
110037
2008-12-12 00:00:00.000
31,50
4,50
45,00
112979
2008-12-12 00:00:00.000
150,00
25,00
NULL
112989
2008-12-10 00:00:00.000
14,58
2,43
2,43
16
113013
2008-12-28 00:00:00.000
6,52
6,52
5,16
Actualizar despus la tabla de pedidos cambiando los importes para que el precio unitario corresponda
con el precio del producto. Los pedidos de los productos que no tienen precio se quedarn como
estaban. (3 filas afectadas)
codigo numpedido
fechapedido
110036
2008-12-12 00:00:00.000
22,50
2,50
NULL
110037
2008-12-12 00:00:00.000
315,00
4,50
45,00
112979
2008-12-12 00:00:00.000
150,00
25,00
NULL
112989
2008-12-10 00:00:00.000
14,58
2,43
2,43
16
113013
2008-12-28 00:00:00.000
5,16
6,52
5,16
1.
Se ven algunos productos que no tienen precio, ahora vamos a actualizar el precio de estos
productos con el precio medio utilizado en los pedidos donde aparecen.
2.
Ayuda: Primero sacamos los productos que queremos actualizar con los pedidos
correspondientes:
fechapedido
aci
41001
NULL
NULL
NULL
NULL
NULL
NULL
aci
41002
NULL
10
112992
1990-04-15 20:00:00.000
7,60
0,76
aci
41002
NULL
18
113027
2008-02-05 00:00:00.000
450,00
8,3333
aci
41003
NULL
15
113012
2008-05-05 00:00:00.000
37,45
1,07
aci
41004
NULL
112963
2008-05-10 00:00:00.000
3,276
0,117
aci
41004
NULL
112968
1990-01-11 00:00:00.000
39,78
1,17
aci
41004
NULL
112983
2008-05-10 00:00:00.000
7,02
1,17
aci
4100x
NULL
25
113055
2009-04-01 00:00:00.000
1,50
0,25
aci
4100x
NULL
26
113057
2008-11-01 00:00:00.000
NULL
NULL
aci
4100y
NULL
112987
2008-01-01 00:00:00.000
275,00
25,00
aci
4100z
NULL
110036
2008-12-12 00:00:00.000
22,50
2,50
aci
4100z
NULL
112979
2008-12-12 00:00:00.000
150,00
25,00
Vemos que el producto ACI 41001 no se podr actualizar porque no tiene pedidos. Pero los dems
se actualizarn con el precio medio de sus pedidos, debern quedar as (7 filas afectadas):
idfab idproducto precio
aci
41001
NULL
aci
41002
4,55
aci
41003
1,07
aci
41004
0,82
aci
4100x
0,25 *
aci
4100y
25,00
aci
4100z
13,75
* aci 4100x tiene 2 pedidos pero uno sin precio por lo que no cuenta
Puedes consultar aqu las soluciones propuestas.
1. Aadir a la oficina 40 otro empleado, Luis Valverde, con nmero de empleado 436, con los mismos
datos que el anterior pero su jefe ser el director de la oficina 40 (no sabemos qu nmero tiene).
INSERT INTO empleados (numemp, nombre, titulo, contrato, ventas, cuota, oficina, jefe)
SELECT 436, 'Luis Valverde','Vendedor', GETDATE(), 0, 1200.45, 40, dir
FROM oficinas WHERE oficina = 40;
2. Pasar los pedidos de octubre 1989 a diciembre 2008. (3 filas afectadas)
UPDATE pedidos SET fechapedido=DATEADD(month,230,fechapedido)
WHERE year(fechapedido)=1989 and month(fechapedido)=10;
3. Queremos actualizar el importe de los pedidos del mes actual con el precio almacenado en la tabla
productos.
SELECT codigo, numpedido,fechapedido,cant, importe,importe/cant AS [precio pedido],precio
FROM pedidos inner join productos ON fab=idfab and producto = idproducto
WHERE YEAR(fechapedido)=YEAR(GETDATE()) and MONTH(fechapedido)=MONTH(GETDATE())
Actualizar despus la tabla de pedidos cambiando los importes para que el precio unitario corresponda
con el precio del producto. Los pedidos de los productos que no tienen precio se quedarn como
estaban. (3 filas afectadas)
UPDATE pedidos SET importe=cant*precio
FROM pedidos inner join productos ON fab=idfab and producto = idproducto
WHERE year(fechapedido)=2008 and month(fechapedido)=12 AND precio IS NOT NULL;
4. Se ven algunos productos que no tienen precio, ahora vamos a actualizar el precio de estos
productos con el precio medio utilizado en los pedidos donde aparecen. La primera SELECT saca los
productos que queremos actualizar con los pedidos correspondientes.
SELECT idfab, idproducto, precio, codigo, numpedido,fechapedido,importe, importe/cant
FROM productos left join pedidos on idfab=fab AND idproducto=producto
WHERE precio IS NULL;
empleados
WHERE
empleados.oficina
oficinas.oficina);
7. Intenta eliminar el empleado 102. Te saldr un error : "Instruccin DELETE en conflicto con la
restriccin..."
DELETE empleados WHERE numemp=102;
Reflexiona sobre el error y elabora una consulta que liste los empleados que pueden dar problemas
(aqu no se trata de utilizar operaciones aprendidas en este tema sino de practicar la integridad
referencial y de paso recordar instrucciones vistas en temas anteriores).
SELECT * from empleados
WHERE numemp IN (select jefe from empleados)
UNION ALL
SELECT * FROM empleados
WHERE numemp IN (SELECT dir FROM oficinas)
UNION ALL
SELECT * FROM empleados
WHERE numemp IN (SELECT rep FROM pedidos)
UNION ALL
SELECT * FROM empleados
WHERE numemp IN (SELECT repclie FROM clientes)
ORDER BY numemp
Elabora ahora una consulta que liste los que se pueden borrar sin problemas.
SELECT numemp FROM empleados
EXCEPT
SELECT numemp from empleados
WHERE numemp IN (select jefe from empleados)
EXCEPT
SELECT numemp FROM empleados
WHERE numemp IN (SELECT dir FROM oficinas)
EXCEPT
SELECT numemp FROM empleados
WHERE numemp IN (SELECT rep FROM pedidos)
EXCEPT
SELECT numemp FROM empleados
WHERE numemp IN (SELECT repclie FROM clientes)
ORDER BY numemp
Borra el primero de la lista, ste s lo puedes borrar.
DELETE empleados WHERE numemp=112;
8. Eliminar los pedidos de productos de ACI cuyo precio de venta en el pedido no corresponda con el
precio unitario del producto de la tabla de productos. (4 filas afectadas)
DELETE FROM pedidos
WHERE fab = 'ACI' AND Importe/cant <> (SELECT precio FROM productos WHERE fab = idfab AND
idproducto = producto);
9. Ahora vamos a recuperar las tablas tal cual estaban al principio, para ello utilizaremos las copias
realizadas al principio de Nuevaoficinas, etc. Lo ms cmodo ser vaciar las tablas y rellenarlas de
nuevo con los datos de las tablas Nueva...
Empieza por eliminar los datos de las tablas. Utilizamos TRUNCATE en la tabla pedidos porque no est
referenciada y para que el contador empiece desde 1 otra vez
TRUNCATE TABLE pedidos
DELETE productos
DELETE clientes
UPDATE oficinas SET dir = NULL; -- Para poder borrar los empleados
UPDATE empleados SET oficina=NULL, jefe=NULL; -- Para poder borrar las oficinas y los empleados
respectivamente.
DELETE oficinas;
DELETE empleados;
Inserta los datos de las tablas Nueva.. a las tablas normales.
INSERT INTO oficinas (oficina, ciudad, region,objetivo,ventas)
SELECT oficina, ciudad, region,objetivo,ventas
FROM Nuevaoficinas;
No podemos rellenar todava la columna Dir ya que no tenemos los empleados dado de alta.
INSERT INTO empleados (numemp, nombre, edad, oficina,titulo,contrato,cuota,ventas)
SELECT numemp, nombre, edad, oficina,titulo,contrato,cuota,ventas
FROM NuevaEmpleados;
Lo mismo pasa con la columna jefe.
UPDATE empleados SET jefe=nueva.jefe
FROM empleados INNER JOIN NuevaEmpleados nueva ON empleados.numemp=nueva.numemp
Estas dos ltimas sentencias se podan haber resumido en una:
INSERT INTO empleados
SELECT *
FROM NuevaEmpleados;
Las hemos dejado en dos porque con otros SQLs no se podra hacer en un slo paso.
UPDATE oficinas SET dir = (SELECT dir FROM Nuevaoficinas nueva
WHERE
oficinas.oficina=nueva.oficina)