cláusula select

113
Cláusula SELECT (SQL Server Compact) Otras versiones Personas que lo han encontrado útil: 0 de 1 - Valorar este tema Especifica las columnas que debe devolver la consulta. Sintaxis SELECT [ ALL | DISTINCT ] TOP (expression) < select_list > < select_list > ::= { * | { table_name | table_alias }.* | { column_name | expression } [ [ AS ] column_alias ] } [ ,...n ] Argumentos ALL Especifica que el conjunto de resultados puede incluir filas duplicadas. ALL es el valor predeterminado. DISTINCT Especifica que el conjunto de resultados sólo puede incluir filas únicas. Los valores NULL se consideran iguales desde el punto de vista de la palabra clave DISTINCT. TOP (expresión) Indica que se devolverá sólo un primer conjunto especificado o porcentaje de filas del conjunto de resultados de la consulta. expression puede ser un número o un porcentaje de filas. Puede utilizar la cláusula TOP en instrucciones SELECT, INSERT, UPDATE y DELETE. Se requieren paréntesis para delimitar la expresión de TOP en las instrucciones INSERT, UPDATE y DELETE. Para compatibilidad con versiones anteriores, se admite el uso de la expresión TOP sin paréntesis en instrucciones SELECT, pero no lo recomendamos. Para obtener más información, vea TOP (SQL Server Compact).

Upload: lena-lawliet

Post on 25-Oct-2015

175 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Cláusula SELECT

Cláusula SELECT (SQL Server Compact)Otras versiones

Personas que lo han encontrado útil: 0 de 1 - Valorar este tema

Especifica las columnas que debe devolver la consulta.

Sintaxis

SELECT [ ALL | DISTINCT ] TOP (expression) < select_list > < select_list > ::= { * | { table_name | table_alias }.* | { column_name | expression } [ [ AS ] column_alias ] } [ ,...n ]

Argumentos

ALLEspecifica que el conjunto de resultados puede incluir filas duplicadas. ALL es el valor predeterminado.

DISTINCTEspecifica que el conjunto de resultados sólo puede incluir filas únicas. Los valores NULL se consideran iguales desde el punto de vista de la palabra clave DISTINCT.

TOP (expresión)Indica que se devolverá sólo un primer conjunto especificado o porcentaje de filas del conjunto de resultados de la consulta. expression puede ser un número o un porcentaje de filas.Puede utilizar la cláusula TOP en instrucciones SELECT, INSERT, UPDATE y DELETE. Se requieren paréntesis para delimitar la expresión de TOP en las instrucciones INSERT, UPDATE y DELETE. Para compatibilidad con versiones anteriores, se admite el uso de la expresión TOP sin paréntesis en instrucciones SELECT, pero no lo recomendamos. Para obtener más información, vea TOP (SQL Server Compact).

< select_list >Columnas que se deben seleccionar para el conjunto de resultados. La lista de selección es una serie de expresiones separadas por comas.

*

Page 2: Cláusula SELECT

Especifica que se deben devolver todas las columnas de todas las tablas de la cláusula FROM. Las columnas se devuelven por tabla, según se especifique en la cláusula FROM, y en el orden en el que aparecen en ella.

table_name| table_alias.*Limita el ámbito de * a la tabla especificada. Requiere que se devuelvan todas las columnas de la tabla especificada en la cláusula FROM. Las columnas se devuelven en el orden en que aparecen en la tabla. Si una tabla tiene un alias especificado en la cláusula FROM, se debe utilizar dicho alias. No se puede usar el nombre de la tabla.

column_nameNombre de una columna que se debe devolver. Para impedir que la referencia sea ambigua, como en el caso de que dos de las tablas de la cláusula FROM tengan columnas con nombres duplicados, se debe calificar column_name. Por ejemplo, si las tablas 'A' y 'B' de una base de datos contienen una columna denominada 'IdElemento' y ambas tablas se combinan en una consulta, IdElemento se debe especificar en la lista SELECT como 'A.IdElemento' y 'B.IdElemento'. Si se ha incluido un alias de tabla, dicho alias se debe usar para calificar el nombre de la columna. En caso contrario, se debe usar el nombre completo de la tabla.

expressionNombre de columna, constante, función o cualquier combinación válida de nombres de columna, constantes y funciones conectados mediante uno o varios operadores.

column_aliasNombre alternativo para sustituir el nombre de la columna en el conjunto de resultados de la consulta. Por ejemplo, se puede especificar un alias como "Cantidad", "Cantidad hasta hoy" o "Cant" para una columna denominada "cantidad". Los alias se emplean también para especificar nombres para los resultados de expresiones; por ejemplo:SELECT AVG([Unit Price]) AS [Average Price] FROM [Order Details]

Nota

column_alias se puede utilizar en una cláusula ORDER BY, pero no en una cláusula WHERE, GROUP BY o HAVING.

Page 3: Cláusula SELECT

Lección 18 - INSERT, UPDATE, DELETE SQL

En esta lección vamos a ver como modificar la BD. Los registros de una tabla pueden

ser modificados de tres modos: Crear nuevos registros, modificarlos o bien eliminarlos.

No se va a profundizar en este sentido, esto lo dejaremos para un posible curso

avanzado de SQL.

Por razones obvias no podrá usar el banco de pruebas para probar estas instrucciones,

de modo que para ello deberá usar su propia BD.

Insert SQL

La instrucción INSERT permite crear o insertar nuevos registros en una tabla, veamos

su sintaxis con un ejemplo práctico, la inserción de un registro en la tabla ALUMNOS:

CÓDIGO: SELECCIONAR TODO

insert into ALUMNOS (ID_ALUMNO , NOMBRE , APELLIDOS , F_NACIMIENTO) 

values (1 , 'Pablo' , 'Hernandaz Mata' , '1995-03-14')

  

Observe como todo lo que se explicó en referencia a los tipos de datos es valido para la

instrucción INSERT. Los datos de tipo numérico no se entrecomillan, a diferencia de los

datos de tipo cadena y fecha.

En general la sintaxis de la instrucción INSERT es la siguiente:

CÓDIGO: SELECCIONAR TODO

Page 4: Cláusula SELECT

INSERT INTO nombre_tabla (lista de campos separados por comas) 

VALUES (lista de datos separados por comas)

  

Donde cada dato de la lista VALUES se corresponde y se asigna a cada campo de la

tabla en el mismo orden de aparición de la sentencia INSERT. Cabe mencionar que si la

clave primaria que identifica el registro que se pretende insertar ya la usa un registro

existente el SGBD rechazaría la operación y devolvería un error de clave primaria

duplicada. 

Así que cuando usted rellena un formulario en Internet por ejemplo, y los datos son

almacenados en una BD, en algún momento del proceso se realizará una instrucción

INSERT con los datos que usted a cumplimentado.

* * *

Update SQL 

La instrucción UPDATE permite actualizar registros de una tabla. Debemos por lo tanto

indicar que registros se quiere actualizar mediante la cláusula WHERE, y que campos

mediante la cláusula SET, además se deberá indicar que nuevo dato va a guardar cada

campo. 

Así por ejemplo supongamos que para el curso que carecía de profesor finalmente ya

se ha decidido quien lo va a impartir, la sintaxis que permite actualizar el profesor que

va a impartir un curso sería la siguiente:

CÓDIGO: SELECCIONAR TODO

update CURSOS

   set ID_PROFE = 2

 where ID_CURSO = 5

Page 5: Cláusula SELECT

Todo lo expuesto sobre lógica booleana es valido para la clausula WHERE de la instrucción

UPDATE, en todo caso dicha cláusula se comporta igual que en una consulta, solo que ahora

en lugar de seleccionar registros para mostrarnos algunos o todos los campos, seleccionará

registros para modificar algunos o todos sus campos. Por lo tanto omitir la cláusula WHERE

en una instrucción UPDATE implica aplicar la actualización a todos los registros de la tabla.

La instrucción anterior asignará un 2 en el campo ID_PROFE de la tabla CURSOS en los

registros cuyo valor en el campo ID_CURSO sea 5. Como sabemos que el campo

ID_CURSO es la clave primaria de la tabla, tan solo se modificará un solo registro si es

que existe. Obviamente en este caso, dado que el campo que se pretende actualizar es

clave foránea de la tabla PROFESORES, si no existe un registro en dicha tabla con

identificador 2 el SGBD devolverá un error de clave no encontrada.

Veamos otro ejemplo, esta vez se modificarán varios campos y registros con una sola

instrucción. Recordemos la tabla EMPLEADOS, en ella se guardan los datos de cada

empleado, el sueldo y supongamos que también se guarda en el campo PRECIO_HORA

el precio de la hora extra que cobra cada empleado en el caso que las trabaje. Bien,

con el cambio de ejercicio se deben subir los sueldos y el precio por hora extra

trabajada, digamos que un 2% el sueldo y un 1 % el precio de la hora extra. Sin

embargo la política de empresa congela el salario a directivos que cobran 3000 euros o

más. ¿Qué instrucción actualizaría estos importes según estas premisas? :

CÓDIGO: SELECCIONAR TODO

update EMPLEADOS

   set SALARIO = SALARIO * 1.02

       PRECIO_HORA = PRECIO_HORA * 1.01 

 where SALARIO < 3000 

Por lo tanto solo se está actualizando el salario y el precio de la hora extra de aquellos

empleados que su salario es inferior a 3000 euros.

En general la sintaxis de la instrucción UPDATE es la siguiente:

CÓDIGO: SELECCIONAR TODO

Page 6: Cláusula SELECT

UPDATE nombre_tabla 

   SET campo1 = valor1,

       campo2 = valor2,

       ...

       campoN = valorM

WHERE condicines

* * *

Delete SQL

La isntrucción DELETE permite eliminar regsitros de una tabla, su sintaxis es simple,

puesto que solo debemos indicar que registros deseamos eliminar mediante la cláusula

WHERE. La siguiente consulta elimina todos los registros de la tabla mascotas que

estan de baja:

CÓDIGO: SELECCIONAR TODO

delete from MACOTAS

 where ESTADO = 'B'

  

Al igua que la instrucción que ocurria con la UPDATE, para la instrucción DELETE es válido

todo lo expuesto sobe la cláusula WHERE para consultas.

La siguiente instrucción elimina todos los registros de la tabla VEHICULOS:

CÓDIGO: SELECCIONAR TODO

delete 

  from VEHICULOS

Page 7: Cláusula SELECT

Al eliminar registros de una tabla estos no deben figurar como clave foránea en otra

tabla, de lo contrario el SGBD devolverá un error de violación de integridad referencial,

puesto que si se permitiese quedarían regsitros huerfanos. 

En general la sintaxis de la instrucción DELETE es la siguiente:

CÓDIGO: SELECCIONAR TODO

DELETE

  FROM nombre_tabla

 WHERE condiniones

* * *

Resumen

Con las instrucciones INSERT, DELETE y UPDATE el SGBD permite crear eliminar o

modificar registros.

La cláusula WHERE de las instrucciones DELETE y UPDATE se comporta igual que en las

consultas y permite descartar o considerar registros mediante condiciones por la

instrucción de actualización o de borrado. Omitir la cláusula WHERE implica aplicar la

operación a todos los registros de la tabla.

Al insertar eliminar o actualizar datos, deben respetarse las restricciones. Si estas

están montadas en la BD, cosa por otro lado muy recomendable, podemos tener

errores de tres tipos: 

Clave primaria duplicada (Al insertar o modificar un registro).

Violación de integridad referencial (se pretende dejar huérfanos registros que

apuntan al registro padre al intentarlo eliminar o modificar).

Clave padre no encontrada (al actualizar o insertar una clave foránea que no

existe en la tabla padre a la que apunta)

Page 8: Cláusula SELECT

DELETE (Transact-SQL)SQL Server 2012

Otras versiones

Personas que lo han encontrado útil: 1 de 1 - Valorar este tema

Quita una o varias filas de una tabla o vista de SQL Server 2012. Convenciones de sintaxis de Transact-SQL

Sintaxis

Transact-SQL

[ WITH <common_table_expression> [ ,...n ] ]DELETE     [ TOP ( expression ) [ PERCENT ] ]     [ FROM ]     { { table_alias      | <object>       | rowset_function_limited       [ WITH ( table_hint_limited [ ...n ] ) ] }       | @table_variable    }    [ <OUTPUT Clause> ]    [ FROM table_source [ ,...n ] ]     [ WHERE { <search_condition>             | { [ CURRENT OF                    { { [ GLOBAL ] cursor_name }                        | cursor_variable_name                    }                 ]              }            }     ]     [ OPTION ( <Query Hint> [ ,...n ] ) ] [; ]

<object> ::={     [ server_name.database_name.schema_name.       | database_name. [ schema_name ] .       | schema_name.

Page 9: Cláusula SELECT

    ]    table_or_view_name }

Argumentos

WITH <common_table_expression>

Especifica el conjunto de resultados de nombre temporal, también conocido como expresión de tabla común, definido dentro del ámbito de la instrucción DELETE. El conjunto de resultados se deriva de una instrucción SELECT.Las expresiones de tabla comunes también se pueden utilizar con las instrucciones SELECT, INSERT, UPDATE y CREATE VIEW. Para obtener más información, vea WITH Common.

TOP (expression) [ PERCENT ]

Especifica el número o el porcentaje de filas aleatorias que se van a eliminar. 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. Para obtener más información, vea TOP (Transact-SQL).

FROM

Palabra clave opcional que se puede usar entre la palabra clave DELETE y el destino table_or_view_name o rowset_function_limited.

table_alias

Alias especificado en la cláusula FROM table_source que representa la tabla o vista de la que se van a eliminar las filas.

server_name

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, son obligatorios database_name y schema_name.

database_name

El nombre de la base de datos.schema_name

Nombre del esquema al que pertenece la tabla o la vista.table_or view_name

Nombre de la tabla o vista cuyas filas se van a quitar.En este ámbito, se puede utilizar una variable de tabla como origen de tabla de una instrucción DELETE.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

Page 10: Cláusula SELECT

definición de vista. Para obtener más información acerca de las vistas que se pueden actualizar, vea CREATE VIEW (Transact-SQL).

rowset_function_limited

Función OPENQUERY u OPENROWSET, dependiendo del proveedor.WITH ( <table_hint_limited> [... n] )

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. No se permiten NOLOCK ni READUNCOMMITTED. Para obtener más información acerca de las sugerencias de tabla, vea Sugerencias de tabla (Transact-SQL).

<OUTPUT_Clause>

Devuelve filas eliminadas, o expresiones basadas en ellas, como parte de la operación DELETE. La cláusula OUTPUT no se admite en instrucciones DML dirigidas a tablas o vistas remotas. Para obtener más información, vea OUTPUT (cláusula de Transact-SQL).

FROM table_source

Especifica una cláusula FROM adicional. Esta extensión de Transact-SQL para DELETE permite especificar datos de <table_source> y eliminar las filas correspondientes de la tabla en la primera cláusula FROM.Se puede utilizar esta extensión, que especifica una combinación, en lugar de una subconsulta en la cláusula WHERE para identificar las filas que se van a quitar.Para obtener más información, vea FROM (Transact-SQL).

WHERE

Especifica las condiciones utilizadas para limitar el número de filas que se van a eliminar. Si no se proporciona una cláusula WHERE, DELETE quita todas las filas de la tabla.Hay dos formas de operaciones de eliminación, que se basan en las condiciones que se especifiquen en la cláusula WHERE:

Las eliminaciones por búsqueda especifican una condición de búsqueda que califica las filas que se van a eliminar. Por ejemplo, WHERE column_name= value.

Las eliminaciones por posición utilizan la cláusula CURRENT OF para especificar un cursor. La operación de eliminación se produce en la posición actual del cursor. Este método puede ser más preciso que una instrucción DELETE por búsqueda que utilice una cláusula WHERE search_condition para calificar las filas que se van a eliminar. Una instrucción DELETE por búsqueda elimina varias filas si la condición de búsqueda no identifica exclusivamente una única fila.

<search_condition>

Especifica las condiciones restrictivas de las filas que se van a eliminar. No hay límite en el número de predicados que se pueden incluir en una condición de búsqueda. Para obtener más información, vea Condiciones de búsqueda (Transact-SQL).

CURRENT OF

Page 11: Cláusula SELECT

Especifica que la instrucción DELETE se ejecutará en la posición actual del cursor especificado.

GLOBAL

Especifica que cursor_name hace referencia a un cursor global.cursor_name

Es el nombre del cursor abierto desde el que se realiza 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

Nombre de una variable de cursor. La variable de cursor debe hacer referencia a un cursor que permita realizar actualizaciones.

OPTION ( <query_hint> [ ,... n] )

Palabras clave que indican que se utilizan sugerencias del optimizador para personalizar el procesamiento de la instrucción por parte del Motor de base de datos. Para obtener más información, vea Sugerencias de consulta (Transact-SQL).

Prácticas recomendadas

Para eliminar todas las filas de una tabla, use TRUNCATE TABLE. TRUNCATE TABLE es más rápido que DELETE y utiliza menos recursos de los registros de transacciones y de sistema.Use la función @@ROWCOUNT para devolver el número de filas eliminadas a la aplicación cliente. Para obtener más información, vea @@ROWCOUNT (Transact-SQL).

Tratamiento de errores

Puede implementar el control de errores de la instrucción DELETE especificando la instrucción en una construcción TRY…CATCH.La instrucción DELETE puede tener un error si infringe un desencadenador o intenta quitar una fila a la que hacen referencia datos de otra tabla con una restricción FOREIGN KEY. Si la instrucción DELETE quita varias filas y cualquiera de las filas eliminadas infringe un desencadenador o restricción, se cancela la instrucción, se devuelve un error y no se elimina ninguna fila.Cuando una instrucción DELETE encuentra un error aritmético (desbordamiento, división entre cero o error de dominio) al evaluar una expresión, el Motor de base de datos trata ese error como si SET ARITHABORT fuese ON. Se cancela el resto del proceso por lotes y se devuelve un mensaje de error.

Interoperabilidad

Page 12: Cláusula SELECT

Es posible utilizar DELETE en el cuerpo de una función definida por el usuario si el objeto que se va a modificar es una variable de tabla.Al eliminar una fila que contiene una columna FILESTREAM, también elimina los archivos del sistema de archivos subyacentes. El recolector de elementos no utilizados de FILESTREAM quita los archivos subyacentes. Para obtener más información, vea Obtener acceso a datos FILESTREAM con Transact-SQL.No se puede especificar la cláusula FROM en una instrucción DELETE 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).

Limitaciones y restricciones

Cuando se usa TOP con DELETE, las filas a las que hace referencia no están organizadas de ninguna manera y la cláusula ORDER BY no se puede especificar directamente en esta instrucción. Si necesita utilizar TOP para eliminar filas por un orden cronológico significativo, debe usar TOP junto con una cláusula ORDER BY en una instrucción de subselección. Vea la sección Ejemplos que aparece más adelante en este tema.TOP no se puede usar en una instrucción DELETE con vistas divididas en particiones.

Comportamiento del bloqueo

De forma predeterminada, una instrucción DELETE siempre adquiere un bloqueo exclusivo (X) en la tabla que modifica y retiene ese bloqueo hasta que se completa la transacción. Al utilizar un bloqueo exclusivo (X), el resto de las transacciones no pueden modificar los datos; las operaciones de lectura solo se pueden realizar si se utiliza la sugerencia NOLOCK o el nivel de aislamiento de lectura no confirmada. Puede especificar sugerencias de tabla para invalidar este comportamiento predeterminado durante la ejecución de la instrucción DELETE especificando otro método de bloqueo, sin embargo se recomienda que solo los desarrolladores y administradores de bases de datos experimentados usen las sugerencias y únicamente como último recurso. Para obtener más información, vea Sugerencias de tabla (Transact-SQL).Cuando se eliminan filas de un montón, Motor de base de datos puede usar bloqueo de filas o páginas para la operación. Como consecuencia, las páginas que han quedado vacías por la operación de eliminación permanecen asignadas al montón. Si no se cancela la asignación de las páginas vacías, otros objetos de la base de datos no pueden volver a utilizar el espacio asociado.Para eliminar las filas de un montón y cancelar la asignación de las páginas, use uno de los métodos siguientes.

Especifique la sugerencia TABLOCK en la instrucción DELETE. Si se utiliza la sugerencia TABLOCK, la operación de eliminación aplica un bloqueo exclusivo a la tabla, en lugar de un bloqueo de fila o de página. Esto permite cancelar la asignación de las páginas. Para obtener más información acerca de la sugerencia TABLOCK, vea Sugerencias de tabla (Transact-SQL).

Se debe utilizar TRUNCATE TABLE si se van a eliminar todas las filas de la tabla.

Page 13: Cláusula SELECT

Cree un índice clúster en el montón antes de eliminar las filas. Puede quitar el índice clúster tras eliminar las filas. Este método requiere más tiempo que los métodos anteriores y utiliza más recursos temporales.

Comportamiento del registro

La instrucción DELETE siempre está registrada totalmente.

Seguridad

PermisosSe requieren permisos DELETE en la tabla de destino. También se requieren los permisos para utilizar SELECT si la instrucción contiene una cláusula WHERE.Los permisos para utilizar DELETE corresponden de forma predeterminada a los miembros del rol fijo de servidor sysadmin, de los roles fijos de base de datosdb_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

Categoría Elementos de sintaxis ofrecidos

Sintaxis básica DELETE

Limitar las filas eliminadas WHERE • FROM • cursor •

Eliminar filas de una tabla remota Servidor vinculado • función de conjunto de filas OPENQUERY • función de conjunto de filas OPENDATASOURCE

Invalidar el comportamiento predeterminado del optimizador de consultas mediante sugerencias

Sugerencias de tabla • sugerencias de consulta

Capturar los resultados de la instrucción DELETE Cláusula OUTPUT

Sintaxis básicaEn los ejemplos de esta sección se muestra la funcionalidad básica de la instrucción DELETE usando la sintaxis mínima requerida.A.Utilizar DELETE sin la cláusula WHEREEn el ejemplo siguiente se eliminan todas las filas de la tabla SalesPersonQuotaHistory porque no se utiliza una cláusula WHERE para limitar el número de filas eliminadas.Transact-SQL

Page 14: Cláusula SELECT

USE AdventureWorks2012;GODELETE FROM Sales.SalesPersonQuotaHistory;GO

Limitar las filas eliminadasEn los ejemplos de esta sección se muestra cómo se limita el número de filas que se van a eliminar.A.Usar la cláusula WHERE para eliminar un conjunto de filasEn el ejemplo siguiente se eliminan todas las filas de la tabla ProductCostHistory en las que el valor de la columna StandardCost es superior a 1000.00.Transact-SQL

USE AdventureWorks2012;GODELETE FROM Production.ProductCostHistoryWHERE StandardCost > 1000.00;GOEn el siguiente ejemplo se muestra una cláusula WHERE más compleja. La cláusula WHERE define dos condiciones que deben cumplirse para determinar las filas que se van a eliminar. El valor de la columna StandardCost debe estar comprendido entre 12.00 y 14.00 y el valor de la columna SellEndDate debe ser NULL. En el ejemplo se imprime también el valor desde la función @@ROWCOUNT para devolver el número de filas eliminadas.Transact-SQL

USE AdventureWorks2012;GODELETE Production.ProductCostHistoryWHERE StandardCost BETWEEN 12.00 AND 14.00 AND EndDate IS NULL;PRINT 'Number of rows deleted is ' + CAST(@@ROWCOUNT as char(3));B.Usar un cursor para determinar la fila que se va a eliminarEn el ejemplo siguiente se elimina una fila única de la tabla EmployeePayHistory mediante un cursor denominado my_cursor. La operación de eliminación solo afecta a la única fila que se captura actualmente del cursor.Transact-SQL

USE AdventureWorks2012;GODECLARE 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;DELETE FROM HumanResources.EmployeePayHistoryWHERE CURRENT OF complex_cursor;

Page 15: Cláusula SELECT

CLOSE complex_cursor;DEALLOCATE complex_cursor;GOC.Usar combinaciones y subconsultas en los datos de una tabla para eliminar filas de otra tablaEn los siguientes ejemplos se muestran dos maneras de eliminar filas de una tabla en función de los datos de otra tabla. En ambos ejemplos, se eliminan las filas de la tabla SalesPersonQuotaHistory basándose en las ventas del año hasta la fecha almacenadas en la tabla SalesPerson. La primera instrucción DELETE muestra la solución de subconsulta compatible con ISO y la segunda instrucción DELETE muestra la extensión de FROM de Transact-SQL para unir las dos tablas.Transact-SQL

-- SQL-2003 Standard subquery

USE AdventureWorks2012;GODELETE FROM Sales.SalesPersonQuotaHistory WHERE BusinessEntityID IN (SELECT BusinessEntityID FROM Sales.SalesPerson WHERE SalesYTD > 2500000.00);GOTransact-SQL

-- Transact-SQL extensionUSE AdventureWorks2012;GODELETE FROM Sales.SalesPersonQuotaHistory FROM Sales.SalesPersonQuotaHistory AS spqhINNER JOIN Sales.SalesPerson AS spON spqh.BusinessEntityID = sp.BusinessEntityIDWHERE sp.SalesYTD > 2500000.00;GOA.Utilizar TOP para limitar el número de filas eliminadasCuando se utiliza una cláusula TOP (n) con DELETE, la operación de eliminación se realiza en una selección aleatoria de n número de filas. En el ejemplo siguiente se eliminan 20 filas aleatorias de la tabla PurchaseOrderDetail cuyas fechas de vencimiento sean anteriores al primero de julio de 2006.Transact-SQL

USE AdventureWorks2012;GODELETE TOP (20) FROM Purchasing.PurchaseOrderDetailWHERE DueDate < '20020701';GOSi necesita utilizar TOP para eliminar filas por un orden cronológico significativo, debe utilizarla junto con ORDER BY en una instrucción de subselección. La siguiente consulta elimina de la tabla PurchaseOrderDetail las 10 filas con las fechas de vencimiento

Page 16: Cláusula SELECT

más antiguas. Para garantizar que solo se eliminen 10 filas, la columna especificada en la instrucción de subselección (PurchaseOrderID) es la clave principal de la tabla. El uso de una columna sin clave en la instrucción de subselección podría causar la eliminación de más de 10 filas si la columna especificada contiene valores duplicados.Transact-SQL

USE AdventureWorks2012;GODELETE FROM Purchasing.PurchaseOrderDetailWHERE PurchaseOrderDetailID IN (SELECT TOP 10 PurchaseOrderDetailID FROM Purchasing.PurchaseOrderDetail ORDER BY DueDate ASC);GO

Eliminar filas de una tabla remotaEn los ejemplos de esta sección se muestra cómo se eliminan filas de una tabla remota mediante un servidor vinculado o una función de conjunto de filas para hacer referencia a la tabla remota. Una tabla remota existe en un servidor o instancia diferente de SQL Server.A.Eliminar datos de una tabla remota usando un servidor vinculadoEn el ejemplo siguiente se eliminan filas de una tabla remota. En el ejemplo se comienza creando un vínculo al origen de datos remoto mediante sp_addlinkedserver.El nombre del servidor vinculado, MyLinkServer, se especifica entonces como parte del nombre de objeto de cuatro partes en el formatoserver.catalog.schema.object.Transact-SQL

USE master;GO-- Create a link to the remote data source. -- Specify a valid server name for @datasrc as 'server_name' or 'server_name\instance_name'.

EXEC sp_addlinkedserver @server = N'MyLinkServer', @srvproduct = N' ', @provider = N'SQLNCLI', @datasrc = N'server_name', @catalog = N'AdventureWorks2012';GOTransact-SQL

-- Specify the remote data source using a four-part name -- in the form linked_server.catalog.schema.object.

DELETE MyLinkServer.AdventureWorks2012.HumanResources.Department WHERE DepartmentID > 16;GO

Page 17: Cláusula SELECT

B.Eliminar datos de una tabla remota con la función OPENQUERYEn el ejemplo siguiente se eliminan filas de una tabla remota especificando la función de conjunto de filas OPENQUERY. En este ejemplo se usa el nombre del servidor vinculado creado en el ejemplo anterior.Transact-SQL

DELETE OPENQUERY (MyLinkServer, 'SELECT Name, GroupName FROM AdventureWorks2012.HumanResources.DepartmentWHERE DepartmentID = 18');GOC.Eliminar datos de una tabla remota con una función OPENDATASOURCEEn el ejemplo siguiente se elimina una fila de una tabla remota especificando 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.Transact-SQL

DELETE FROM OPENDATASOURCE('SQLNCLI', 'Data Source= <server_name>; Integrated Security=SSPI') .AdventureWorks2012.HumanResources.Department WHERE DepartmentID = 17;'

Capturar los resultados de la instrucción DELETEA.Usar DELETE con la cláusula OUTPUTEn el ejemplo siguiente se muestra cómo se guardan los resultados de una instrucción DELETE en una variable de tabla.Transact-SQL

USE AdventureWorks2012;GODELETE Sales.ShoppingCartItemOUTPUT DELETED.* WHERE ShoppingCartID = 20621;

--Verify the rows in the table matching the WHERE clause have been deleted.SELECT COUNT(*) AS [Rows in Table] FROM Sales.ShoppingCartItem WHERE ShoppingCartID = 20621;GOB.Usar OUTPUT con <from_table_name> en una instrucción DELETEEn el ejemplo siguiente se eliminan las filas de la tabla ProductProductPhoto según los criterios de búsqueda definidos en la cláusula FROM de la instrucción DELETE.La cláusula OUTPUT devuelve columnas de la tabla que se elimina (DELETED.ProductID, DELETED.ProductPhotoID) y de la tabla Product. Esta información se utiliza en la cláusula FROM para especificar las filas que se deben eliminar.Transact-SQL

USE AdventureWorks2012;GODECLARE @MyTableVar table (

Page 18: Cláusula SELECT

ProductID int NOT NULL, ProductName nvarchar(50)NOT NULL, ProductModelID int NOT NULL, PhotoID int NOT NULL);

DELETE Production.ProductProductPhotoOUTPUT DELETED.ProductID, p.Name, p.ProductModelID, DELETED.ProductPhotoID INTO @MyTableVarFROM Production.ProductProductPhoto AS phJOIN Production.Product as p ON ph.ProductID = p.ProductID WHERE p.ProductModelID BETWEEN 120 and 130;

--Display the results of the table variable.SELECT ProductID, ProductName, ProductModelID, PhotoID FROM @MyTableVarORDER BY ProductModelID;GO

Page 19: Cláusula SELECT

NSERT (Transact-SQL)SQL Server 2012

Otras versiones

Personas que lo han encontrado útil: 3 de 3 - Valorar este tema

Agrega una o varias filas a una tabla o una vista en SQL Server 2012. Para obtener ejemplos, vea Ejemplos. Convenciones de sintaxis de Transact-SQL

Sintaxis

Transact-SQL

[ WITH <common_table_expression> [ ,...n ] ]INSERT {        [ TOP ( expression ) [ PERCENT ] ]         [ INTO ]         { <object> | rowset_function_limited           [ WITH ( <Table_Hint_Limited> [ ...n ] ) ]        }    {        [ ( column_list ) ]         [ <OUTPUT Clause> ]        { VALUES ( { DEFAULT | NULL | expression } [ ,...n ] ) [ ,...n ]         | derived_table         | execute_statement        | <dml_table_source>        | DEFAULT VALUES         }    }}[;]<object> ::={     [ server_name . database_name . schema_name .       | database_name .[ schema_name ] .       | schema_name .     ]  table_or_view_name

Page 20: Cláusula SELECT

}

<dml_table_source> ::=    SELECT <select_list>    FROM ( <dml_statement_with_output_clause> )       [AS] table_alias [ ( column_alias [ ,...n ] ) ]    [ WHERE <search_condition> ]        [ OPTION ( <query_hint> [ ,...n ] ) ]

<column_definition> ::= column_name <data_type> [ COLLATE collation_name ] [ NULL | NOT NULL ]

<data type> ::= [ type_schema_name . ] type_name [ ( precision [ , scale ] | max ]-- External tool only syntaxINSERT {    [BULK]    [ database_name . [ schema_name ] . | schema_name . ]    [ table_name | view_name ]    ( <column_definition> )    [ WITH (        [ [ , ] CHECK_CONSTRAINTS ]        [ [ , ] FIRE_TRIGGERS ]        [ [ , ] KEEP_NULLS ]        [ [ , ] KILOBYTES_PER_BATCH = kilobytes_per_batch ]        [ [ , ] ROWS_PER_BATCH = rows_per_batch ]        [ [ , ] ORDER ( { column [ ASC | DESC ] } [ ,...n ] ) ]        [ [ , ] TABLOCK ]    ) ]}[; ]

Argumentos

WITH <common_table_expression>

Especifica el conjunto de resultados con nombre temporal, denominado también expresión de tabla común, definido en el ámbito de la instrucción INSERT. El conjunto de resultados se deriva de una instrucción SELECT. Para obtener más información, vea WITH common_table_expression (Transact-SQL).

TOP (expression) [ PERCENT ]

Especifica el número o el porcentaje de filas aleatorias que se van a insertar. expression puede ser un número o un porcentaje de las filas. Para obtener más información, vea TOP (Transact-SQL).

Page 21: Cláusula SELECT

INTO

Es una palabra clave opcional que se puede utilizar entre INSERT y la tabla de destino.

server_name

Es el nombre del servidor vinculado en el que se encuentra la tabla o la vista. server_name puede especificarse como un nombre de servidor vinculado o usando la función OPENDATASOURCE.Cuando server_name se especifica como un servidor vinculado, se requieren database_name y schema_name. Cuando server_name se especifica con OPENDATASOURCE, database_name y schema_name pueden no aplicarse a todos los orígenes de datos y estar sujetos a las capacidades del proveedor OLE DB que tiene acceso al objeto remoto.

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 la vista que va a recibir los datos.Se puede utilizar una variable de tabla, en su ámbito, como origen de tabla en una instrucción INSERT.La vista a la que hace referencia table_or_view_name debe poder actualizarse y debe hacer referencia exactamente a una tabla base en la cláusula FROM de la vista. Por ejemplo, la instrucción INSERT de una vista de varias tablas debe utilizar una column_list que solamente haga referencia a columnas de una tabla base. Para obtener más información acerca de las vistas que se pueden actualizar, vea CREATE VIEW (Transact-SQL).

rowset_function_limited

Especifica la función OPENQUERY u OPENROWSET. El uso de estas funciones está sujeto a las capacidades del proveedor OLE DB que tiene acceso al objeto remoto.

WITH ( <table_hint_limited> [... n ] )

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.No se permiten READPAST, NOLOCK ni READUNCOMMITTED. Para obtener más información acerca de las sugerencias de tabla, vea Sugerencias de tabla (Transact-SQL).

 Importante

La posibilidad de especificar las sugerencias HOLDLOCK, SERIALIZABLE, READCOMMITTED, REPEATABLEREAD o UPDLOCK en tablas que son destinos de instrucciones INSERT se quitará en una versión futura de SQL Server.

Page 22: Cláusula SELECT

influyen en el rendimiento de las instrucciones INSERT. Evite el uso de dichas sugerencias en los nuevos trabajos de desarrollo y piense en modificar las aplicaciones que las utilizan actualmente.

Especificar la sugerencia TABLOCK en una tabla que es el destino de una instrucción INSERT tiene el mismo efecto que especificar la sugerencia TABLOCKX. Se realiza un bloqueo exclusivo en la tabla.

(column_list)

Es una lista de una o más columnas donde se van a insertar los datos. column_list se debe incluir entre paréntesis y delimitar con comas.Si la columna no se incluye en column_list, Motor de base de datos debe ser capaz de proporcionar un valor basado en la definición de la columna; de lo contrario, no se puede cargar la fila. Motor de base de datos proporciona automáticamente un valor para la columna si esta:

Tiene una propiedad IDENTITY. Se usa el valor de identidad incremental siguiente.

Tiene un valor predeterminado. Se usa el valor predeterminado de la columna.

Tiene un tipo de datos timestamp. Se utiliza el valor actual de marca de tiempo.

Admite valores NULL. Se usa un valor NULL. Es una columna calculada. Se utiliza el valor calculado.

Se debe usar column_list al insertar valores explícitos en una columna de identidad. La opción SET IDENTITY_INSERT debe ser ON para la tabla.

Cláusula OUTPUT

Devuelve las filas insertadas como parte de la operación de inserción. Los resultados se pueden devolver a la aplicación de procesamiento o insertarse en una tabla o variable de tabla para su nuevo procesamiento.La cláusula OUTPUT no se admite en las instrucciones DML que hacen referencia a vistas locales con particiones, vistas distribuidas con particiones, tablas remotas o instrucciones INSERT que contengan una execute_statement. La cláusula OUTPUT INTO no se admite en instrucciones INSERT que contengan una cláusula <dml_table_source>.

VALUES

Presenta la lista o listas de valores de datos que se van a insertar. Debe haber un valor de datos por cada columna en column_list, si se especifica, o en la tabla. La lista de valores debe ir entre paréntesis.Si los valores de la lista Value no están en el mismo orden que las columnas de la tabla o no contienen un valor para cada columna de la tabla, se debe usarcolumn_list para especificar de forma explícita la columna que almacenará cada valor de entrada.Puede utilizar el constructor de filas de Transact-SQL (que también se denomina constructor con valores de tabla) para especificar varias filas en una única instrucción INSERT. El constructor de filas se compone de una única cláusula VALUES con varias listas de valores escritos entre paréntesis y separados por

Page 23: Cláusula SELECT

una coma. Para obtener más información, vea Constructor con valores de tabla (Transact-SQL).

DEFAULT

Hace que Motor de base de datos cargue el valor predeterminado definido para una columna. Si no existe ningún valor predeterminado para la columna y esta admite valores NULL, se inserta NULL. Para una columna definida con el tipo de datos timestamp, se inserta el siguiente valor de marca de tiempo.DEFAULT no es un valor válido para una columna de identidad.

expression

Es una constante, variable o expresión. La expresión no puede contener una instrucción EXECUTE.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 en la página de códigos correspondiente a la intercalación predeterminada de la base de datos o la columna. Los caracteres que no se encuentren en esta página de códigos se perderán.

derived_table

Es cualquier instrucción SELECT válida que devuelva filas con los datos que se van a cargar en la tabla. La instrucción SELECT no puede contener una expresión de tabla común (CTE).

execute_statement

Es cualquier instrucción EXECUTE válida que devuelva datos con instrucciones SELECT o READTEXT. Para obtener más información, vea EXECUTE (Transact-SQL).Las opciones de RESULT SETS de la instrucción EXECUTE no se pueden especificar en una instrucción INSERT…EXEC.Si se usa execute_statement con INSERT, cada conjunto de resultados debe ser compatible con las columnas de la tabla o de column_list.execute_statement se puede utilizar para ejecutar procedimientos almacenados en el mismo servidor o en un servidor remoto. Se ejecuta el procedimiento en el servidor remoto, se devuelven los conjuntos de resultados al servidor local y se cargan en la tabla del servidor local. En una transacción distribuida,execute_statement no se puede emitir en un servidor vinculado de bucle invertido cuando la conexión tiene varios conjuntos de resultados activos múltiples (MARS) habilitados.If execute_statement devuelve datos con la instrucción READTEXT, cada instrucción READTEXT puede devolver un máximo de 1 MB (1024 KB) de datos.execute_statement también se puede usar con procedimientos extendidos. execute_statement inserta los datos devueltos por el subproceso principal del procedimiento extendido; no obstante, los resultados de los subprocesos distintos del subproceso principal no se insertan.No puede especificar un parámetro con valores de tabla como el destino de una instrucción INSERT EXEC; sin embargo, se puede especificar como un origen en la cadena o procedimiento almacenado INSERT EXEC. Para obtener más

Page 24: Cláusula SELECT

información, vea Usar parámetros con valores de tabla (motor de base de datos).

<dml_table_source>

Especifica que las filas insertadas en la tabla de destino son las que ha devuelto la cláusula OUTPUT de una instrucción INSERT, UPDATE, DELETE o MERGE, filtradas opcionalmente por una cláusula WHERE. Si se especifica <dml_table_source>, el destino de la instrucción INSERT externa debe cumplir las restricciones siguientes:

Debe ser una tabla base, no una vista. No puede ser una tabla remota. No puede tener definido ningún desencadenador. No puede participar en ninguna relación clave principal-clave externa. No puede participar en la replicación de mezcla ni en las suscripciones

actualizables para la replicación transaccional.El nivel de compatibilidad de la base de datos debe estar establecido en 100 o superior. Para obtener más información, vea OUTPUT (cláusula de Transact-SQL).

<select_list>

Es una lista separada por comas que especifica las columnas devueltas por la cláusula OUTPUT que se tienen que insertar. Las columnas de <select_list> deben ser compatibles con las columnas en las que se insertan los valores. <select_list> no puede hacer referencia a funciones de agregado ni a TEXTPTR.

 Nota

Las variables enumeradas en la lista SELECT hacen referencia a sus valores originales, sin tener en cuenta los cambios realizados en ellos en <dml_statement_with_output_clause>.

<dml_statement_with_output_clause>

Es una instrucción INSERT, UPDATE, DELETE o MERGE válida que devuelve las filas afectadas en una cláusula OUTPUT. La instrucción no puede contener una cláusula WITH y no puede tener como destino tablas remotas o vistas con particiones. Si se especifica UPDATE o DELETE, no puede ser una instrucción UPDATE o DELETE basada en cursores. No se puede hacer referencia a las filas de origen como instrucciones DML anidadas.

WHERE <search_condition>

Es cualquier cláusula WHERE que contiene una condición <search_condition> válida que filtra las filas devueltas por <dml_statement_with_output_clause>. Para obtener más información, vea Condiciones de búsqueda (Transact-SQL). Cuando se utiliza en este contexto, <search_condition> no puede contener subconsultas, funciones escalares definidas por el usuario que realicen acceso a datos, funciones de agregado, TEXTPTR ni predicados de búsqueda de texto completo.

DEFAULT VALUES

Page 25: Cláusula SELECT

Hace que la nueva fila contenga los valores predeterminados definidos para cada columna.

BULK

La usan las herramientas externas para cargar un flujo de datos binarios. Esta opción no está diseñada para usarse con herramientas tales como SQL Server Management Studio, SQLCMD, OSQL ni interfaces de programación de aplicaciones de acceso a datos como SQL Server Native Client.

FIRE_TRIGGERS

Especifica que se ejecutarán todos los desencadenadores de inserción definidos en la tabla de destino durante la operación de carga de flujos de datos binarios. Para obtener más información, vea BULK INSERT (Transact-SQL).

CHECK_CONSTRAINTS

Especifica que deben comprobarse todas las restricciones de la tabla o vista de destino durante la operación de carga de flujos de datos binarios. Para obtener más información, vea BULK INSERT (Transact-SQL).

KEEPNULLS

Especifica que las columnas vacías deben conservar un valor nulo durante la operación de carga de flujos de datos binarios. Para obtener más información, vea Mantener valores NULL o usar valores predeterminados durante la importación masiva (SQL Server).

KILOBYTES_PER_BATCH = kilobytes_per_batch

Especifica el número aproximado de kilobytes (KB) de datos por lote como kilobytes_per_batch. Para obtener más información, vea BULK INSERT (Transact-SQL).

ROWS_PER_BATCH =rows_per_batch

Indica el número aproximado de filas de datos del flujo de datos binarios. Para obtener más información, vea BULK INSERT (Transact-SQL).Nota   Se produce un error de sintaxis si no se proporciona una lista de columnas.

Prácticas recomendadas

Utilice la función @@ROWCOUNT para devolver el número de filas insertado a la aplicación cliente. Para obtener más información, vea @@ROWCOUNT (Transact-SQL).

Prácticas recomendadas para la importación masiva de datosUsar INSERT INTO…SELECT para realizar una importación masiva de datos con registro mínimoPuede usar INSERT INTO <target_table> SELECT <columns> FROM <source_table> para transferir eficazmente un gran número de filas de una tabla, como una tabla de ensayo, a otra tabla con registro mínimo. El registro mínimo puede mejorar el rendimiento de la instrucción y reducir la posibilidad de que la operación rellene el espacio del registro de transacciones disponible durante la transacción.

Page 26: Cláusula SELECT

El registro mínimo para esta instrucción tiene los requisitos siguientes: El modelo de recuperación de la base de datos está establecido en registro

simple o masivo. La tabla de destino es un montón vacío o no vacío. La tabla de destino no se usa en la replicación. La sugerencia TABLOCK se especifica para la tabla de destino.

Las filas que se insertan en un montón como el resultado de una acción de inserción en una instrucción MERGE también se pueden registrar con un nivel mínimo.A diferencia de la instrucción BULK INSERT, que contiene un bloqueo Bulk Update menos restrictivo, INSERT INTO…SELECT con la sugerencia TABLOCK retiene un bloqueo exclusivo (X) en la tabla. Esto significa que no se pueden insertar filas mediante operaciones de inserción en paralelo.Usar OPENROWSET y BULK para datos de importación masivaLa función OPENROWSET puede aceptar las siguientes sugerencias de tabla, que proporcionan optimizaciones de carga masiva con la instrucción INSERT:

La sugerencia TABLOCK puede reducir al mínimo el número de registros para la operación de inserción. El modelo de recuperación de la base de datos debe establecerse en registro simple o masivo, y la tabla de destino no se puede utilizar en la replicación. Para obtener más información, vea Requisitos previos para el registro mínimo durante la importación masiva.

La sugerencia IGNORE_CONSTRAINTS puede deshabilitar temporalmente la comprobación de restricciones FOREIGN KEY y CHECK.

La sugerencia IGNORE_TRIGGERS puede deshabilitar temporalmente la ejecución de desencadenadores.

La sugerencia KEEPDEFAULTS permite la inserción del valor predeterminado de la columna de una tabla, si existe, en lugar de NULL, cuando falta el valor del registro de datos de esa columna.

La sugerencia KEEPIDENTITY permite que se usen los valores de identidad en el archivo de datos importado para la columna de identidad en la tabla de destino.

Estas optimizaciones son similares a las que están disponibles con el comando BULK INSERT. Para obtener más información, vea Sugerencias de tabla (Transact-SQL).

Tipos de datos

Al insertar filas, considere el comportamiento de los tipos de datos siguientes: Si se va a cargar un valor en columnas con un tipo de

datos char, varchar o varbinary, el relleno o el truncamiento de los espacios en blanco finales (espacios para char y varchar, y ceros para varbinary) se determinan mediante el valor de la opción SET ANSI_PADDING definida para la columna al crear la tabla. Para obtener más información, vea SET ANSI_PADDING (Transact-SQL).En la siguiente tabla se muestra la operación predeterminada cuando SET ANSI_PADDING es OFF.

Tipo de datos

Operación predeterminada

Page 27: Cláusula SELECT

char Rellena el valor con espacios hasta el ancho definido de la columna.

varchar Quita los espacios finales hasta el último carácter distinto de espacio o hasta un carácter de espacio único para las cadenas compuestas solamente de espacios.

varbinary Quita los ceros finales.

Si se carga una cadena vacía (' ') en una columna con un tipo de datos varchar o text, la operación predeterminada consiste en cargar una cadena de longitud cero.

Al insertar un valor NULL en una columna text o image, no se crea un puntero de texto válido ni se asigna previamente una página de texto de 8 KB.

En las columnas creadas con el tipo de datos uniqueidentifier se almacenan valores binarios de 16 bytes con formato especial. A diferencia de las columnas de identidad, Motor de base de datos no genera automáticamente valores de columnas con el tipo de datos uniqueidentifier. Durante una operación de inserción, se pueden usar variables con un tipo de datos uniqueidentifier y constantes de cadena con el formato xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (36 caracteres incluidos los guiones, donde x es un dígito hexadecimal de los intervalos 0-9 o a-f) para las columnas uniqueidentifier. Por ejemplo, 6F9619FF-8B86-D011-B42D-00C04FC964FF es un valor válido para una columna o variable uniqueidentifier. Utilice la función NEWID() para obtener un identificador único global (GUID).

Insertar valores en columnas de tipo definido por el usuarioPuede insertar valores en columnas de tipo definido por el usuario si:

Proporciona un valor del tipo definido por el usuario. Suministra 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 siguiente ejemplo se muestra cómo insertar un valor en una columna de tipo definido por el usuario Point mediante la conversión explícita a partir de una cadena.

INSERT INTO Cities (Location) VALUES ( CONVERT(Point, '12.3:46.2') );

También se puede suministrar un valor binario sin realizar ninguna conversión explícita, dado que todos los tipos definidos por el usuario se pueden convertir implícitamente a partir de este valor binario.

Llama a una función definida por el usuario que devuelve un valor del tipo definido por el usuario. En el siguiente ejemplo se utiliza una funciónCreateNewPoint() definida por el usuario para crear un valor nuevo del tipo Point definido por el usuario e insertar el valor en la tabla Cities.

INSERT INTO Cities (Location) VALUES ( dbo.CreateNewPoint(x, y) );

Tratamiento de errores

Page 28: Cláusula SELECT

Puede implementar el tratamiento de errores para la instrucción INSERT especificando la instrucción en una construcción TRY…CATCH.Si una instrucción INSERT infringe una restricción o una regla, o si contiene un valor incompatible con el tipo de datos de la columna, la instrucción no se puede ejecutar y se recibe un mensaje de error.Si INSERT carga varias filas con SELECT o EXECUTE, cualquier infracción de una regla o restricción que se produzca en los valores que se cargan provoca que se detenga la instrucción y que no se carguen filas.Cuando una instrucción INSERT detecta un error aritmético (desbordamiento, división entre cero o error de dominio) al evaluar una expresión, Motor de base de datos trata dichos errores como si SET ARITHABORT estuviera establecido en ON. El lote se detiene y se devuelve un mensaje de error. Al evaluar una expresión con SET ARITHABORT y SET ANSI_WARNINGS en OFF, si una instrucción INSERT, DELETE o UPDATE encuentra un error aritmético, desbordamiento, división entre cero o error de dominio, SQL Server inserta o actualiza un valor NULL. Si la columna de destino no acepta valores NULL, no se puede efectuar la acción de inserción o actualización y el usuario recibe un error.

Interoperabilidad

Cuando se define un desencadenador INSTEAD OF en las acciones INSERT en una tabla o vista, se ejecuta el desencadenador en lugar de la instrucción INSERT. Para obtener más información acerca de los desencadenadores INSTEAD OF, vea CREATE TRIGGER (Transact-SQL).

Limitaciones y restricciones

Cuando se insertan valores en tablas remotas y no se especifican todos los valores de todas las columnas, debe identificar las columnas en las que se deben insertar los valores especificados.Cuando se utiliza TOP con INSERT las filas a las que hace referencia no están organizadas de ninguna manera y la cláusula ORDER BY no se puede especificar directamente en esta instrucción. Si necesita usar TOP para insertar las filas en un orden cronológico significativo, debe utilizar TOP junto con una cláusula ORDER BY que se especifica en una instrucción de subselección. Vea la sección Ejemplos que aparece más adelante en este tema.

Comportamiento del registro

La instrucción INSERT siempre se registra completamente excepto cuando se usa la función OPENROWSET con la palabra clave BULK o cuando se usa INSERT INTO <target_table> SELECT <columns> FROM <source_table>. Estas operaciones pueden ser registradas mínimamente. Para obtener más información, vea la sección "Prácticas recomendadas para la carga masiva de datos" anteriormente en este tema.

Seguridad

Page 29: Cláusula SELECT

Durante una conexión de servidores vinculados, el servidor de envío proporciona un nombre de inicio de sesión y una contraseña para conectarse en su nombre al servidor de recepción. Para que esta conexión funcione, debe crear una asignación de inicio de sesión entre los servidores vinculados utilizandosp_addlinkedsrvlogin.Cuando utilice OPENROWSET (BULK…), es importante que entienda el modo en el que SQL Server controla la suplantación. Para obtener más información, vea "Consideraciones de seguridad" en Importar de forma masiva datos mediante BULK INSERT u OPENROWSET(BULK...) (SQL Server).

PermisosEl permiso INSERT es obligatorio en la tabla de destino.Los permisos para INSERT se adjudican de forma predeterminada a los miembros del rol fijo de servidor sysadmin, a los roles fijos de base de datos db_owner ydb_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.Para ejecutar INSERT con la opción BULK de la función OPENROWSET, debe ser miembro del rol fijo de servidor sysadmin o bulkadmin.

Ejemplos

Categoría Elementos de sintaxis ofrecidos

Sintaxis básica INSERT • constructor con valores de tabla

Tratar los valores de columna IDENTITY • NEWID • valores predeterminados • tipos definidos por el usuario

Insertar datos de otras tablas INSERT…SELECT • INSERT…EXECUTE • WITH expresión de tabla común • TOP • OFFSET FETCH

Especificar objetos de destino que no sean tablas estándar Vistas • variables de tabla

Insertar filas en una tabla remota Servidor vinculado • función de conjunto de filas OPENQUERY • función de conjunto de filas OPENDATASOURCE

Cargar datos de forma masiva de tablas o archivos de datos INSERT…SELECT • función OPENROWSET

Invalidar el comportamiento predeterminado del optimizador de consultas mediante sugerencias

Sugerencias de tabla

Capturar los resultados de la instrucción INSERT Cláusula OUTPUT

Page 30: Cláusula SELECT

Sintaxis básicaLos ejemplos de esta sección demuestran la funcionalidad básica de la instrucción INSERT usando la sintaxis mínima requerida.A.Insertar una sola fila de datosEn el siguiente ejemplo se inserta una fila en la tabla Production.UnitMeasure. Las columnas de esta tabla son UnitMeasureCode, Name y ModifiedDate. Dado que los valores para todas las columnas se suministran e incluyen en el mismo orden que las columnas de la tabla, no es necesario especificar los nombres de columna en la lista de columnas.Transact-SQL

USE AdventureWorks2012;GOINSERT INTO Production.UnitMeasureVALUES (N'FT', N'Feet', '20080414');GOB.Insertar varias filas de datosEn el siguiente ejemplo se usa el constructor de valores de tabla para insertar tres filas en la tabla Production.UnitMeasure en una instrucción INSERT. Dado que los valores para todas las columnas se suministran e incluyen en el mismo orden que las columnas de la tabla, no es necesario especificar los nombres de columna en la lista de columnas.Transact-SQL

USE AdventureWorks2012;GOINSERT INTO Production.UnitMeasureVALUES (N'FT2', N'Square Feet ', '20080923'), (N'Y', N'Yards', '20080923'), (N'Y3', N'Cubic Yards', '20080923');GOC.Insertar datos que no están en el mismo orden que las columnas de la tablaEn el siguiente ejemplo se utiliza una lista de columnas para especificar de forma explícita los valores insertados en cada columna. El orden de las columnas de la tabla Production.UnitMeasure es UnitMeasureCode, Name, ModifiedDate; no obstante, las columnas no se incluyen en dicho orden en column_list.Transact-SQL

USE AdventureWorks2012;GOINSERT INTO Production.UnitMeasure (Name, UnitMeasureCode, ModifiedDate)VALUES (N'Square Yards', N'Y2', GETDATE());GO

Tratar los valores de columnaLos ejemplos de esta sección demuestran métodos para insertar valores en columnas que se definen con una propiedad IDENTITY, un valor DEFAULT o se definen con tipos de datos como uniqueidentifer o columnas de un tipo definido por el usuario.

Page 31: Cláusula SELECT

A.Insertar datos en una tabla con columnas que tienen valores predeterminadosEn el ejemplo siguiente se muestra la inserción de filas en una tabla con columnas que generan automáticamente un valor o tienen un valor predeterminado.Column_1 es una columna calculada que genera automáticamente un valor concatenando una cadena con el valor insertado en column_2. Column_2 se define con una restricción predeterminada. Si no se especifica un valor para esta columna, se usará el valor predeterminado. Column_3 se define con el tipo de datosrowversion, que genera automáticamente un número binario único que se incrementa. Column_4 no genera automáticamente ningún valor. Cuando no se especifica un valor para esta columna, se inserta NULL. La instrucción INSERT inserta filas que contienen valores para algunas de las columnas, pero no para todas. En la última instrucción INSERT, no se especifica ninguna columna y solamente se insertan los valores predeterminados con la cláusula DEFAULT VALUES.Transact-SQL

USE AdventureWorks2012;GOIF OBJECT_ID ('dbo.T1', 'U') IS NOT NULL DROP TABLE dbo.T1;GOCREATE TABLE dbo.T1 ( column_1 AS 'Computed column ' + column_2, column_2 varchar(30) CONSTRAINT default_name DEFAULT ('my column default'), column_3 rowversion, column_4 varchar(40) NULL);GOINSERT INTO dbo.T1 (column_4) VALUES ('Explicit value');INSERT INTO dbo.T1 (column_2, column_4) VALUES ('Explicit value', 'Explicit value');INSERT INTO dbo.T1 (column_2) VALUES ('Explicit value');INSERT INTO T1 DEFAULT VALUES; GOSELECT column_1, column_2, column_3, column_4FROM dbo.T1;GOB.Insertar datos en una tabla con una columna de identidadEn el siguiente ejemplo se muestran los distintos métodos para insertar datos en una columna de identidad. Las dos primeras instrucciones INSERT permiten generar valores de identidad para las filas nuevas. La tercera instrucción INSERT invalida la propiedad IDENTITY de la columna con la instrucción SET IDENTITY_INSERT e inserta un valor explícito en la columna de identidad.Transact-SQL

USE AdventureWorks2012;

Page 32: Cláusula SELECT

GOIF OBJECT_ID ('dbo.T1', 'U') IS NOT NULL DROP TABLE dbo.T1;GOCREATE TABLE dbo.T1 ( column_1 int IDENTITY, column_2 VARCHAR(30));GOINSERT T1 VALUES ('Row #1');INSERT T1 (column_2) VALUES ('Row #2');GOSET IDENTITY_INSERT T1 ON;GOINSERT INTO T1 (column_1,column_2) VALUES (-99, 'Explicit identity value');GOSELECT column_1, column_2FROM T1;GOC.Insertar datos en una columna uniqueidentifier mediante NEWID()En el siguiente ejemplo se utiliza la función NEWID() para obtener un GUID para column_2. A diferencia de las columnas de identidad, Motor de base de datos no genera automáticamente valores de columnas con el tipo de datos uniqueidentifier, según se muestra en la segunda instrucción INSERT.Transact-SQL

USE AdventureWorks2012;GOIF OBJECT_ID ('dbo.T1', 'U') IS NOT NULL DROP TABLE dbo.T1;GOCREATE TABLE dbo.T1 ( column_1 int IDENTITY, column_2 uniqueidentifier,);GOINSERT INTO dbo.T1 (column_2) VALUES (NEWID());INSERT INTO T1 DEFAULT VALUES; GOSELECT column_1, column_2FROM dbo.T1;GOD.Insertar datos en columnas de tipo definido por el usuarioLas siguientes instrucciones de Transact-SQL insertan tres filas en la columna PointValue de la tabla Points. Esta columna usa un tipo definido por el usuario CLR(UDT). El tipo de datos Point está compuesto por valores enteros X e Y que se exponen como propiedades del UDT. Debe utilizar las funciones CAST o CONVERT para convertir los valores X e Y separados por comas al tipo Point. Las dos primeras instrucciones utilizan la función CONVERT para convertir un valor de cadena al

Page 33: Cláusula SELECT

tipo Point y la tercera utiliza la función CAST. Para obtener más información, vea Manipular datos UDT.INSERT INTO dbo.Points (PointValue) VALUES (CONVERT(Point, '3,4'));INSERT INTO dbo.Points (PointValue) VALUES (CONVERT(Point, '1,5'));INSERT INTO dbo.Points (PointValue) VALUES (CAST ('1,99' AS Point));

Insertar datos de otras tablasLos ejemplos de esta sección demuestran métodos para insertar filas de una tabla en otra.A.Usar las opciones SELECT y EXECUTE para insertar datos de otras tablasEn el siguiente ejemplo se muestra cómo insertar datos de una tabla en otra mediante INSERT…SELECT o INSERT…EXECUTE. Cada uno se basa en una instrucción SELECT con varias tablas que contiene una expresión y un valor literal en la lista de columnas.La primera instrucción INSERT usa una instrucción SELECT para derivar los datos de las tablas de origen (Employee, SalesPerson y Person) y almacenar el conjunto de resultados en la tabla EmployeeSales . La segunda instrucción INSERT usa la cláusula EXECUTE para llamar a un procedimiento almacenado que contiene la instrucción SELECT y la tercera instrucción INSERT usa la cláusula EXECUTE para hacer referencia a la instrucción SELECT como una cadena literal.Transact-SQL

USE AdventureWorks2012;GOIF OBJECT_ID ('dbo.EmployeeSales', 'U') IS NOT NULL DROP TABLE dbo.EmployeeSales;GOIF OBJECT_ID ('dbo.uspGetEmployeeSales', 'P') IS NOT NULL DROP PROCEDURE uspGetEmployeeSales;GOCREATE TABLE dbo.EmployeeSales( DataSource varchar(20) NOT NULL, BusinessEntityID varchar(11) NOT NULL, LastName varchar(40) NOT NULL, SalesDollars money NOT NULL);GOCREATE PROCEDURE dbo.uspGetEmployeeSales AS SET NOCOUNT ON; SELECT 'PROCEDURE', sp.BusinessEntityID, c.LastName, sp.SalesYTD FROM Sales.SalesPerson AS sp INNER JOIN Person.Person AS c ON sp.BusinessEntityID = c.BusinessEntityID WHERE sp.BusinessEntityID LIKE '2%' ORDER BY sp.BusinessEntityID, c.LastName;GO--INSERT...SELECT exampleINSERT INTO dbo.EmployeeSales

Page 34: Cláusula SELECT

SELECT 'SELECT', sp.BusinessEntityID, c.LastName, sp.SalesYTD FROM Sales.SalesPerson AS sp INNER JOIN Person.Person AS c ON sp.BusinessEntityID = c.BusinessEntityID WHERE sp.BusinessEntityID LIKE '2%' ORDER BY sp.BusinessEntityID, c.LastName;GO--INSERT...EXECUTE procedure exampleINSERT INTO dbo.EmployeeSales EXECUTE dbo.uspGetEmployeeSales;GO--INSERT...EXECUTE('string') exampleINSERT INTO dbo.EmployeeSales EXECUTE ('SELECT ''EXEC STRING'', sp.BusinessEntityID, c.LastName, sp.SalesYTD FROM Sales.SalesPerson AS sp INNER JOIN Person.Person AS c ON sp.BusinessEntityID = c.BusinessEntityID WHERE sp.BusinessEntityID LIKE ''2%'' ORDER BY sp.BusinessEntityID, c.LastName');GO--Show results.SELECT DataSource,BusinessEntityID,LastName,SalesDollarsFROM dbo.EmployeeSales;GOB.Usar la expresión de tabla común WITH para definir los datos insertadosEn el siguiente ejemplo se crea la tabla NewEmployee. Una expresión de tabla común (EmployeeTemp) define las filas de una o varias tablas que se van a insertar en la tabla NewEmployee. La instrucción INSERT hace referencia a las columnas de la expresión de tabla común.Transact-SQL

USE AdventureWorks2012;GOIF OBJECT_ID (N'HumanResources.NewEmployee', N'U') IS NOT NULL DROP TABLE HumanResources.NewEmployee;GOCREATE TABLE HumanResources.NewEmployee( EmployeeID int NOT NULL, LastName nvarchar(50) NOT NULL, FirstName nvarchar(50) NOT NULL, PhoneNumber Phone NULL, AddressLine1 nvarchar(60) NOT NULL, City nvarchar(30) NOT NULL, State nchar(3) NOT NULL,

Page 35: Cláusula SELECT

PostalCode nvarchar(15) NOT NULL, CurrentFlag Flag);GOWITH EmployeeTemp (EmpID, LastName, FirstName, Phone, Address, City, StateProvince, PostalCode, CurrentFlag)AS (SELECT e.BusinessEntityID, c.LastName, c.FirstName, pp.PhoneNumber, a.AddressLine1, a.City, sp.StateProvinceCode, a.PostalCode, e.CurrentFlag FROM HumanResources.Employee e INNER JOIN Person.BusinessEntityAddress AS bea ON e.BusinessEntityID = bea.BusinessEntityID INNER JOIN Person.Address AS a ON bea.AddressID = a.AddressID INNER JOIN Person.PersonPhone AS pp ON e.BusinessEntityID = pp.BusinessEntityID INNER JOIN Person.StateProvince AS sp ON a.StateProvinceID = sp.StateProvinceID INNER JOIN Person.Person as c ON e.BusinessEntityID = c.BusinessEntityID )INSERT INTO HumanResources.NewEmployee SELECT EmpID, LastName, FirstName, Phone, Address, City, StateProvince, PostalCode, CurrentFlag FROM EmployeeTemp;GOC.Usar TOP para limitar los datos insertados de la tabla de origenEn el siguiente ejemplo se crea la tabla EmployeeSales y se insertan el nombre y los datos de ventas del año hasta la fecha para los primeros 5 empleados aleatorios de la tabla HumanResources.Employee. La instrucción INSERT elige cualquiera de las 5 filas devueltas por la instrucción SELECT. La cláusula OUTPUT muestra las filas que se insertan en la tabla EmployeeSales. Observe que la cláusula ORDER BY de la instrucción SELECT no se utiliza para determinar los primeros 5 empleados.Transact-SQL

USE AdventureWorks2012 ;GOIF OBJECT_ID ('dbo.EmployeeSales', 'U') IS NOT NULL DROP TABLE dbo.EmployeeSales;GOCREATE TABLE dbo.EmployeeSales( EmployeeID nvarchar(11) NOT NULL, LastName nvarchar(20) NOT NULL, FirstName nvarchar(20) NOT NULL, YearlySales money NOT NULL );GOINSERT TOP(5)INTO dbo.EmployeeSales

Page 36: Cláusula SELECT

OUTPUT inserted.EmployeeID, inserted.FirstName, inserted.LastName, inserted.YearlySales SELECT sp.BusinessEntityID, c.LastName, c.FirstName, sp.SalesYTD FROM Sales.SalesPerson AS sp INNER JOIN Person.Person AS c ON sp.BusinessEntityID = c.BusinessEntityID WHERE sp.SalesYTD > 250000.00 ORDER BY sp.SalesYTD DESC;Si necesita usar TOP para insertar las filas en un orden cronológico significativo, debe utilizar TOP junto con ORDER BY en una instrucción de subselección, tal y como se muestra en el siguiente ejemplo. La cláusula OUTPUT muestra las filas que se insertan en la tabla EmployeeSales. Observe que los primeros 5 empleados se insertan ahora según los resultados de la cláusula ORDER BY en lugar de las filas aleatorias.Transact-SQL

INSERT INTO dbo.EmployeeSales OUTPUT inserted.EmployeeID, inserted.FirstName, inserted.LastName, inserted.YearlySales SELECT TOP (5) sp.BusinessEntityID, c.LastName, c.FirstName, sp.SalesYTD FROM Sales.SalesPerson AS sp INNER JOIN Person.Person AS c ON sp.BusinessEntityID = c.BusinessEntityID WHERE sp.SalesYTD > 250000.00 ORDER BY sp.SalesYTD DESC;

Especificar objetos de destino que no sean tablas estándarEn los ejemplos de esta sección se muestra cómo insertar filas especificando una variable de tabla o vista.A.Insertar datos especificando una vistaEn el siguiente ejemplo se especifica un nombre de vista como objeto de destino; sin embargo, la fila nueva se inserta en la tabla base subyacente. El orden de los valores de la instrucción INSERT debe coincidir con el orden de las columnas de la vista. Para obtener más información, vea Modificar datos mediante una vista.Transact-SQL

USE AdventureWorks2012;GOIF OBJECT_ID ('dbo.T1', 'U') IS NOT NULL DROP TABLE dbo.T1;GOIF OBJECT_ID ('dbo.V1', 'V') IS NOT NULL DROP VIEW dbo.V1;GOCREATE TABLE T1 ( column_1 int, column_2 varchar(30));GOCREATE VIEW V1 AS SELECT column_2, column_1 FROM T1;GOINSERT INTO V1

Page 37: Cláusula SELECT

VALUES ('Row 1',1);GOSELECT column_1, column_2 FROM T1;GOSELECT column_1, column_2FROM V1;GOB.Insertar datos en una variable de tablaEn el siguiente ejemplo se especifica una variable de tabla como el objeto de destino.Transact-SQL

USE AdventureWorks2012;GO-- Create the table variable.DECLARE @MyTableVar table( LocationID int NOT NULL, CostRate smallmoney NOT NULL, NewCostRate AS CostRate * 1.5, ModifiedDate datetime);

-- Insert values into the table variable.INSERT INTO @MyTableVar (LocationID, CostRate, ModifiedDate) SELECT LocationID, CostRate, GETDATE() FROM Production.Location WHERE CostRate > 0;

-- View the table variable result set.SELECT * FROM @MyTableVar;GO

Insertar filas en una tabla remotaLos ejemplos de esta sección demuestran cómo insertar filas en una tabla de destino remota mediante un servidor vinculado o una función de conjunto de filas para hacer referencia a la tabla remota.A.Insertar datos en una tabla remota mediante un servidor vinculadoEl ejemplo siguiente inserta filas en una tabla remota. En el ejemplo se comienza creando un vínculo al origen de datos remoto mediante sp_addlinkedserver. El nombre del servidor vinculado, MyLinkServer, se especifica entonces como parte del nombre de objeto de cuatro partes en el formato server.catalog.schema.object.Transact-SQL

USE master;GO-- Create a link to the remote data source. -- Specify a valid server name for @datasrc as 'server_name' or 'server_name\instance_name'.

EXEC sp_addlinkedserver @server = N'MyLinkServer', @srvproduct = N' ', @provider = N'SQLNCLI', @datasrc = N'server_name',

Page 38: Cláusula SELECT

@catalog = N'AdventureWorks2012';GOTransact-SQL

USE AdventureWorks2012;GO-- Specify the remote data source in the FROM clause using a four-part name -- in the form linked_server.catalog.schema.object.

INSERT INTO MyLinkServer.AdventureWorks2012.HumanResources.Department (Name, GroupName)VALUES (N'Public Relations', N'Executive General and Administration');GOB.Insertar datos en una tabla remota con una función OPENQUERYEn el ejemplo siguiente se inserta una fila en una tabla remota especificando la función de conjunto de filas OPENQUERY. En este ejemplo se usa el nombre del servidor vinculado creado en el ejemplo anterior.Transact-SQL

-- Use the OPENQUERY function to access the remote data source.

INSERT OPENQUERY (MyLinkServer, 'SELECT Name, GroupName FROM AdventureWorks2012.HumanResources.Department')VALUES ('Environmental Impact', 'Engineering');GOC.Insertar datos en una tabla remota con una función OPENDATASOURCEEn el ejemplo siguiente se inserta una fila en una tabla remota especificando 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.Transact-SQL

-- Use the OPENDATASOURCE function to specify the remote data source.-- Specify a valid server name for Data Source using the format server_name or server_name\instance_name.

INSERT INTO OPENDATASOURCE('SQLNCLI', 'Data Source= <server_name>; Integrated Security=SSPI') .AdventureWorks2012.HumanResources.Department (Name, GroupName) VALUES (N'Standards and Methods', 'Quality Assurance');GO

Cargar datos de forma masiva de tablas o archivos de datosLos ejemplos de esta sección muestran dos métodos para cargar datos de forma masiva en una tabla mediante la instrucción INSERT.A.Insertar datos en un montón con registro mínimoEl ejemplo siguiente crea una tabla nueva (un montón) e inserta los datos en ella desde otra tabla con registro mínimo. El ejemplo supone que el modelo de recuperación de la base de datos AdventureWorks2012 está establecido en FULL. Para asegurarse de que se utiliza el registro mínimo, el modelo de recuperación de la base de

Page 39: Cláusula SELECT

datos AdventureWorks2012 se establece en BULK_LOGGED antes de que las filas se inserten y se restablece en FULL después de la instrucción INSERT INTO…SELECT. Además, se especifica la sugerencia TABLOCK para la tabla de destino Sales.SalesHistory. Esto asegura que la instrucción use el espacio mínimo en el registro de transacciones y funcione eficazmente.Transact-SQL

USE AdventureWorks2012;GO-- Create the target heap.CREATE TABLE Sales.SalesHistory( SalesOrderID int NOT NULL, SalesOrderDetailID int NOT NULL, CarrierTrackingNumber nvarchar(25) NULL, OrderQty smallint NOT NULL, ProductID int NOT NULL, SpecialOfferID int NOT NULL, UnitPrice money NOT NULL, UnitPriceDiscount money NOT NULL, LineTotal money NOT NULL, rowguid uniqueidentifier ROWGUIDCOL NOT NULL, ModifiedDate datetime NOT NULL );GO-- Temporarily set the recovery model to BULK_LOGGED.ALTER DATABASE AdventureWorks2012SET RECOVERY BULK_LOGGED;GO-- Transfer data from Sales.SalesOrderDetail to Sales.SalesHistoryINSERT INTO Sales.SalesHistory WITH (TABLOCK) (SalesOrderID, SalesOrderDetailID, CarrierTrackingNumber, OrderQty, ProductID, SpecialOfferID, UnitPrice, UnitPriceDiscount, LineTotal, rowguid, ModifiedDate)SELECT * FROM Sales.SalesOrderDetail;GO-- Reset the recovery model.ALTER DATABASE AdventureWorks2012SET RECOVERY FULL;GOB.Usar la función OPENROWSET con BULK para cargar datos de forma masiva en una tablaEn el ejemplo siguiente se insertan filas de un archivo de datos en una tabla especificando la función OPENROWSET. La sugerencia de tabla IGNORE_TRIGGERS se

Page 40: Cláusula SELECT

especifica para la optimización del rendimiento. Para obtener más ejemplos, vea Importar de forma masiva datos mediante BULK INSERT u OPENROWSET(BULK...) (SQL Server).Transact-SQL

-- Use the OPENROWSET function to specify the data source and specifies the IGNORE_TRIGGERS table hint.INSERT INTO HumanResources.Department WITH (IGNORE_TRIGGERS) (Name, GroupName)SELECT b.Name, b.GroupName FROM OPENROWSET ( BULK 'C:\SQLFiles\DepartmentData.txt', FORMATFILE = 'C:\SQLFiles\BulkloadFormatFile.xml', ROWS_PER_BATCH = 15000)AS b ;GO

Invalidar el comportamiento predeterminado del optimizador de consultas mediante sugerenciasLos ejemplos de esta sección demuestran cómo usar sugerencias de tabla para invalidar de forma temporal el comportamiento predeterminado del optimizador de consultas cuando se procesa la instrucción INSERT.

 Advertencia

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.

A.Usar la sugerencia TABLOCK para especificar un método de bloqueoEn el ejemplo siguiente se especifica que se aplique un bloqueo exclusivo (X) en la tabla Production.Location y que se mantenga hasta que finalice la instrucción INSERT.Transact-SQL

USE AdventureWorks2012;GOINSERT INTO Production.Location WITH (XLOCK)(Name, CostRate, Availability)VALUES ( N'Final Inventory', 15.00, 80.00);GO

Capturar los resultados de la instrucción INSERTLos ejemplos de esta sección demuestran cómo usar la cláusula OUTPUT para devolver información de cada fila afectada por una instrucción INSERT 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.A. Usar OUTPUT con una instrucción INSERTEn el siguiente ejemplo se inserta una fila en la tabla ScrapReason y se utiliza la cláusula OUTPUT para devolver los resultados de la instrucción a la variable de la tabla @MyTableVar. Dado que la columna ScrapReasonID se define con una propiedad IDENTITY, no se especifica ningún valor en la instrucción INSERT para dicha

Page 41: Cláusula SELECT

columna. No obstante, debe tener en cuenta que el valor generado por Motor de base de datos para la columna se devuelve en la cláusula OUTPUT de la columnaINSERTED.ScrapReasonID.Transact-SQL

USE AdventureWorks2012;GODECLARE @MyTableVar table( NewScrapReasonID smallint, Name varchar(50), ModifiedDate datetime);INSERT Production.ScrapReason OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate INTO @MyTableVarVALUES (N'Operator error', GETDATE());

--Display the result set of the table variable.SELECT NewScrapReasonID, Name, ModifiedDate FROM @MyTableVar;--Display the result set of the table.SELECT ScrapReasonID, Name, ModifiedDate FROM Production.ScrapReason;GOB.Usar OUTPUT con columnas de identidad y calculadasEn el siguiente ejemplo se crea la tabla EmployeeSales y, a continuación, se insertan varias filas en ella usando una instrucción INSERT con una instrucción SELECT para recuperar los datos de las tablas de origen. La tabla EmployeeSales contiene una columna de identidad (EmployeeID) y una columna calculada (ProjectedSales). Puesto que Motor de base de datos genera estos valores durante la operación de inserción, ninguna de estas columnas se puede definir [email protected]

USE AdventureWorks2012 ;GOIF OBJECT_ID ('dbo.EmployeeSales', 'U') IS NOT NULL DROP TABLE dbo.EmployeeSales;GOCREATE TABLE dbo.EmployeeSales( EmployeeID int IDENTITY (1,5)NOT NULL, LastName nvarchar(20) NOT NULL, FirstName nvarchar(20) NOT NULL, CurrentSales money NOT NULL, ProjectedSales AS CurrentSales * 1.10 );GODECLARE @MyTableVar table( LastName nvarchar(20) NOT NULL, FirstName nvarchar(20) NOT NULL, CurrentSales money NOT NULL );

INSERT INTO dbo.EmployeeSales (LastName, FirstName, CurrentSales)

Page 42: Cláusula SELECT

OUTPUT INSERTED.LastName, INSERTED.FirstName, INSERTED.CurrentSales INTO @MyTableVar SELECT c.LastName, c.FirstName, sp.SalesYTD FROM Sales.SalesPerson AS sp INNER JOIN Person.Person AS c ON sp.BusinessEntityID = c.BusinessEntityID WHERE sp.BusinessEntityID LIKE '2%' ORDER BY c.LastName, c.FirstName;

SELECT LastName, FirstName, CurrentSalesFROM @MyTableVar;GOSELECT EmployeeID, LastName, FirstName, CurrentSales, ProjectedSalesFROM dbo.EmployeeSales;GOC.Insertar los datos devueltos por una cláusula OUTPUTEn el ejemplo siguiente se capturan los datos devueltos por la cláusula OUTPUT de una instrucción MERGE y se insertan en otra tabla. La instrucción MERGE actualiza diariamente la columna Quantity de la tabla ProductInventory basándose en los pedidos procesados en la tabla SalesOrderDetail. También elimina las filas correspondientes a los productos cuyas existencias se colocan en el valor 0. En el ejemplo se capturan las filas que se eliminan y se insertan en otra tabla,ZeroInventory, que realiza el seguimiento de los productos sin existencias.Transact-SQL

USE AdventureWorks2012;GOIF OBJECT_ID(N'Production.ZeroInventory', N'U') IS NOT NULL DROP TABLE Production.ZeroInventory;GO--Create ZeroInventory table.CREATE TABLE Production.ZeroInventory (DeletedProductID int, RemovedOnDate DateTime);GO

INSERT INTO Production.ZeroInventory (DeletedProductID, RemovedOnDate)SELECT ProductID, GETDATE()FROM( MERGE Production.ProductInventory AS pi USING (SELECT ProductID, SUM(OrderQty) FROM Sales.SalesOrderDetail AS sod JOIN Sales.SalesOrderHeader AS soh ON sod.SalesOrderID = soh.SalesOrderID AND soh.OrderDate = '20070401' GROUP BY ProductID) AS src (ProductID, OrderQty) ON (pi.ProductID = src.ProductID) WHEN MATCHED AND pi.Quantity - src.OrderQty <= 0 THEN DELETE

Page 43: Cláusula SELECT

WHEN MATCHED THEN UPDATE SET pi.Quantity = pi.Quantity - src.OrderQty OUTPUT $action, deleted.ProductID) AS Changes (Action, ProductID)WHERE Action = 'DELETE';IF @@ROWCOUNT = 0PRINT 'Warning: No rows were inserted';GOSELECT DeletedProductID, RemovedOnDate FROM Production.ZeroInventory;

Page 44: Cláusula SELECT

UPDATE (Transact-SQL)SQL Server 2012

Otras versiones

Personas que lo han encontrado útil: 5 de 5 - Valorar este tema

Cambia los datos de una tabla o vista de SQL Server 2012. Para obtener ejemplos, vea Ejemplos. Convenciones de sintaxis de Transact-SQL

Sintaxis

Transact-SQL

[ WITH <common_table_expression> [...n] ]UPDATE     [ TOP ( expression ) [ PERCENT ] ]     { { table_alias | <object> | rowset_function_limited          [ WITH ( <Table_Hint_Limited> [ ...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 ]

    [ <OUTPUT Clause> ]    [ FROM{ <table_source> } [ ,...n ] ]

Page 45: Cláusula SELECT

    [ WHERE { <search_condition>             | { [ CURRENT OF                   { { [ GLOBAL ] cursor_name }                       | cursor_variable_name                   }                 ]              }            }     ]     [ OPTION ( <query_hint> [ ,...n ] ) ][ ; ]

<object> ::={     [ server_name . database_name . schema_name .     | database_name .[ schema_name ] .     | schema_name .    ]    table_or_view_name}

Argumentos

WITH <common_table_expression>

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 obtener más información, vea 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 utilizar 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 FROM 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

Page 46: Cláusula SELECT

tabla o la vista. Si se especifica server_name, son obligatorios 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 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 poder actualizarse y debe hacer referencia exactamente a una tabla base en la cláusula FROM de la vista. Para obtener más información acerca de las vistas que se pueden actualizar, veaCREATE VIEW (Transact-SQL).

rowset_function_limited

Es la función OPENQUERY u OPENROWSET, dependiendo de las funciones del proveedor.

WITH ( <Table_Hint_Limited> )

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. No se permiten NOLOCK ni READUNCOMMITTED. Para obtener más información acerca de 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 expressionsustituye al valor existente en column_name o @variable.

 Nota

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

Page 47: Cláusula SELECT

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 utiliza uno o varios argumentos.

.WRITE (expression,@Offset,@Length)

Especifica que una sección del valor de column_name se va a modificar. expression reemplaza las unidades @Length a partir de @Offset de column_name. Con esta cláusula solo se pueden especificar 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 usa para incrementar column_name. expression se debe evaluar, o bien se debe poder convertir implícitamente al tipocolumn_name. Si expression se establece como NULL, se omitirá @Length, y se truncará el valor de column_name en el @Offset especificado.@Offset es el punto inicial del valor de column_name en el que se escribe expression. @Offset es una posición ordinal basada en cero, es de tipo bigint y no puede ser un número negativo. Si @Offset es NULL, la operación de actualización anexa expression al final del valor de column_name existente y @Length no se tiene en cuenta. Si @Offset es mayor que la longitud del valor de column_name, el 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. Si

Page 48: Cláusula SELECT

la suma de @Offset y LEN(expression) es superior al tamaño subyacente declarado, se produce un error.@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 en NULL, la operación de actualización quita todos los datos de @Offset hasta el final del valor de column_name.Para obtener más información, vea la sección Notas.

@ 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 no es lo mismo que SET @variable = column, column =expression, que establece la variable en el valor previo a la actualización de la columna.

<OUTPUT_Clause>

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 obtener más información, vea OUTPUT (cláusula de Transact-SQL).

FROM <table_source>

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.

 Nota

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.

Page 49: Cláusula SELECT

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.

<search_condition>

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. El número de predicados que pueden incluirse en una condición de búsqueda no tiene límite. Para obtener más información acerca de los predicados y las condiciones de búsqueda, vea Condiciones 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 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.

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 ( <query_hint> [ ,... 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, vea Sugerencias de consulta (Transact-SQL).

Prácticas recomendadas

Utilice la función @@ROWCOUNT para devolver el número de filas insertado a la aplicación cliente. Para obtener más información, vea @@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 utilice la cláusula OUTPUT.

Page 50: Cláusula SELECT

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.Transact-SQL

USE AdventureWorks2012;GOIF OBJECT_ID ('dbo.Table1', 'U') IS NOT NULL DROP TABLE dbo.Table1;GOIF OBJECT_ID ('dbo.Table2', 'U') IS NOT NULL DROP TABLE dbo.Table2;GOCREATE TABLE dbo.Table1 (ColA int NOT NULL, ColB decimal(10,3) NOT NULL);GOCREATE TABLE dbo.Table2 (ColA int PRIMARY KEY NOT NULL, ColB decimal(10,3) NOT NULL);GOINSERT INTO dbo.Table1 VALUES(1, 10.0), (1, 20.0);INSERT INTO dbo.Table2 VALUES(1, 0.0);GOUPDATE dbo.Table2 SET dbo.Table2.ColB = dbo.Table2.ColB + dbo.Table1.ColBFROM dbo.Table2 INNER JOIN dbo.Table1 ON (dbo.Table2.ColA = dbo.Table1.ColA);GOSELECT 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.Transact-SQL

USE AdventureWorks2012;GOIF OBJECT_ID ('dbo.Table1', 'U') IS NOT NULL DROP TABLE dbo.Table1;GOIF OBJECT_ID ('dbo.Table2', 'U') IS NOT NULL DROP TABLE dbo.Table2;GOCREATE TABLE dbo.Table1

Page 51: Cláusula SELECT

(c1 int PRIMARY KEY NOT NULL, c2 int NOT NULL);GOCREATE TABLE dbo.Table2 (d1 int PRIMARY KEY NOT NULL, d2 int NOT NULL);GOINSERT INTO dbo.Table1 VALUES (1, 10);INSERT INTO dbo.Table2 VALUES (1, 20), (2, 30);GODECLARE 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;GOSELECT 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 obtener más información, vea SET ANSI_PADDING (Transact-SQL).

Actualizar columnas de tipo text, ntext e imageAl 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, utilice WRITETEXT o UPDATETEXT en lugar de la instrucción UPDATE.

Page 52: Cláusula SELECT

Si la instrucción UPDATE pudo 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.

 Importante

Los tipos de datos ntext, text e image se quitarán en una versión futura de Microsoft 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)

Actualizar tipos de datos de valores grandesUse la cláusula .WRITE (expression, @Offset,@Length) para realizar una actualización parcial o completa de los tipos de datos varchar(max), nvarchar(max) yvarbinary(max). Por ejemplo, la actualización parcial de una columna varchar(max) podría eliminar o modificar solo los 200 primeros caracteres de la columna, mientras que una actualización completa eliminaría o modificaría todos los datos de la columna. .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. Tenga en cuenta que el registro mínimo no se utiliza cuando se actualizan valores existentes. Para obtener más información, vea 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 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 la columna modificada por la cláusula .WRITE se hace referencia en una cláusula OUTPUT, el valor completo de la columna, ya sea la imagen anterior dedeleted.column_name o la imagen posterior de inserted.column_name, se vuelve a 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 tipos definidos por el usuarioHay 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

Page 53: Cláusula SELECT

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 datos FILESTREAMPuede 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 puede utilizar .WRITE() para realizar actualizaciones parciales de datos FILESTREAM. Para obtener más información, vea FILESTREAM (SQL Server).

Tratamiento 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,

Page 54: Cláusula SELECT

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 obtener más información acerca de los desencadenadores INSTEAD OF, vea CREATE TRIGGER (Transact-SQL).

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 acerca de 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.Transact-SQL

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

Page 55: Cláusula SELECT

FROM cte AS x -- cte is assigned an alias.INNER JOIN @y AS y ON y.ID = x.ID;SELECT * FROM @x;GOEl conjunto de resultados es el siguiente.ID     Value------ -----1      1002      200(2 row(s) affected)Transact-SQL

-- UPDATE statement with CTE references that are incorrectly matched.USE tempdb;GODECLARE @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.ValueFROM cte AS x -- cte is assigned an alias.INNER JOIN @y AS y ON y.ID = x.ID; SELECT * FROM @x; GOEl conjunto de resultados es el siguiente.ID     Value------ -----1      1002      100(2 row(s) affected)

Comportamiento del bloqueo

Una instrucción UPDATE siempre adquiere un bloqueo exclusivo (X) en la tabla que modifica y retiene ese bloqueo hasta que se completa la transacción. Con un bloqueo exclusivo, ninguna otra transacción puede modificar los datos. Puede especificar sugerencias de tabla para invalidar este comportamiento predeterminado durante la ejecución de la instrucción UPDATE especificando otro método de bloqueo, sin embargo se recomienda que solo los desarrolladores y administradores de bases de datos experimentados usen las sugerencias y únicamente como último recurso. Para obtener más información, vea Sugerencias de tabla (Transact-SQL).

Comportamiento del registro

Page 56: Cláusula SELECT

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" en la sección anterior "Tipos de datos".

Seguridad

PermisosSe 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 utilice una columna de la tabla.Los permisos para utilizar UPDATE corresponden de forma predeterminada a los miembros del rol fijo de servidor sysadmin, de los roles fijos de base de datosdb_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

Categoría Elementos de sintaxis ofrecidos

Sintaxis básica UPDATE

Limitar las filas que se actualizan WHERE • TOP • expresión de tabla común WITH • WHERE CURRENT OF

Establecer valores de columna valores calculados • operadores compuestos • valores predeterminados • subconsultas

Especificar objetos de destino que no sean tablas estándar vistas • variables de tabla • alias de tabla

Actualizar los datos basados en datos del resto de las tablas FROM

Actualizar las filas de una tabla remota servidor vinculado • 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

sugerencias de tabla • sugerencias de consulta

Page 57: Cláusula SELECT

Capturar los resultados de la instrucción UPDATE Cláusula OUTPUT

Usar UPDATE en otras instrucciones Procedimientos almacenados • TRY…CATCH

Sintaxis básicaLos 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 simpleEn el ejemplo siguiente se actualiza un solo valor de columna para todas las filas de la tabla Person.Address.Transact-SQL

USE AdventureWorks2012;GOUPDATE Person.AddressSET ModifiedDate = GETDATE();B.Actualizar varias columnasEn el siguiente ejemplo se actualizan los valores de las columnas Bonus, CommissionPct y SalesQuota para todas las filas de la tabla SalesPerson.Transact-SQL

USE AdventureWorks2012;GOUPDATE Sales.SalesPersonSET Bonus = 6000, CommissionPct = .10, SalesQuota = NULL;GO

Limitar las filas que se actualizanEn los ejemplos de esta sección se muestran varias formas de limitar el número de filas afectadas por la instrucción UPDATE.A.Usar la cláusula WHEREEn 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 tablaProduction.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.Transact-SQL

USE AdventureWorks2012;GOUPDATE Production.ProductSET Color = N'Metallic Red'WHERE Name LIKE N'Road-250%' AND Color = N'Red';GOB.Usar la cláusula TOPEn 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

Page 58: Cláusula SELECT

número de filas 'n'. En el ejemplo siguiente se actualiza un 25 por ciento la columnaVacationHours en 10 filas aleatorias de la tabla Employee.Transact-SQL

USE AdventureWorks2012;GOUPDATE TOP (10) HumanResources.EmployeeSET VacationHours = VacationHours * 1.25 ;GOSi 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.Transact-SQL

UPDATE HumanResources.EmployeeSET VacationHours = VacationHours + 8FROM (SELECT TOP 10 BusinessEntityID FROM HumanResources.Employee ORDER BY HireDate ASC) AS thWHERE HumanResources.Employee.BusinessEntityID = th.BusinessEntityID;GOC.Usar la cláusula WITH common_table_expressionEn el siguiente ejemplo se actualiza el valor PerAssemnblyQty para todas las partes y componentes que se utilizan directamente o indirectamente para crear elProductAssemblyID 800. La expresión de tabla común devuelve una lista jerárquica de partes que se utilizan directamente para generar el ProductAssemblyID 800y las partes que se utilizan para generar esos componentes, etc. Solo se modifican las filas devueltas por la expresión de tabla común.Transact-SQL

USE AdventureWorks2012;GOWITH 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.BillOfMaterialsSET PerAssemblyQty = c.PerAssemblyQty * 2

Page 59: Cláusula SELECT

FROM Production.BillOfMaterials AS cJOIN Parts AS d ON c.ProductAssemblyID = d.AssemblyIDWHERE d.ComponentLevel = 0; D.Usar la cláusula WHERE CURRENT OFEn 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.Transact-SQL

USE AdventureWorks2012;GODECLARE 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.EmployeePayHistorySET PayFrequency = 2 WHERE CURRENT OF complex_cursor;CLOSE complex_cursor;DEALLOCATE complex_cursor;GO

Establecer valores de columnaEn los ejemplos de esta sección se muestra la actualización de columnas mediante valores calculados, subconsultas y valores DEFAULT.A.Especificar un valor calculadoEn 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.Transact-SQL

USE AdventureWorks2012 ;GOUPDATE Production.ProductSET ListPrice = ListPrice * 2;GOB.Especificar un operador compuestoEn 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.Transact-SQL

USE AdventureWorks2012;GODECLARE @NewPrice int = 10;UPDATE Production.Product

Page 60: Cláusula SELECT

SET ListPrice += @NewPriceWHERE Color = N'Red';GOEn 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.Transact-SQL

USE AdventureWorks2012;GOUPDATE Production.ScrapReason SET Name += ' - tool malfunction'WHERE ScrapReasonID BETWEEN 10 and 12;C.Especificar una subconsulta en la cláusula SETEn 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.Transact-SQL

USE AdventureWorks2012;GOUPDATE Sales.SalesPersonSET 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);GOD.Actualizar las filas con valores DEFAULTEn 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.Transact-SQL

USE AdventureWorks2012;GOUPDATE Production.LocationSET CostRate = DEFAULTWHERE CostRate > 20.00;

Especificar objetos de destino que no sean tablas estándarEn los ejemplos de esta sección se muestra cómo actualizar filas especificando una vista, un alias de tabla o una variable de tabla.A.Especificar una vista como el objeto de destinoEn 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

Page 61: Cláusula SELECT

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 obtener más información, vea Modificar datos mediante una vista.Transact-SQL

USE AdventureWorks2012;GOUPDATE Person.vStateProvinceCountryRegionSET CountryRegionName = 'United States of America'WHERE CountryRegionName = 'United States';B.Especificar un alias de tabla como el objeto de destinoEn 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.Transact-SQL

USE AdventureWorks2012;GOUPDATE srSET sr.Name += ' - tool malfunction'FROM Production.ScrapReason AS srJOIN Production.WorkOrder AS wo ON sr.ScrapReasonID = wo.ScrapReasonID AND wo.ScrappedQty > 300;C.Especificar una variable de tabla como el objeto de destinoEn el siguiente ejemplo se actualizan las filas de una variable de tabla.Transact-SQL

USE AdventureWorks2012;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 @MyTableVarSET NewVacationHours = e.VacationHours + 20, ModifiedDate = GETDATE()FROM HumanResources.Employee AS e WHERE e.BusinessEntityID = EmpID;

-- Display the results of the UPDATE statement.

Page 62: Cláusula SELECT

SELECT EmpID, NewVacationHours, ModifiedDate FROM @MyTableVarORDER BY EmpID;GO

Actualizar los datos basados en datos del resto de las tablasEn los ejemplos de esta sección se muestran métodos para actualizar las filas de una tabla basada en la información de otra.A.Usar la instrucción UPDATE con información de otra tablaEn este ejemplo se modifica la columna SalesYTD de la tabla SalesPerson para reflejar las ventas más recientes registradas en la tabla SalesOrderHeader.Transact-SQL

USE AdventureWorks2012;GOUPDATE Sales.SalesPersonSET SalesYTD = SalesYTD + SubTotalFROM Sales.SalesPerson AS spJOIN Sales.SalesOrderHeader AS so ON sp.BusinessEntityID = so.SalesPersonID AND so.OrderDate = (SELECT MAX(OrderDate) FROM Sales.SalesOrderHeader WHERE SalesPersonID = sp.BusinessEntityID);GOEn 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 siguiente ejemplo:Transact-SQL

USE AdventureWorks2012;GOUPDATE Sales.SalesPersonSET 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

Page 63: Cláusula SELECT

Actualizar las filas de una tabla remotaEn 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.A.Actualizar datos en una tabla remota con un servidor vinculadoEn el ejemplo siguiente se actualiza una tabla en un servidor remoto. En el ejemplo se comienza creando un vínculo al origen de datos remoto mediantesp_addlinkedserver. El nombre del servidor vinculado, MyLinkServer, 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.Transact-SQL

USE master;GO-- Create a link to the remote data source. -- Specify a valid server name for @datasrc as 'server_name' or 'server_name\instance_name'.

EXEC sp_addlinkedserver @server = N'MyLinkServer', @srvproduct = N' ', @provider = N'SQLNCLI10', @datasrc = N'<server name>', @catalog = N'AdventureWorks2012';GOUSE AdventureWorks2012;GO-- Specify the remote data source using a four-part name -- in the form linked_server.catalog.schema.object.

UPDATE MyLinkServer.AdventureWorks2012.HumanResources.DepartmentSET GroupName = N'Public Relations'WHERE DepartmentID = 4;B.Actualizar datos en una tabla remota con la función OPENQUERYEn el ejemplo siguiente se actualiza una fila en una tabla remota especificando la función de conjunto de filas OPENQUERY. En este ejemplo se usa el nombre del servidor vinculado creado en el ejemplo anterior.Transact-SQL

UPDATE OPENQUERY (MyLinkServer, 'SELECT GroupName FROM HumanResources.Department WHERE DepartmentID = 4') SET GroupName = 'Sales and Marketing';C.Actualizar datos en una tabla remota con la función OPENDATASOURCEEn el ejemplo siguiente se inserta una fila en una tabla remota especificando 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

Page 64: Cláusula SELECT

obtener más información, vea 5b982015-e196-44c3-83b8-275fb9d769b2.cmp.xml (opción de configuración del servidor).Transact-SQL

UPDATE OPENQUERY (MyLinkServer, 'SELECT GroupName FROM HumanResources.Department WHERE DepartmentID = 4') SET GroupName = 'Sales and Marketing';

Actualizar tipos de datos de objetos grandesEn 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).A.Usar UPDATE con .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 tablaProduction.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.Transact-SQL

USE AdventureWorks2012;GODECLARE @MyTableVar table ( SummaryBefore nvarchar(max), SummaryAfter nvarchar(max));UPDATE Production.DocumentSET DocumentSummary .WRITE (N'features',28,10)OUTPUT deleted.DocumentSummary, inserted.DocumentSummary INTO @MyTableVarWHERE Title = N'Front Reflector Bracket Installation';SELECT SummaryBefore, SummaryAfter FROM @MyTableVar;GOB.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 utilizar 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.Transact-SQL

USE AdventureWorks2012;

Page 65: Cláusula SELECT

GO-- Replacing NULL value with temporary data.UPDATE Production.DocumentSET DocumentSummary = N'Replacing NULL value'WHERE Title = N'Crank Arm and Tire Maintenance';GOSELECT DocumentSummary FROM Production.DocumentWHERE 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.DocumentSET DocumentSummary .WRITE(N'Carefully inspect and maintain the tires and crank arms.',0,NULL)WHERE Title = N'Crank Arm and Tire Maintenance';GOSELECT DocumentSummary FROM Production.DocumentWHERE Title = N'Crank Arm and Tire Maintenance';GO-- Appending additional data to the end of the column by setting -- @Offset to NULL.UPDATE Production.DocumentSET DocumentSummary .WRITE (N' Appending data to the end of the column.', NULL, 0)WHERE Title = N'Crank Arm and Tire Maintenance';GOSELECT DocumentSummary FROM Production.DocumentWHERE 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.DocumentSET DocumentSummary .WRITE (NULL, 56, 0)WHERE Title = N'Crank Arm and Tire Maintenance';GOSELECT DocumentSummary FROM Production.DocumentWHERE Title = N'Crank Arm and Tire Maintenance';GO-- Removing partial data beginning at position 9 and ending at -- position 21.UPDATE Production.DocumentSET DocumentSummary .WRITE ('',9, 12)WHERE Title = N'Crank Arm and Tire Maintenance';GOSELECT DocumentSummary FROM Production.Document

Page 66: Cláusula SELECT

WHERE Title = N'Crank Arm and Tire Maintenance';GOC.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.Transact-SQL

USE AdventureWorks2012;GOUPDATE Production.ProductPhotoSET ThumbNailPhoto = ( SELECT * FROM OPENROWSET(BULK 'c:\Tires.jpg', SINGLE_BLOB) AS x )WHERE ProductPhotoID = 1;GOD.Usar UPDATE para modificar datos FILESTREAMEn 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).Transact-SQL

UPDATE Archive.dbo.RecordsSET [Chart] = CAST('Xray 1' as varbinary(max))WHERE [SerialNumber] = 2;

Actualizar tipos definidos por el usuarioEn los siguientes ejemplos se modifican valores de columnas de tipo definido por el usuario (UDT) CLR. Se muestran tres métodos. Para obtener más información acerca de las columnas definidas por el usuario, vea Tipos definidos por el usuario de CLR.A.Usar un tipo de datos del sistemaPuede usar un UDT para suministrar 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.CitiesSET Location = CONVERT(Point, '12.3:46.2')WHERE Name = 'Anchorage';B.Invocar un métodoPuede 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.CitiesSET Location.SetXY(23.5, 23.5)

Page 67: Cláusula SELECT

WHERE Name = 'Anchorage';C.Modificar el valor de una propiedad o miembro de datosPuede 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.CitiesSET Location.X = 23.5WHERE Name = 'Anchorage';

Invalidar el comportamiento predeterminado del optimizador de consultas mediante sugerenciasEn 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.

 Advertencia

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 los desarrolladores experimentados utilicen las sugerencias y como último recurso.

A.Especificar una sugerencia de tablaEn el siguiente ejemplo se especifica la sugerencia de tabla TABLOCK. Esta sugerencia especifica que se aplique un bloqueo compartido a la tablaProduction.Product y que se mantenga hasta que finalice la instrucción UPDATE.Transact-SQL

USE AdventureWorks2012;GOUPDATE Production.ProductWITH (TABLOCK)SET ListPrice = ListPrice * 1.10WHERE ProductNumber LIKE 'BK-%';GOB.Especificar una sugerencia de consultaEn el siguiente ejemplo se especifica la sugerencia de consultaOPTIMIZE 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.Transact-SQL

USE AdventureWorks2012;GOCREATE PROCEDURE Production.uspProductUpdate@Product nvarchar(25)ASSET NOCOUNT ON;

Page 68: Cláusula SELECT

UPDATE Production.ProductSET ListPrice = ListPrice * 1.10WHERE ProductNumber LIKE @ProductOPTION (OPTIMIZE FOR (@Product = 'BK-%') );GO-- Execute the stored procedure EXEC Production.uspProductUpdate 'BK-%';

Capturar los resultados de la instrucción UPDATELos ejemplos de esta sección demuestran 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.A.Usar UPDATE con la cláusula OUTPUTEn el siguiente ejemplo se actualiza un 25 por ciento de la columna VacationHours de las 10 primeras filas de la tabla Employee y también 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 columnadeleted.VacationHours y el valor actualizado en la columna inserted.VacationHours en la variable de tabla @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. Para obtener más ejemplos en los que se utiliza la cláusula OUTPUT, vea OUTPUT (cláusula de Transact-SQL).Transact-SQL

USE AdventureWorks2012;GODECLARE @MyTableVar table( EmpID int NOT NULL, OldVacationHours int, NewVacationHours int, ModifiedDate datetime);UPDATE TOP (10) HumanResources.EmployeeSET VacationHours = VacationHours * 1.25, ModifiedDate = GETDATE() OUTPUT inserted.BusinessEntityID, deleted.VacationHours, inserted.VacationHours, inserted.ModifiedDateINTO @MyTableVar;--Display the result set of the table variable.SELECT EmpID, OldVacationHours, NewVacationHours, ModifiedDateFROM @MyTableVar;GO--Display the result set of the table.SELECT TOP (10) BusinessEntityID, VacationHours, ModifiedDateFROM HumanResources.Employee;GO

Page 69: Cláusula SELECT

Usar UPDATE en otras instruccionesEn los ejemplos de esta sección se muestra cómo usar UPDATE en otras instrucciones.A.Usar UPDATE en un procedimiento almacenadoEn el siguiente ejemplo se utiliza 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 utiliza en la instrucción UPDATE para actualizar la columna VacationHours de la tablaHumanResources.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 cada hora (SalariedFlag = 0),VacationHours se establece en el número actual de horas más el valor especificado en @NewHours; por otra parte, VacationHours se establece en el valor especificado en @NewHours.Transact-SQL

USE AdventureWorks2012;GOCREATE PROCEDURE HumanResources.Update_VacationHours@NewHours smallintAS SET NOCOUNT ON;UPDATE HumanResources.EmployeeSET VacationHours = ( CASE WHEN SalariedFlag = 0 THEN VacationHours + @NewHours ELSE @NewHours END )WHERE CurrentFlag = 1;GO

EXEC HumanResources.Update_VacationHours 40;B.Usar UPDATE en un bloque TRY…CATCHEn el siguiente ejemplo se usa una instrucción UPDATE en un bloque TRY…CATCH para administrar los errores de ejecución que se puedan producir durante una operación de actualización.Transact-SQL

USE AdventureWorks2012;GOBEGIN TRANSACTION;

BEGIN TRY -- Intentionally generate a constraint violation error. UPDATE HumanResources.Department SET Name = N'MyNewName' WHERE DepartmentID BETWEEN 1 AND 2;END TRY

Page 70: Cláusula SELECT

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

Page 71: Cláusula SELECT

El INNER JOIN

El INNER JOIN es otro tipo de composición de tablas, permite emparejar filas de distintas tablas de forma más eficiente que con el producto cartesiano cuando una de lascolumnas de emparejamiento está indexada. Ya que en vez de hacer el producto cartesiano completo y luego seleccionar la filas que cumplen la condición de emparejamiento, para cada fila de una de las tablas busca directamente en la otra tabla las filas que cumplen la condición, con lo cual se emparejan sólo las filas que luego aparecen en el resultado.

La sintaxis es la siguiente:

Ejemplo:

SELECT *FROM pedidos INNER JOIN clientes ON pedidos.clie = clientes.numclie

 tabla1 y tabla2 son especificaciones de tabla (nombre de tabla con alias o no, nombre de consulta guardada), de las tablas cuyos registros se van a combinar.

Pueden ser las dos la misma tabla, en este caso es obligatorio definir al menos un alias de tabla.

 col1, col2 son las columnas de emparejamiento.

Observar que dentro de la cláusula ON los nombres de columna deben ser nombres cualificados (llevan delante el nombre de la tabla y un punto).

 Las columnas de emparejamiento deben contener la misma clase de datos, las dos de tipo texto, de tipo fecha etc... los campos numéricos deben ser de tipos similares. Por ejemplo, se puede combinar campos AutoNumérico y Long puesto que son tipos similares, sin embargo, no se puede combinar campos de tipo Simple y Doble. Además las columnas no pueden ser de tipo Memo ni OLE.

 comp representa cualquier operador de comparación ( =, <, >, <=, >=, o <> ) y se utiliza para establecer la condición de emparejamiento.

Se pueden definir varias condiciones de emparejamiento unidas por los operadores AND y OR poniendo cada condición entre paréntesis. Ejemplo:

SELECT * FROM pedidos INNER JOIN productos ON (pedidos.fab = productos.idfab) AND (pedidos.producto = productos.idproducto)

 Se pueden combinar más de dos tablas En este caso hay que sustituir en la sintaxis una tabla por un INNER JOIN completo. 

Por ejemplo:

Page 72: Cláusula SELECT

SELECT *FROM (pedidos INNER JOIN clientes ON pedidos.clie = clientes.numclie) INNER JOIN empleados ON pedidos.rep = empleados.numemp

En vez de tabla1 hemos escrito un INNER JOIN completo, también podemos escribir:

SELECT *FROM clientes INNER JOIN (pedidos INNER JOIN empleados ON pedidos.rep = empleados.numemp) ON pedidos.clie = clientes.numclie

En este caso hemos sustituido tabla2 por un INNER JOIN completo.

Page 73: Cláusula SELECT

Consultas combinadas. JOINS

Consultas combinadas.

    Habitualmente cuando necesitamos recuperar la información de una base de datos nos encontramos con que dicha información se encuentra repartida en varias tablas, referenciadas a través de varios códigos. De este modo si tuvieramos una tabla de ventas con un campo cliente, dicho campo contendría el código del cliente de la tabla de cliente. 

    Sin embargo está forma de almacenar la información no resulta muy util a la hora de consultar los datos. SQL nos proporciona una forma facil de mostrar la información repartida en varias tablas, las consultas combinadas o JOINS.

    Las consultas combinadas pueden ser de tres tipos:

Combinación interna Combinación externa Uniones

[arriba]

Combinación interna.

    La combinación interna nos permite mostrar los datos de dos o más tablas a través de una condición WHERE.

    Si recordamos los ejemplos de los capitulos anteriores tenemos una tabla de coches, en la que tenemos referenciada la marca a través del código de marca. Para realizar la consulta combinada entre estas dos tablas debemos escribir una consulta SELECT  en cuya claúsula FROM escribiremos el nombre de las dos tablas, separados por comas, y una condición WHERE que obligue a que el código de marca de la tabla de coches sea igual al código de la tabla de marcas.

    Lo más sencillo es ver un ejemplo directamente:

SELECT tCoches.matricula,               tMarcas.marca,               tCoches.modelo,               tCoches.color,               tCoches.numero_kilometros,               tCoches.num_plazas FROM tCoches, tMarcas WHERE tCoches.marca = tMarcas.codigo

    La misma consulta de forma "visual" ...

Page 74: Cláusula SELECT

    Demonos cuenta que hemos antepuesto el nombre de cada tabla a el nombre del campo, esto no es obligatorio si los nombres de campos no se repiten en las tablas, pero es acondajable para evitar conflictos de nombres entre campos. Por ejemplo, si para referirnos al campo marca no anteponemos el nombre del campo la base de datos no sabe si queremos el campo marca de la tabla tCoches, que contiene el código de la marca, o el campo marca de la tabla tMarcas, que contiene el nombre de la marca.

    Otra opción es utilizar la cláusula INNER JOIN. Su sintaxis es identica a la de una consulta SELECT habitual, con la particularidad de que én la cláusula FROM sólo aparece una tabla o vista, añadiendose el resto de tablas a través de cláusulas INNER JOIN .

SELECT [ALL | DISTINCT ]             <nombre_campo> [{,<nombre_campo>}]FROM <nombre_tabla> [{INNER JOIN  <nombre_tabla> ON <condicion_combinacion>}][WHERE <condicion> [{ AND|OR <condicion>}]][GROUP BY <nombre_campo> [{,<nombre_campo >}]][HAVING <condicion>[{ AND|OR <condicion>}]][ORDER BY <nombre_campo>|<indice_campo> [ASC | DESC]                  [{,<nombre_campo>|<indice_campo> [ASC | DESC ]}]]

    El ejemplo anterior escrito utilizando la clausula INNER JOIN  quedaria de la siguiente manera:

SELECT tCoches.matricula,        tMarcas.marca,        tCoches.modelo,        tCoches.color,        tCoches.numero_kilometros,        tCoches.num_plazas FROM tCochesINNER JOIN tMarcas ON tCoches.marca = tMarcas.codigo

    La cláusula INNER JOIN permite separar completamente las condiciones de combinación con otros criterios, cuando tenemos consultas que combinan nueve o diez tablas esto realmente se agradece. Sin embargo muchos programadores no son amigos de la cláusula INNER JOIN, la razón es que uno de los principales gestores de bases de datos, ORACLE, no la soportaba. Si nuestro porgrama debia trabajar sobre bases de datos ORACLE no podiamos utilizar INNER JOIN. A partir de la version ORACLE 9i oracle soporta la cláusula INNER JOIN.

Page 75: Cláusula SELECT

[arriba]

Combinación Externa

    La combinación interna es excluyente. Esto quiere decir que si un registro no cumple la condición de combinación no se incluye en los resultados. De este modo en el ejemplo anterior si un coche no tiene grabada la marca no se devuelve en mi consulta.

    Según la naturaleza de nuestra consulta esto puede ser una ventaja , pero en otros casos significa un serio problema. Para modificar este comportamiento SQL pone a nuestra disposición la combinación externa. La combinación externa no es excluyente.

    La sintaxis es muy parecida a la combinación interna,

SELECT [ALL | DISTINCT ]             <nombre_campo> [{,<nombre_campo>}]FROM <nombre_tabla> [{LEFT|RIGHT OUTER JOIN  <nombre_tabla> ON <condicion_combinacion>}][WHERE <condicion> [{ AND|OR <condicion>}]][GROUP BY <nombre_campo> [{,<nombre_campo >}]][HAVING <condicion>[{ AND|OR <condicion>}]][ORDER BY <nombre_campo>|<indice_campo> [ASC | DESC]                  [{,<nombre_campo>|<indice_campo> [ASC | DESC ]}]]

    La combinación externa puede ser diestra o siniestra, LEFT OUTER JOIN o RIGHT OUTER JOIN.  Con LEFT  OUTER JOIN obtenemos todos los registros de en la tabla que situemos a la izquierda de la clausula JOIN, mientras que con RIGHT OUTER JOIN obtenmos el efecto contrario.

    Como mejor se ve la combinación externa es con un ejemplo.

SELECT tCoches.matricula,        tMarcas.marca,        tCoches.modelo,        tCoches.color,        tCoches.numero_kilometros,        tCoches.num_plazas FROM tCochesLEFT OUTER JOIN tMarcas ON tCoches.marca = tMarcas.codigo

    Esta consulta devolverá todos los registros de la tabla tCoches, independientemente de que tengan marca o no. En el caso de que el coche no tenga marca se devolverá el valor null para los campos de la tabla tMarcas.

    Visualmente (la consulta devuelve los datos en azul) ...

Page 76: Cláusula SELECT

 

    El mismo ejemplo con RIGHT OUTER JOIN.

SELECT tCoches.matricula,        tMarcas.marca,        tCoches.modelo,        tCoches.color,        tCoches.numero_kilometros,        tCoches.num_plazas FROM tCochesRIGHT OUTER JOIN tMarcas ON tCoches.marca = tMarcas.codigo

    Esta consulta devolverá los registros de la tabla tCoches que tengan marca relacionada y todos los registros de la tabla tMarcas, tengan algún registro en tCoches o no.

    Visualmente (la consulta devuelve los datos en azul) ...

[arriba]

Union

    La cláusula UNION permite unir dos o más conjuntos de resultados en uno detras del otro como si se tratase de una única tabla. De este modo podemos obtener los registros de mas de una tabla "unidos".

    La sintaxis corresponde a la de varias SELECT unidas a través de UNION, como se muestra a continuación:

SELECT [ALL | DISTINCT ]             <nombre_campo> [{,<nombre_campo>}]

Page 77: Cláusula SELECT

FROM <nombre_tabla> [{LEFT|RIGHT OUTER JOIN  <nombre_tabla> ON <condicion_combinacion>}][WHERE <condicion> [{ AND|OR <condicion>}]][GROUP BY <nombre_campo> [{,<nombre_campo >}]][HAVING <condicion>[{ AND|OR <condicion>}]]{UNION [ALL | DISTINCT ]SELECT [ALL | DISTINCT ]             <nombre_campo> [{,<nombre_campo>}]FROM <nombre_tabla> [{LEFT|RIGHT OUTER JOIN  <nombre_tabla> ON <condicion_combinacion>}][WHERE <condicion> [{ AND|OR <condicion>}]][GROUP BY <nombre_campo> [{,<nombre_campo >}]][HAVING <condicion>[{ AND|OR <condicion>}]]}[ORDER BY <nombre_campo>|<indice_campo> [ASC | DESC]                  [{,<nombre_campo>|<indice_campo> [ASC | DESC ]}]]

    Para utilizar la clausula UNION debemos cumplir una serie de normas.

Las consultas a unir deben tener el mismo número campos, y además los campos deben ser del mismo tipo.

Sólo puede haber una única clausula ORDER BY al final de la sentencia SELECT.

    El siguiente ejemplo muestra el uso de UNION

SELECT tCoches.matricula,        tMarcas.marca,        tCoches.modelo,        tCoches.color,        tCoches.numero_kilometros,        tCoches.num_plazas FROM tCochesINNER JOIN tMarcas ON tCoches.marca = tMarcas.codigoUNIONSELECT tMotos.matricula,        tMarcas.marca,        tMotos.modelo,        tMotos.color,        tMotos.numero_kilometros,        0FROM tMotosINNER JOIN tMarcas ON tMotos.marca = tMarcas.codigo;Puede observarse el uso de la constante cero en la segunda lista de selección para hacer coincidir el número y tipo decampos que devuelve la consulta UNION.

 

Page 78: Cláusula SELECT

Lección 15 - Reunión interna y externa (INNER / OUTER JOIN)

En la lección anterior se trató la operación de reunión entre tablas que guardan una

relación. Existe una sintaxis más concreta para realizar la operación de reunión, donde

la cláusula WHERE se usa únicamente para filtrar registros y no para reunir registros.

Reunión interna - cláusulas inner join / on

Esta cláusula está diseñada precisamente para reunir registros de varias tablas, en ella

intervienen las claves primarias y foráneas, y no intervienen, o lo hacen en la cláusula

WHERE, los filtros propiamente dichos. Veamos una de las consultas que se expuso en

la lección anterior usando esta sintaxis.

Consulta que realiza la reunión entre los profesores y los cursos que imparte cada uno

usando INNER JOIN / ON:

CÓDIGO: SELECCIONAR TODO

select *

  from CURSOS C inner join PROFESORES P 

    on C.ID_PROFE = P.ID_PROFE 

 llevar código al banco de pruebas

Si antes se dijo que el SGBD realiza el producto cartesiano entre dos tablas y

posteriormente mediante la cláusula WHERE ignora aquellos registros que carecen de

sentido y muestra los que guardan una relación, ahora podemos verlo del siguiente

modo: el SGBD recorrerá la tabla hijo(CURSOS) y para cada uno asociará el registro de

la tabla padre(PROFESORES) que satisface la cláusula ON. Para asociar el profesor no

es necesario realizar, para cada curso, un recorrido secuencial sobre la tabla

PROFESORES hasta encontrarlo, puesto que en la cláusula ON estamos indicando su

clave primaria, por lo que el motor SQL usuará el índice que la clave lleva implicito

para localizar un profesor de forma mucho más eficiente. Igual que haría usted para

localizar un capítulo concreto de un libro, usando el índice.

Page 79: Cláusula SELECT

Algunos puristas afirman que este es el modo correcto de construir las consultas,

porque el motor SQL trabaja de un modo más eficiente, a otros sin embargo les resulta

incomodo o simplemente menos atractivo. Lo ideal sería que todo esto fuese

transparente al desarrollador. El motor SQL debe interpretar la consulta y devolver el

resultado de la forma más eficiente, obviamente realizando productos cartesianos y

posteriormente filtrando los registros no es un método eficiente, pero esto es algo que

consideramos en este curso como herramienta de aprendizaje o método de

comprensión, y que en realidad los SGBD no hacen a no ser que no les quede más

remedio, ya sea porque se lo pidamos explícitamente omitiendo la cláusula WHERE, no

se hayan establecido las relaciones, o sean poco "inteligentes". Dicho de otro modo, yo

espero de un SGBD que sea eficaz no solo al ejecutar la consulta, sino al interpretarla y

al elaborar un plan de ejecución adecuado y eficaz, y poder usar la sintaxis que más

cómoda me resulte, sin tener que pensar si la consulta es costosa o no para el motor

SQL. Desafortunadamente no siempre se podrá pasar esto por alto, en ocasiones se

deberá optimizar la consulta para ayudar al SGBD a ser más eficiente. En cualquier

caso la optimización queda fuera del alcance de este curso. Por ahora basta con que

usted sepa que es importante crear las claves primarias y foráneas debidamente, tanto

por una cuestión de eficiencia como de integridad referencial.

Veamos otro ejemplo de la lección anterior usando esta cláusula, concretamente del

apartado de ejercicios, donde se pedía los cursos en que se ha matriculado el alumno

con identificador 1:

CÓDIGO: SELECCIONAR TODO

select C.TITULO CURSO

  from ALUMNOS_CURSOS AC inner join CURSOS C

    on AC.ID_CURSO = C.ID_CURSO

 where AC.ID_ALUMNO = 1

 llevar código al banco de pruebas

Observe como en la cláusula WHERE se establece un filtro propiamente dicho, y en la

cláusula ON se establece la condición de reunión que el motor debe aplicar entre las

tablas a ambos lados de la cláusula INNER JOIN.

Page 80: Cláusula SELECT

Veamos un último ejemplo de reunión interna en la que aparezcan tres tablas, para ello

tomemos otro ejemplo de la lección anterior, la reunión de los alumnos con los cursos

que cursa cada uno. Tomando ejemplos equivalentes construidos únicamente con la

cláusula WHERE se pueden observar mejor las diferencias.

CÓDIGO: SELECCIONAR TODO

  select C.TITULO CURSO , concat(A.APELLIDOS,', ',A.NOMBRE ) ALUMNO

    from ALUMNOS_CURSOS AC inner join ALUMNOS A

      on AC.ID_ALUMNO = A.ID_ALUMNO inner join CURSOS C

      on AC.ID_CURSO  = C.ID_CURSO

order by C.TITULO , A.NOMBRE , A.APELLIDOS

 llevar código al banco de pruebas

Si ahora sobre este consulta se quisiera reducir el resultado a un curso o un alumno en

concreto, se añadiría la pertinente cláusula WHERE con el filtro deseado justo antes de

la cláusula ORDER BY. 

* * *

Reunión externa - left outer join / right outer join

La reunión externa puede verse en este caso como una reunión interna donde no es

necesario que el registro hijo tenga informada la clave foránea para ser mostrado, por

ejemplo, cuando se mostraban los cursos junto a los profesores que los imparten, como

uno de los cursos no tiene padre, es decir, no tiene un profesor asignado, o lo que es lo

mismo, el campo ID_PROFE de la tabla CURSOS está a nulo, este curso no se muestra

dado que no satisface la cláusula ON. Bien, este recurso nos ofrece la posibilidad de

mostrar estos registros con los campos del registro padre a nulo.

La reunión externa siempre se realizaran por la izquierda o por la derecha, una de las

dos. De este modo expresamos el deseo de considerar todos los registros de la tabla a

la izquierda o a la derecha de la cláusula OUTER JOIN, aunque no se hallen

Page 81: Cláusula SELECT

coincidencias con la otra tabla según la cláusula ON. Veamos la consulta que muestra

los cursos y sus profesores aunque el curso no tenga profesor asignado:

CÓDIGO: SELECCIONAR TODO

select *

  from CURSOS C left outer join PROFESORES P 

    on C.ID_PROFE = P.ID_PROFE

 llevar código al banco de pruebas

Como en este caso usamos LEFT OUTER JOIN, la tabla que de la izquierda, es decir, la

tabla CURSOS, será considerada por completo aunque no tenga éxito la cláusula ON,

en cuyo caso los campos de la tabla situada a la derecha de la cláusula se mostrarán a

nulo. 

Si invertimos el orden de las tablas y usamos RIGHT OUTER JOIN, o simplemente RIGHT

JOIN, expresión equivalente simplificada aplicable también a LEFT JOIN, el resultado es

el mismo.

CÓDIGO: SELECCIONAR TODO

select *

  from PROFESORES P right join CURSOS C

    on C.ID_PROFE = P.ID_PROFE

 llevar código al banco de pruebas

En la consulta anterior se están considerando todos los cursos aunque estos no tengan

un profesor definido, si ahora usted quisiera obtener esto mismo pero añadiendo un

filtro sobre la tabla PROFESORES, por ejemplo que el apellido del profesor contenga

una "E", cabe esperar hacerlo en la cláusula WHERE, sin embargo también es posible

aplicar el filtro en la cláusula ON. En realidad elegiremos una u otra cláusula en función

de lo que deseemos obtener. Si lo hacemos en la clausula ON de un OUTER JOIN se

Page 82: Cláusula SELECT

estarán obteniendo todos los cursos con los campos de la tabla PROFESORES a nulo si

la condicion establecida en la cláusula ON no tiene éxito. Si se hace en la cláusula

WHERE se estará forzando a que se cumpla dicha cláusula y por tanto la reunión

externa se rompe. Veamos esto con un ejemplo:

Consulta que muestra todos los cursos acompañados del profesor que lo imparte. Si el

curso no tiene profesro definido o bien el campo APELLIDOS no contiene una "E", los

campos de la tabla PROFESORES se mostrarán a nulo:

CÓDIGO: SELECCIONAR TODO

select *

  from PROFESORES P right join CURSOS C

    on C.ID_PROFE = P.ID_PROFE

   and P.APELLIDOS like '%E%' 

 llevar código al banco de pruebas

El resultado presenta para el curso 3 los campos de la tabla PROFESORES a nulo

porque el campo APELLIDOS del profesor que lo imparte no contiene un "E". Para el

curso 5 ocurre lo mismo pero en este caso el motivo es además que no tiene profesor

definido, con que mucho menos podrá ser cierta la otra condición.

Ahora aplicamos el filtro del apellido en la cláusula WHERE:

CÓDIGO: SELECCIONAR TODO

select *

  from PROFESORES P right join CURSOS C

    on C.ID_PROFE = P.ID_PROFE

 where P.APELLIDOS like '%E%' 

 llevar código al banco de pruebas

Page 83: Cláusula SELECT

Observamos como la reunión externa se rompe puesto que la cláusula WHERE exige

que el apellido del profesor contenga una "E", dado que los cursos que no tienen

profesor definido la consulta devuelve el apellido a nulo, esta cláusula no se satisface

por lo que oculta el registro y la reunión externa carece de sentido, o si usted quiere, la

clausula WHERE es aplicable a la tabla CURSOS pero no a la tabla PROFESORES, puesto

que en este caso no tiene sentido realizar una reunión externa para que luego un filtro

en la cláusula WHERE la anule.

* * *

Vamos ahora a ver los recuentos sobre reuniones externas, por ejemplo los alumnos

que hay matriculados en cada curso. Esta consulta se presentó en la lección anterior,

en el apartado de ejercicios, sin embargo los cursos sin alumnos matriculados eran

ignorados en lugar de aparecer con un cero como sería de esperar. Esto es debido a

que no satisfacen la clausula ON de una reunión interna, por lo que se debe usar la

reunión externa para este propósito, pero cuidado, ahora no nos sirve el recuento de

registros, puesto que pueden venir cursos sin alumnos, o lo que es lo mismo, cursos

con los datos del alumno a nulo, de modo que si contamos registros los datos no serán

verídicos, deben contarse alumnos. Revise si lo cree conveniente la lección 10donde se

trataron las particularidades del valor NULO.

Alumnos matriculados en cada curso, aunque estos sean cero:

CÓDIGO: SELECCIONAR TODO

  select C.TITULO CURSO, count(AC.ID_ALUMNO) ALUMNOS, count(1) REGISTROS

    from ALUMNOS_CURSOS AC right join CURSOS C

     on AC.ID_CURSO = C.ID_CURSO

group by C.TITULO

 llevar código al banco de pruebas

En la anterior consulta se han contado tanto alumnos como registros para poder

observar la diferencia. La única fila en que estos dos valores difieren es para el curso

de SQL avanzado. Dado que la reunión externa devuelve la fila con los datos del

alumno a nulo para los cursos sin alumnos, al realizar un recuento de registros el valor

es uno, el registro existe, pero al realizar el recuento del campo ID_ALUMNO este es

Page 84: Cláusula SELECT

ignorado por la función COUNT por ser nulo.

Observe que en este caso la tabla que interesa tratar por completo mostrando todos

sus registros es la tabla padre(CURSOS), y la tabla donde no importa que halla aciertos

es la tabla hijos(ALUMNOS_CURSOS). Es decir, la consulta devuelve todos los registros

de la tabla CURSOS aunque para ellos no existan hijos en la tabla ALUMNOS_CURSOS.

En los ejemplos anteriores a este último, también interesaba tratar por completo la

tabla CURSOS, pero esta ejercía de hijo y no de padre, y los campos de la tabla

PROFESORES podían venir a nulo no porque no existiera el registro en la tabla

PROFESORES que también, sino como consecuencia de que el campo ID_PROFE de la

tabla CURSOS contenía un valor nulo.

* * *

Por último comentar que la reunión externa no es posible hacerla usando únicamente

la cláusula WHERE, debemos forzosamente usar la cláusula OUTER JOIN. Esto es así en

MySQL, sin embargo en Oracle, que originalmente solo se podían construir consultas

con las sintaxis basada en cláusula WHERE, si es posible realizar reuniones externas

con esta sintaxis, para ello indicamos el símbolo"(+)" tras los campos de la clausula

WHERE pertenecientes a la tabla que devolverá los campos a nulo en el caso de no

cumplirse la condición, por ejemplo la consulta anterior en Oracle se construiría de la

siguiente manera. 

Consulta Oracle:

CÓDIGO: SELECCIONAR TODO

  select C.TITULO CURSO, count(AC.ID_ALUMNO) ALUMNOS, count(1) REGISTROS

    from ALUMNOS_CURSOS AC ,CURSOS C

   where AC.ID_CURSO(+) = C.ID_CURSO

group by C.TITULO

Con ello estamos indicando el SGBD Oracle que aunque no encuentre el registro en la

tabla ALUMNOS_CURSOS, devuelva el registro de la tabla CURSOS con los datos de la

tabla ALUMNOS_CURSOS a nulo, es decir, se esta realizando una reunión externa. Por

ejemplo, en la consulta en la que se devolvía todos los cursos con el profesor que

imparte cada curso y ademas incluíamos el filtro de que el apellido del profesor tuviese

Page 85: Cláusula SELECT

una "E" se construiría de la siguiente manera en Oracle:

Consulta Oracle:

CÓDIGO: SELECCIONAR TODO

select *

  from PROFESORES P , CURSOS C

 where C.ID_PROFE = P.ID_PROFE(+)

   and P.APELLIDOS(+) like '%E%' 

En general en una reunión externa debemos tratar siempre la tabla cuyos campos

pueden venir a nulo, si es en Oracle, aunque actualmente es posible usar la sintaxis

OUTER JOIN, pondremos el símbolo "(+)" a cada campo de dicha tabla que aparezca en

la cláusula WHERE. Si usamos OUTER JOIN, pondremos todos los campos que

establecen condiciones de dicha tabla en la cláusula ON, si lo hacemos en la cláusula

WHERE como filtro corriente la reunión externa se rompe y carece de sentido.

* * *

Resumen

La reunión interna permite reunir registros de tablas relacionadas ignorando los

registros que no satisfacen la condición de reunión especificada en la cláusula WHERE

o bien en la cláusula ON en el caso de usar la sintaxis INNER JOIN.

La reunión externa permite reunir registros de tablas relacionadas considerando todos

los registros de una primera tablas aunque ninguno de los registros de una segunda

tabla presente aciertos contra la primera, obviamente en ese caso los campos de esta

última tabla vendrán a nulo.

Existen dos sintaxis para realizar las operaciones de reunión ya sea externa o interna,

dependiendo del SGBD. Basada en cláusula WHERE o bien basada en cláusula INNER

JOIN / OUTER JOIN. Lo ideal sería dejar a criterio del desarrollador el uso de cualquiera

de ellas siempre y cuando el SGBD lo soporte.

En una reunión externa debemos tratar siempre la tabla cuyos campos pueden venir a

nulo poniendo todos los campos que establecen condiciones de dicha tabla en la

Page 86: Cláusula SELECT

cláusula ON del OUTER JOIN, si lo hacemos en la cláusula WHERE como filtro corriente

la reunión externa se rompe y carece de sentido.

* * *

Ejercicio 1

Construya una consula que resuelva el número de cursos que imparte cada profesor

usando la cláusula INNER JOIN.

Ejercicio 2

Realice una consulta entre las tablas CURSOS, ALUMNOS y ALUMNOS_CURSOS de

modo que aparezcan los alumnos matriculados en cada curso pero mostrando todos los

cursos aunque no tengan alumnos matriculados.

 

Page 87: Cláusula SELECT

SQL WHERE Clause

« Previous

Next Chapter »

The WHERE clause is used to filter records.

The SQL WHERE Clause 

The WHERE clause is used to extract only those records that fulfill a specified criterion.

SQL WHERE SyntaxSELECT column_name,column_nameFROM table_nameWHERE column_name operator value;

Demo Database

In this tutorial we will use the well-known Northwind sample database.

Below is a selection from the "Customers" table:

CustomerID CustomerName ContactName Address City PostalCode

1 Alfreds Futterkiste Maria Anders Obere Str. 57 Berlin 12209

2 Ana Trujillo Emparedados y helados

Ana Trujillo Avda. de la Constitución 2222

México D.F.

05021

3 Antonio Moreno Taquería Antonio Moreno Mataderos 2312 México D.F.

05023

Page 88: Cláusula SELECT

4 Around the Horn Thomas Hardy 120 Hanover Sq. London WA1 1DP

5 Berglunds snabbköp Christina Berglund

Berguvsvägen 8 Luleå S-958 22

WHERE Clause Example

The following SQL statement selects all the customers from the country "Mexico", in the "Customers" table:

Example

SELECT * FROM CustomersWHERE Country='Mexico';

Try it yourself »

Text Fields vs. Numeric Fields

SQL requires single quotes around text values (most database systems will also allow double quotes).

However, numeric fields should not be enclosed in quotes:

Example

SELECT * FROM CustomersWHERE CustomerID=1;

Try it yourself »

Page 89: Cláusula SELECT

Operators in The WHERE Clause

The following operators can be used in the WHERE clause:

Operator Description

= Equal

<> Not equal. Note: In some versions of SQL this operator may be written as !=

> Greater than

< Less than

>= Greater than or equal

<= Less than or equal

BETWEEN Between an inclusive range

LIKE Search for a pattern

IN To specify multiple possible values for a column

Page 90: Cláusula SELECT

Lección 5 - Operadores (SQL WHERE)

Un operador, como su propio nombre indica, es quien opera, normalmente entre

dos operandos, estableciendo una operación que al ejecutarla se obtiene un resultado.

Por ejemplo en matemáticas: 3 + 4

"+" es el operador y, "3" y "4" son los operandos. el resultado de esta operación es 7.

A modo de apunte diremos, aunque poco tenga que ver con esta lección, que el SQL nos

permite calcular ciertas operaciones matemáticas tanto en la clausula SELECT, para

obtener resultados, como en la cláusula WHERE, para establecer condiciones:

CÓDIGO: SELECCIONAR TODO

select 3 + 4

 llevar código al banco de pruebas

A la pregunta: ¿Qué empleados tienen un salario mayor de 1350?, podríamos construir la

consulta SQL así, sustituyendo 1350 por: 1300 + 50.

CÓDIGO: SELECCIONAR TODO

select NOMBRE , APELLIDOS

  from EMPLEADOS

 where SALARIO > 1300 + 50

 llevar código al banco de pruebas

Page 91: Cláusula SELECT

Lógica booleana

Lo que se pretende abordar en esta lección principalmente es la lógica booleana, que

es la que nos permite establecer condiciones. Advierto que esta lección puede resultar

un poco dura, si tiene dificultades para entender lo que trataremos, no se preocupe e

intente quedarse con la idea de fondo.

Cuando usted jugaba al ya clásico juego de ¿quién es quién?,

usted estaba aplicando lógica booleana para descubrir el personaje que su

contrincante escondía. Usted lanzaba preguntas con el propósito de saber si una

característica del personaje misterioso era cierta o falsa, y si era cierta, descartaba los

personajes que no presentaban esa característica. El SGBD hace algo muy parecido,

usted establece una característica en la clausula WHERE de la consulta SQL, y el SGBD

descarta los registros en que la característica es falsa, mientras que mantiene los que

es cierta.

Expresiones booleanas

Si usted jugando a ¿Quién es quién? preguntaba a su contrincante: ¿tiene barba?, lo

que en realidad estaba preguntando era: ¿EL PERSONAJE MISTERIOSO tiene BARBA?

pues bien, esto es una expresión booleana donde:

"tiene" es el operador, "EL PERSONAJE MISTERIOSO" es un operando variable, que

depende del personaje elegido por su contrincante, y "BARBA" es un operando

constante. El resultado de aplicar esta expresión a un personaje concreto dará cierto si

Page 92: Cláusula SELECT

el personaje tiene barba, y falso en caso contrario.

Cuando en la primera consulta de este cuso:

CÓDIGO: SELECCIONAR TODO

select NOMBRE , APELLIDOS

  from EMPLEADOS

 where SALARIO > 1350

 llevar código al banco de pruebas

indicábamos en la clausula WHERE: SALARIO > 1350(¿es SALARIO mayor a 1350?),

estábamos estableciendo una expresión booleana donde:

">" es el operador, "SALARIO" es un operando variable, que tomará valores de cada

registro de la tabla EMPLEADOS, y "1350" es un operando constante. El resultado de

esta expresión depende del valor que tome la variable SALARIO, pero en cualquier caso

sólo puede dar dos posibles resultados, o cierto o falso. Por lo tanto diremos que una

expresión booleana sólo tiene dos posibles resultados.

El motor SQL evalúa la expresión booleana de la clausula WHERE para cada registro de

la tabla, y el resultado determina si el registro que se está tratando se tomará en

consideración. Lo hará si el resultado de evaluar la expresión es cierto, y lo ignorará si

el resultado es falso.

Ejemplo de expresiones booleanas: 

"4 > 3" : ¿es cuatro mayor que tres?

"3 = 12" : ¿es tres igual a doce?

Fíjese que los operandos son del mismo tipo, en este caso tipo INT. Sin embargo el

resultado obtenido no es un dato de tipo INT, sino booleano, sus posibles valores son cierto

o falso.

(4 > 3) = cierto

(3 = 12) = falso

Page 93: Cláusula SELECT

Operadores

Algunos de los operadores que nos permiten construir expresiones booleanas son:

> : "A > B" devuelve cierto si A es estrictamente mayor que B, de lo contrario

devuelve falso.

< : "A < B" devuelve cierto si A es estrictamente menor que B, de lo contrario

devuelve falso.

= : "A = B" devuelve cierto si A es igual a B, de lo contrario devuelve falso.

>= : "A >= B" devuelve cierto si A es mayor o igual a B, de lo contrario

devuelve falso.

<= : "A <= B" devuelve cierto si A es menor o igual a B, de lo contrario

devuelve falso.

!= : "A != B" devuelve cierto si A es distinto a B, de lo contrario devuelve

falso.

Al construir expresiones con estos operadores, los dos operandos deben ser del mismo

tipo, ya sean números, cadenas o fechas.

Ejemplo de expresión booleana con cadenas: ('Aranda, Pedro' < 'Zapata, Mario' ) =

cierto, puesto que por orden alfabético 'Aranda, Pedro' está posicionado antes que

'Zapata, Mario' , por lo tanto es menor el primero que el segundo.

Operadores lógicos

Los operadores lógicos permiten formar expresiones booleanas tomando como

operandos otras expresiones booleanas. Fíjese que en las expresiones vistas

anteriormente, los operandos debían ser números, cadenas o fechas, ahora sin

embargo los operandos deben ser expresiones booleanas, el conjunto forma una nueva

expresión booleana que, como toda expresión booleana, dará como resultado cierto o

falso.

AND : "A and B" devuelve cierto si A y B valen cierto, y falso en cualquier otro

caso.

OR : "A or B" devuelve cierto si A o B valen cierto, y falso únicamente cuando

tanto A como B valen falso.

NOT : "not A" devuelve falso si A vale cierto, y cierto si A vale falso.

Veamos una aplicación en el mundo cotidiano.

Supongamos el siguiente anunciado:

Page 94: Cláusula SELECT

Mi jefe quiere contratar a una persona para repartir genero, solamente pueden optar a

la vacante aquellos candidatos que tengan vehículo propio y licencia de conducir

automóviles. Como candidatos tenemos a Ángela, que tiene licencia pero no tiene

vehículo. A Salva, que tiene licencia y vehículo. Y a Teresa, que tiene vehículo pero de

momento no tiene licencia. ¿Quiénes pueden pasar al proceso de selección?

Convertimos el anunciado en una expresión booleana:

Sea C: pasa al proceso de selección.

Sea A: tiene vehículo propio.

Sea B: tiene licencia de conducir automóviles.

Entonces para que un candidato satisfaga C, se debe dar A y B:

C = A and B

Resolvamos la expresión para cada candidato:

Aplicado a Ángela: C = (A and B) = (falso and cierto) = falso. Luego no pasa al proceso

de selección.

Aplicado a Salva: C = (A and B) = (cierto and cierto) = cierto. Luego pasa al proceso

de selección.

Aplicado a Teresa: C = (A and B) = (cierto and falso) = falso. Luego no pasa al proceso

de selección.

Veamos ahora esto mismo aplicado al SQL:

Consideremos ahora la tabla PERSONAS, donde hemos guardado una "S" en el campo

RUBIA si la persona es rubia y una "N" en caso contrario, análogamente se ha aplicado

el mismo criterio para ALTA y GAFAS, es decir, para indicar si es alta y si lleva gafas.

El operador AND

Como ya hemos dicho el operador AND devuelve cierto si ambas expresiones son

ciertas, y falso en cualquier otro caso. Supongamos que queremos saber ¿qué personas

son rubias y altas?, para ello construimos la siguiente consulta SQL:

Page 95: Cláusula SELECT

CÓDIGO: SELECCIONAR TODO

select NOMBRE

  from PERSONAS

 where (RUBIA = 'S') and (ALTA = 'S')  

 llevar código al banco de pruebas

Resultado:

Evaluar (RUBIA = 'S') da como resultado cierto o falso, al igual que evaluar (ALTA =

'S'), son de echo los dos operandos booleanos del operador AND. Si para un registro

ambos son ciertos el resultado es cierto, y se mostrarán los datos de ese registro que

indica la clausula SELECT.

En el caso de tener una expresión de la forma: "A and B and D" la expresión se evalúa

por partes por orden de aparición:

primero se evalúa (A and B) = E

y finalmente (E and D)

Si todos los operadores de la expresión son AND, entonces todos las expresiones deben

valer cierto para que el resultado sea cierto.

Veamos un ejemplo de esto mientras jugamos a ¿Quién es quién?

Usted pregunta: 

¿es rubia? y la respuesta es cierto

¿es alta? y la respuesta es falso

¿lleva gafas? y la respuesta es cierto

Por lo tanto debe ser una persona que sea rubia y, no sea alta y, lleve gafas.

¿Quién es el personaje?

CÓDIGO: SELECCIONAR TODO

Page 96: Cláusula SELECT

select NOMBRE

  from PERSONAS

 where (RUBIA = 'S') and (ALTA = 'N') and (GAFAS='S')  

 llevar código al banco de pruebas

Resultado:

Antes de dejar el operador AND, recordar del modo equivalente y más simplificado que

se comentó en la lección 3 en que podemos condicionar un campo a un rango de

valores mediante el operador BETWEEN:

CÓDIGO: SELECCIONAR TODO

where SALARIO >= 1300 and SALARIO <=1500

que el salario sea mayor o igual a 1300 y menor o igual a 1500

forma equivalente:

CÓDIGO: SELECCIONAR TODO

where SALARIO between 1300 and 1500

que el salario este entre 1300 y 1500

El operador OR

Con el operador OR basta que uno de los dos operandos sea cierto para que el

resultado sea cierto:

Supongamos que queremos saber las personas que son rubias o bien altas, es decir,

queremos que si es rubia la considere con independencia de su altura, y a la inversa,

también queremos que la seleccione si es alta independientemente del color de pelo.

La consulta sería la siguiente.

CÓDIGO: SELECCIONAR TODO

Page 97: Cláusula SELECT

select NOMBRE

  from PERSONAS

 where (RUBIA = 'S') or (ALTA = 'S')   

 llevar código al banco de pruebas

Resultado:

Si todos los operadores de la expresión son OR, por ejemplo "A or B or C", entonces

todos las expresiones deben valer falso para que el resultado sea falso, con que solo

una valga cierto el resultado es cierto.

Supongamos que quiere seleccionar tres registros concretos de la tabla EMPLEADOS

para ver sus datos, le interesan los registros con identificador 1, 2 y 4. Para esta

situación debe usar el operador OR, puesto que su consulta debe establecer la

condición: que el identificador sea 1, 2 o 4:

CÓDIGO: SELECCIONAR TODO

select *

  from EMPLEADOS

 where ID_EMPLEADO = 1 or ID_EMPLEADO = 2 or ID_EMPLEADO = 4

 llevar código al banco de pruebas

Resultado:

El asterisco presente en la cláusula SELECT equivale a indicar todos los campos de la tabla.

Fíjese como en la anterior consulta para cualquier registro de la tabla EMPLEADOS que

el campo ID_EMPLEADO contenga un valor distinto a 1, 2 o 4, el resultado de evaluar la

expresión será falso, puesto que todos las expresiones booleanas darán falso, pero con

Page 98: Cláusula SELECT

que una de ellas valga cierto, el registro sera seleccionado. De hecho si un mismo

campo aparece dos o más veces en expresiones de la cláusula WHERE como en el

ejemplo anterior, carece de sentido que el operador sea AND: usted puede esperar que

una persona sea rubia o morena, pero no puede esperar que sea rubia y morena. Del

mismo modo el identificador de un registro nunca podrá ser 1 y 2, o es 1 o es 2 o es x.

Un modo de simplificar la anterior consulta es mediante la palabra clave IN, donde se

establece una lista de valores posibles que debe contener el campo indicado para que

el registro sea seleccionado. La palabra clave IN equivale a establecer condiciones

sobre un mismo campo conectadas por el operador OR.

CÓDIGO: SELECCIONAR TODO

select *

  from EMPLEADOS

 where ID_EMPLEADO in (1,2,4) 

 llevar código al banco de pruebas

Resultado:

El operador NOT

Este operador tan solo tiene un operando, el resultado es negar el valor del operando

de modo que:

"(4 > 3) = cierto" luego "not (4>3) = falso"

Si negamos dos veces una expresión booleana es equivalente a la expresión original:

"(4 > 3) = cierto" luego "not ( not (4>3) ) = cierto"

Cuando descubrimos al personaje misterioso, a la pregunta ¿es alta? la respuesta era

falso, luego podríamos haber establecido lo siguiente: "not (ALTA = 'S')" en lugar de

"(ALTA = 'N')":

CÓDIGO: SELECCIONAR TODO

Page 99: Cláusula SELECT

select NOMBRE

  from PERSONAS

 where (RUBIA = 'S') and not (ALTA = 'S') and (GAFAS='S')  

 llevar código al banco de pruebas

Resultado:

Otro ejemplo: si negamos toda la expresión de la clausula WHERE, estaremos

precisamente seleccionando los registros que antes descartábamos, y al revés,

descartando los que antes seleccionábamos.

Tomemos la anterior consulta y neguemos la clausula WHERE, si antes el resultado era:

Carmen, ahora el resultado ha de ser todas las persona menos Carmen. Para hacer

esto cerramos entre paréntesis toda la expresión y le colocamos el operador "not"

delante, de ese modo primero se resolverá lo que esta dentro de los paréntesis y

finalmente se negará el resultado.

CÓDIGO: SELECCIONAR TODO

select NOMBRE

  from PERSONAS

 where not ((RUBIA = 'S') and not(ALTA = 'S') and (GAFAS= 'S'))  

 llevar código al banco de pruebas

Efectivamente el resultado es justo lo contrario que antes:

Y aun otro ejemplo de este operador junto la palabra clave IN: tomemos la consulta

que seleccionaba tres registros concretos de la tabla EMPLEADOS, y modifiquémosla

únicamente incluyendo el operador NOT para que devuelva lo contrario, es decir, todos

los registros menos los tres que antes seleccionaba:

CÓDIGO: SELECCIONAR TODO

Page 100: Cláusula SELECT

select *

  from EMPLEADOS

 where ID_EMPLEADO not in (1,2,4)   

 llevar código al banco de pruebas

Resultado:

El uso de paréntesis

Los paréntesis se comportan como en matemáticas, no es lo mismo "5 + 4 / 3" donde

primero se calculará la división y después se sumará 5, que "(5 + 4) / 3" donde primero

se resolverá la suma y el resultado parcial se dividirá por 3. Sin paréntesis la división

tiene prioridad sobre la suma, con paréntesis forzamos a que la operación se realice en

el orden deseado.

Los operadores AND y OR tienen la misma prioridad de modo que se evalúa la

expresión por orden de aparición:

No es lo mismo: "RUBIA and ALTA or GAFAS" = "(RUBIA and ALTA) or GAFAS" que,

"RUBIA and (ALTA or GAFAS)". En primer caso estamos diciendo: "que sea rubia y alta,

o bien lleve gafas", y en el segundo "que sea rubia y, sea alta o lleve gafas".

CÓDIGO: SELECCIONAR TODO

select NOMBRE

  from PERSONAS

 where RUBIA = 'S' and ALTA = 'S' or GAFAS= 'S'   

 llevar código al banco de pruebas

Resultado:

CÓDIGO: SELECCIONAR TODO

Page 101: Cláusula SELECT

select NOMBRE

  from PERSONAS

 where RUBIA = 'S' and (ALTA = 'S' or GAFAS= 'S')   

 llevar código al banco de pruebas

Resultado:

* * *

Resumen

En esta lección se ha descrito como construir expresiones booleanas y como trabajar

con ellas para establecer condiciones en la clausula WHERE de una consulta SQL.

Las expresiones booleanas con operadores tales como ( > , = , != ...) precisan

operandos de tipo número, cadena o fecha, y el resultado de evaluar la expresión

devuelve siempre cierto o falso.

Ejemplo: (SALARIO > 1350)

Las expresiones con operadores tales como (AND , OR , NOT) precisan expresiones

booleanas como operandos, el conjunto es una nueva expresión booleana que al

evaluarla devolverá siempre cierto o falso.

Ejemplo: RUBIA = 'S' and ALTA = 'S'

El uso de paréntesis garantiza que, en una expresión compleja las expresiones simples

que la forman se evalúen en el orden que usted desea.

Ejemplo: not ( (RUBIA = 'S' or ALTA = 'S') and (ALTA ='N' or GAFAS = 'S') )

* * *

Ejercicio 1

Cree una consulta SQL que devuelva las personas que son altas, o bien son rubias con

gafas.

Ejercicio 2

Cree una consulta SQL que devuelva los empleados que son mujer y cobran más de

Page 102: Cláusula SELECT

1300 euros. 

En la tabla empleados se guarda una "H" en el campo SEXO para indicar que es hombre, o

una "M" para indicar que es mujer.

Ejercicio 3

Usando solo expresiones (ALTA = 'S') , (RUBIA = 'S') , (GAFAS = 'S') combinadas con el

operador NOT resuelva:

¿Quién es quién? Lleva gafas y no es alta ni rubia. 

Ejercicio 4 (optativo)

Suponiendo que A vale cierto y B vale falso, evalúe la siguiente expresión booleana:

C= ((A and B) and (A or (A or B))) or A