SQL SERVER INICIOS MANUAL DE REFERENCIA

1 - Objetivos y alcances del tutorial de Microsoft Sql Server

El curso brinda un concepto teórico corto, luego un problema resuelto que invito a ejecutar, modificar y jugar con el mismo. Por último, y lo más importante, una serie de ejercicios propuestos que nos permitirá saber si podemos aplicar el concepto. La única herramienta que necesitamos inicialmente es este sitio ya que podrá ejecutar todos los problemas como son la creación de tablas, insert, delete, update, definición de índices y restricciones, creación y ejecución de procedimientos almacenados, vistas, subconsultas, creación de trigger etc. La única restricción es que todos los visitantes de este sitio comparten la misma base de datos llamada: wi520641_sqlserverya (este nombre un poco singular se debe a que las empresas de hosting es la que lo define) Siempre que lancemos un comando SQL en el sitio www.sqlserverya.com.ar estaremos accediendo a la base de datos wi520641_sqlserverya.

2 - Crear una tabla (create table - sp_tables - sp_columns - drop table)

Una base de datos almacena su información en tablas. Una tabla es una estructura de datos que organiza los datos en columnas y filas; cada columna es un campo (o atributo) y cada fila, un registro. La intersección de una columna con una fila, contiene un dato específico, un solo valor. Cada registro contiene un dato por cada columna de la tabla. Cada campo (columna) debe tener un nombre. El nombre del campo hace referencia a la información que almacenará. Cada campo (columna) también debe definir el tipo de dato que almacenará. Las tablas forman parte de una base de datos. Nosotros trabajaremos con la base de datos llamada wi520641_sqlserverya (este nombre se debe a que las empresas de hosting es la que lo define), que ya he creado en el servidor sqlserverya.com.ar. Para ver las tablas existentes creadas por los usuarios en una base de datos usamos el procedimiento almacenado "sp_tables @table_owner='dbo';":

sp_tables @table_owner='dbo'; El parámetro @table_owner='dbo' indica que solo muestre las tablas de usuarios y no las que crea el SQL Server para administración interna. Finalizamos cada comando con un punto y coma. Al crear una tabla debemos resolver qué campos (columnas) tendrá y que tipo de datos almacenarán cada uno de ellos, es decir, su estructura. La sintaxis básica y general para crear una tabla es la siguiente: create table NOMBRETABLA( NOMBRECAMPO1 TIPODEDATO, ... NOMBRECAMPON TIPODEDATO ); La tabla debe ser definida con un nombre que la identifique y con el cual accederemos a ella. Creamos una tabla llamada "usuarios" y entre paréntesis definimos los campos y sus tipos: create table usuarios ( nombre varchar(30), clave varchar(10) ); Cada campo con su tipo debe separarse con comas de los siguientes, excepto el último. Cuando se crea una tabla debemos indicar su nombre y definir al menos un campo con su tipo de dato. En esta tabla "usuarios" definimos 2 campos:
 

nombre: que contendrá una cadena de caracteres de 30 caracteres de longitud, que almacenará el nombre de usuario y clave: otra cadena de caracteres de 10 de longitud, que guardará la clave de cada usuario.

Cada usuario ocupará un registro de esta tabla, con su respectivo nombre y clave. Para nombres de tablas, se puede utilizar cualquier caracter permitido para nombres de directorios, el primero debe ser un caracter alfabético y no puede contener espacios. La longitud máxima es de 128 caracteres. Si intentamos crear una tabla con un nombre ya existente (existe otra tabla con ese nombre), mostrará un mensaje indicando que ya hay un objeto llamado 'usuarios' en la base de datos y la sentencia no se ejecutará. Esto es muy importante ya que cuando haga los ejercicios en este sitio puede haber otra persona que haya creado una tabla con el nombre que usted especifique.

Para ver la estructura de una tabla usamos el procedimiento almacenado "sp_columns" junto al nombre de la tabla: sp_columns usuarios; aparece mucha información que no analizaremos en detalle, como el nombre de la tabla, su propietario, los campos, el tipo de dato de cada campo, su longitud, etc.: ...COLUMN_NAME TYPE_NAME LENGHT _______________________________________ nombre varchar 30 clave varchar 10 Para eliminar una tabla usamos "drop table" junto al nombre de la tabla a eliminar: drop table usuarios; Si intentamos eliminar una tabla que no existe, aparece un mensaje de error indicando tal situación y la sentencia no se ejecuta. Para evitar este mensaje podemos agregar a la instrucción lo siguiente: if object_id('usuarios') is not null drop table usuarios; En la sentencia precedente especificamos que elimine la tabla "usuarios" si existe.

3 - Insertar y recuperar registros de una tabla (insert into - select)

Un registro es una fila de la tabla que contiene los datos propiamente dichos. Cada registro tiene un dato por cada columna (campo). Nuestra tabla "usuarios" consta de 2 campos, "nombre" y "clave". Al ingresar los datos de cada registro debe tenerse en cuenta la cantidad y el orden de los campos. La sintaxis básica y general es la siguiente: insert into NOMBRETABLA (NOMBRECAMPO1, ..., NOMBRECAMPOn) values (VALORCAMPO1, ..., VALORCAMPOn); Usamos "insert into", luego el nombre de la tabla, detallamos los nombres de los campos entre paréntesis y separados por comas y luego de la cláusula "values" colocamos los valores para cada campo, también entre paréntesis y separados por comas. Para agregar un registro a la tabla tipeamos:

'Juan Perez'. la cadena no se carga. nombre) values ('River'.'Luis'). entre paréntesis. el valor de la clave (la cadena "Boca") se guardará en el campo "nombre" y el valor del nombre (la cadena "Luis") en el campo "clave": insert into usuarios (nombre. Se coloca entre comillas (simples). Note que los datos ingresados. El tipo "varchar" define una cadena de longitud variable en la cual determinamos el máximo de caracteres entre paréntesis.'payaso'). El tipo de dato especifica el tipo de información que puede guardar un campo: caracteres. En el siguiente ejemplo se colocan los valores en distinto orden en que se nombran los campos. junto al nombre del campo colocamos la longitud. definimos un campo de tipo varchar(30). Estos son algunos tipos de datos básicos de SQL Server (posteriormente veremos otros):  varchar: se usa para almacenar cadenas de caracteres. El comando "select" recupera los registros de una tabla.insert into usuarios (nombre.'Juan'). Una cadena es una secuencia de caracteres. clave) values ('Mariano'. aparece un mensaje indicando tal situación y la sentencia no se ejecuta. Si ingresamos los datos en un orden distinto al orden en que se nombraron los campos. Para ver los registros de una tabla usamos "select": select * from usuarios. para almacenar cadenas de hasta 30 caracteres. 4 . no aparece un mensaje de error y los datos se guardan de modo incorrecto. Es importante ingresar los valores en el mismo orden en que se nombran los campos: insert into usuarios (clave. números.clave) values ('Boca'. ejemplo: 'Hola'. En el ejemplo anterior se nombra primero el campo "clave" y luego el campo "nombre" por eso. es decir. su estructura. Por ejemplo. como corresponden a cadenas de caracteres se colocan entre comillas simples. etc. Con el asterisco indicamos que muestre todos los campos de la tabla "usuarios". los valores también se colocan en ese orden. es decir. Puede guardar hasta 8000 caracteres. Si asignamos una cadena de caracteres de mayor longitud que la definida.Tipos de datos básicos Ya explicamos que al crear una tabla debemos resolver qué campos (columnas) tendrá y que tipo de datos almacenará cada uno de ellos. .

queremos ver el usuario cuyo nombre es "Marcelo". "where" con la cual podemos especificar condiciones para una consulta "select". También es posible recuperar algunos registros. En el ejemplo anterior seleccionamos los campos "titulo" y "autor" de la tabla "libros".). La sintaxis básica y general es la siguiente: select * from NOMBRETABLA. si vamos a guardar precios. podemos recuperar algunos registros. Definimos campos de este tipo cuando queremos representar. clave from usuarios . float: se usa para almacenar valores numéricos con decimales. La lista de campos luego del "select" selecciona los datos correspondientes a los campos nombrados. mostrando todos los registros. la condición: select nombre. cantidades. el tipo "float" es más adecuado. Los datos aparecen ordenados según la lista de selección. empleando la instrucción "select". si en un campo almacenaremos números enteros. si en un campo vamos a guardar un número telefónico o un número de documento. Por ejemplo. 5 . por ejemplo. si definimos un campo de tipo varchar(10) e intentamos asignarle la cadena 'Buenas tardes'. sólo los que cumplan con ciertas condiciones indicadas con la cláusula "where".Recuperar algunos campos (select) Hemos aprendido cómo ver todos los registros de una tabla. por ejemplo. para ello utilizamos "where" y luego de ella.Recuperar algunos registros (where) Hemos aprendido a seleccionar algunos campos de una tabla. Se utiliza como separador el punto (. 6 .  Por ejemplo. Definimos campos de este tipo para precios. el tipo "float" sería una mala elección. de -2000000000 a 2000000000 aprox. con ellos no realizamos operaciones matemáticas. integer: se usa para guardar valores numéricos enteros. Otro ejemplo. en dicha lista los nombres de los campos se separan con comas. usamos "varchar". aparece un mensaje de error y la sentencia no se ejecuta. Por ejemplo. Podemos especificar el nombre de los campos que queremos ver separándolos por comas: select titulo. no así "integer" que no tiene decimales.autor from libros. Existe una cláusula. Antes de crear una tabla debemos pensar en sus campos y optar por el tipo de dato adecuado para cada uno de ellos. Es decir. no "integer" porque si bien son dígitos. El asterisco (*) indica que se seleccionan todos los campos de la tabla.

hacer comparaciones. valores de campos. . Si ningún registro cumple la condición establecida con el "where". En la consulta anterior solicitamos el nombre de todos los usuarios cuya clave sea igual a "River". SQL Server tiene 4 tipos de operadores: 1. NOMBRECAMPOn from NOMBRETABLA where CONDICION. 4. 2. concatenar cadenas. con "where" establecemos condiciones para recuperar algunos registros. etc. relacionales (o de comparación) aritméticos de concatenación lógicos. Por ahora veremos solamente los primeros. 7 .where nombre='Marcelo'. no aparecerá ningún registro.. Los operadores relacionales (o de comparación) nos permiten comparar dos expresiones. Para las condiciones se utilizan operadores relacionales (tema que trataremos más adelante en detalle). . El signo igual(=) es un operador relacional. que pueden ser variables. Para recuperar algunos campos de algunos registros combinamos en la consulta la lista de campos y la cláusula "where": select nombre from usuarios where clave='River'.. Entonces. La sintaxis básica y general es la siguiente: select NOMBRECAMPO1..Operadores relacionales Los operadores son símbolos que permiten realizar operaciones matemáticas. Para la siguiente selección de registros especificamos una condición que solicita los usuarios cuya clave es igual a "River": select nombre. 3.clave from usuarios where clave='River'.

Los operadores relacionales comparan valores del mismo tipo. para ello usamos la condición: select * from libros where autor<>'Borges'. Utilizamos el operador relacional de igualdad.Borrar registros (delete) . Los operadores relacionales vinculan un campo con un valor para que SQL Server compare cada registro (el campo especificado) con el valor dado. Podemos comparar valores numéricos. No son los únicos. precio from libros where precio>20. existen otros que veremos mas adelante. 8 . Los operadores relacionales son los siguientes: = <> > < >= <= igual distinto mayor menor mayor o igual menor o igual Podemos seleccionar los registros cuyo autor sea diferente de "Borges". queremos mostrar los títulos y precios de los libros cuyo precio sea mayor a 20 pesos: select titulo. por ejemplo: select *from libros where autor='Borges'. Se emplean para comprobar si un campo cumple con una condición. Queremos seleccionar los libros cuyo precio sea menor o igual a 30: select *from libros where precio<=30. Por ejemplo.Hemos aprendido a especificar condiciones de igualdad para seleccionar registros de una tabla.

por "RealMadrid": update usuarios set clave='RealMadrid'. Para modificar uno o varios datos de uno o varios registros utilizamos "update" (actualizar). Muestra un mensaje indicando la cantidad de registros que ha eliminado. es decir. queremos como nueva clave "Boca". se eliminan todos los registros de la tabla nombrada. ningún registro será eliminado.Actualizar registros (update) Decimos que actualizamos un registro cuando modificamos alguno de sus valores. Por ejemplo. 9 . Utilizamos "update" junto al nombre de la tabla y "set" junto con el campo a modificar y su nuevo valor. queremos cambiar los valores de todas las claves. queremos eliminar aquel registro cuyo nombre de usuario es "Marcelo": delete from usuarios where nombre='Marcelo'. ningún registro cumple con la condición especificada. en nuestra tabla "usuarios". queremos cambiar el valor correspondiente a la clave de nuestro usuario llamado "Federicolopez". Si solicitamos el borrado de un registro que no existe.Para eliminar los registros de una tabla usamos el comando "delete": delete from usuarios. sino solamente algunos. Por ejemplo. . necesitamos una condición "where" que afecte solamente a este registro: update usuarios set clave='Boca' where nombre='Federicolopez'. Si no queremos eliminar todos los registros. para ello debemos establecer condiciones de selección con "where". Tenga en cuenta que si no colocamos una condición. Podemos modificar algunos registros. El cambio afectará a todos los registros. Por ejemplo. para ello utilizamos el comando "delete" junto con la clausula "where" con la cual establecemos la condición que deben cumplir los registros a borrar. debemos indicar cuál o cuáles.

todo lo que está entre los símbolos "/*" y "*/" no se ejecuta. necesitamos agregar comentarios. Las condiciones no son obligatorias. no se modifica ninguno. un asterisco seguido de una barra (*/). una cadena vacía o una cadena literal "null". un texto que no se ejecuta. 11 . es decir. para ello se emplean dos guiones (--) al comienzo de la línea: select * from libros --mostramos los registros de libros.Si Microsoft SQL Server no encuentra registros que cumplan con la condición del "where". el otro nombre del campo con su nuevo valor 10 .Comentarios Para aclarar algunas instrucciones. autor /*mostramos títulos y nombres de los autores*/ from libros. se coloca una barra seguida de un asterisco (/*) al comienzo del bloque de comentario y al finalizarlo. todo lo que está luego de los guiones (hacia la derecha) no se ejecuta. Es posible ingresar comentarios en la línea de comandos. En estos casos decimos que el campo puede contener valores nulos. clave='Marce' where nombre='Marcelo'. Para agregar varias líneas de comentarios. Para ello colocamos "update". puede desconocerse o no existir el dato correspondiente a algún campo de un registro. . No es lo mismo que un valor "0". select titulo. "set" junto al nombre del campo y el nuevo valor y separado por coma. en la línea anterior. A veces.Valores null (is null) "null" significa "dato desconocido" o "valor inexistente". la actualización afectará a todos los registros. pero si omitimos la cláusula "where". en ocasiones. el nombre de la tabla. También podemos actualizar varios campos en una sola instrucción: update usuarios set nombre='Marceloduarte'.

los campos permiten valores nulos (caso del campo "precio"). Cuando colocamos "null" estamos diciendo que admite valores nulos (caso del campo "editorial"). Si ingresamos los datos de un libro. Para ver cuáles campos admiten valores nulos y cuáles no. El campo "titulo" no debería estar vacío nunca. Veamos un ejemplo.'Siglo XXI'. En el ejemplo anterior.precio) values('El aleph'.'Lewis Carroll'. Para ello.Por ejemplo. muestra un mensaje y la inserción no se realiza. en la columna "IS_NULLABLE" vemos que muestra "NO" en los campos que no permiten valores nulos y "YES" en los campos que si los permiten. Para especificar que un campo no admita valores nulos. por ejemplo: insert into libros (titulo.'Borges'. Nos muestra mucha información. autor varchar(20) not null. es decir.null. podemos ingresar "null" cuando no conocemos el valor. no se coloca entre comillas. si no lo aclaramos. precio float ). igualmente el campo "autor".editorial. Note que el valor "null" no es una cadena de caracteres. debemos especificar que dichos campos no admitan valores nulos: create table libros( titulo varchar(30) not null. tenemos campos que no pueden estar vacíos jamás.null). SQL Server no lo permite.'Borges'. al crear la tabla.editorial. Entonces. Si intentamos ingresar el valor "null" en campos que no admiten valores nulos (como "titulo" o "autor"). podemos tener valores nulos en el campo "precio" porque es posible que para algunos libros no le hayamos establecido el precio para la venta. podemos emplear el procedimiento almacenado "sp_columns" junto al nombre de la tabla. para el cual aún no hemos definido el precio podemos colocar "null" para mostrar que no tiene precio: insert into libros (titulo. por defecto.'Emece'. los campos "editorial" y "precio" si admiten valores nulos. . También podemos colocar "null" en el campo "editorial" si desconocemos el nombre de la editorial a la cual pertenece el libro que vamos a ingresar: insert into libros (titulo.autor. editorial varchar(15) null.autor.25). si un campo acepta valores nulos.25).autor. En contraposición.editorial. Tenemos nuestra tabla "libros".precio) values(null. debemos colocar "not null" luego de la definición del campo. en nuestra tabla de libros.precio) values('Alicia en el pais'.

pero podemos especificarlo igualmente agregando "null". el número de documento puede establecerse como clave primaria. para que un campo no permita valores nulos debemos especificarlo luego de definir el campo.Clave primaria Una clave primaria es un campo (o varios) que identifica un solo registro (fila) en una tabla. Si tenemos la tabla "usuarios". el nombre de cada usuario puede establecerse como clave primaria. es un valor que no se repite. incluso el mismo domicilio (padre e hijo por ejemplo). con la segunda. Vamos a aprender a establecerla al crear la tabla. por ahora veremos la sintaxis más sencilla. Entonces. La sintaxis básica y general es la siguiente: . puede haber personas con igual apellido y nombre.Para recuperar los registros que contengan el valor "null" en algún campo. select * from libros where editorial=''. las siguientes sentencias "select" no retornan los mismos registros: select * from libros where editorial is null. es un valor que no se repite. agregando "not null". Tenemos nuestra tabla "usuarios" definida con 2 campos ("nombre" y "clave"). puede haber usuarios con igual clave. no podemos utilizar los operadores relacionales vistos anteriormente: = (igual) y <> (distinto). Con la primera sentencia veremos los libros cuya editorial es igual a "null". pero su nombre de usuario será siempre diferente. los libros cuya editorial guarda una cadena vacía. Con la primera sentencia veremos los libros cuyo precio es igual a "null" (desconocido). La sentencia anterior tendrá una salida diferente a la siguiente: select * from libros where precio=0. debemos utilizar los operadores "is null" (es igual a null) y "is not null" (no es null): select * from libros where precio is null. con la segunda. Podemos establecer que un campo sea clave primaria al momento de crear la tabla o luego que ha sido creada. Hay 2 maneras de hacerlo. pero su documento será siempre distinto. los campos permiten valores nulos. los libros cuyo precio es 0. Igualmente para campos de tipo cadena. 12 . Por defecto. Para un valor del campo clave existe solamente un registro. Veamos un ejemplo. si tenemos una tabla con datos de personas.

debe cumplir como requisito. . 13 . Por ello. que sus valores no se repitan ni sean nulos. Es decir. aparece un mensaje y la instrucción "insert" no se ejecuta. primary key (NOMBRECAMPO) ). al ingresar los registros. muestra un mensaje y la inserción no se realiza. Cualquier campo (de cualquier tipo) puede ser clave primaria. primary key(nombre) ). el nombre del campo que será clave primaria. clave varchar(10). al definir un campo como clave primaria. si estuviesen repetidos. "primary key" y entre paréntesis.create table NOMBRETABLA( CAMPO TIPO. Sólo puede haber un campo "identity" por tabla. Luego de haber establecido un campo como clave primaria. SQL Server controla que los valores para el campo establecido como clave primaria no estén repetidos en la tabla. . para nuestra tabla "usuarios" para asegurarnos que cada usuario tendrá un nombre diferente y único: create table usuarios( nombre varchar(20). Se utiliza generalmente en campos correspondientes a códigos de identificación para generar valores únicos para cada nuevo registro que se inserta. aparece un mensaje indicando que se viola la clave primaria y la actualización no se realiza. automáticamente SQL Server lo convierte a "not null". Una tabla sólo puede tener una clave primaria. Lo que hacemos agregar luego de la definición de cada campo. si realizamos una actualización. SQL Server controla que los valores para el campo establecido como clave primaria no estén repetidos en la tabla. si en nuestra tabla "usuarios" ya existe un usuario con nombre "juanperez" e intentamos ingresar un nuevo usuario con nombre "juanperez".. Igualmente.Campo con atributo Identity Un campo numérico puede tener un atributo extra "identity". Los valores de un campo con este atributo genera valores secuenciales que se inician en 1 y se incrementan en 1 automáticamente.. En el siguiente ejemplo definimos una clave primaria. si lo estuviese.

debemos agregar el atributo "identity" luego de su definición al crear la tabla: create table libros( codigo int identity.precio) values(5.'Emece'.titulo. porque se inserta automáticamente tomando el último valor como referencia. Este primer registro ingresado guardará el valor 1 en el campo correspondiente al código. por ejemplo: insert into libros (titulo. No está permitido ingresar el valor correspondiente al campo "identity".23). Para que un campo genere sus valores automáticamente. pero lo veremos posteriormente. "identity" permite indicar el valor de inicio de la secuencia y el incremento. Si continuamos ingresando registros. titulo varchar(40) not null. por ejemplo: insert into libros (codigo. Un campo de identidad no permite valores nulos.Para que un campo pueda establecerse como "identity".editorial.editorial. Si ejecutamos el procedimiento "sp_columns()" veremos que en el campo "codigo" en la columna "TYPE_NAME" aparece "int identity" y en la columna "IS_NULLABLE" aparece "NO". Un campo "identity" no es editable. autor varchar(30). . Para ingresar registros omitimos el campo definido como "identity".precio) values('El aleph'. no se puede ingresar un valor ni actualizarlo.'Jose Hernandez'. aunque no se indique especificamente.autor.'Martin Fierro'.'Borges'. precio float ). es decir. Un campo definido como "identity" generalmente se establece como clave primaria. tipos que estudiaremos posteriormente). Cuando un campo tiene el atributo "identity" no se puede ingresar valor para él.autor. o 1 si es el primero.'Paidos'. el código (dato que no ingresamos) se cargará automáticamente siguiendo la secuencia de autoincremento. éste debe ser entero (también puede ser de un subtipo de entero o decimal con escala 0.25). generará un mensaje de error. editorial varchar(15).

etc. Para permitir ingresar un valor en un campo de identidad se debe activar la opción "identity_insert": set identity_insert libros on. colocará el valor "4". precio float ).2). "104".'Alicia en el pais de las maravillas').'Paidos'). Los valores comenzarán en "100" y se incrementarán de 2 en 2. . el primer registro ingresado tendrá el valor "100". las instrucciones "insert" deben explicitar un valor: insert into libros (codigo.titulo) values (5.Otras características del atributo Identity El atributo "identity" permite indicar el valor de inicio de la secuencia y el incremento. Cuando "identity_insert" está en ON. es decir. autor varchar(30). titulo varchar(20). La función "ident_seed()" retorna el valor de inicio del campo "identity" de la tabla que nombramos: select ident_seed('libros'). si se elimina el último registro ingresado (por ejemplo 3) y luego se inserta otro registro. para ello usamos la siguiente sintaxis: create table libros( codigo int identity(100.'Paenza'. "106". Es decir. editorial) values ('Matematica estas ahi'.autor. SQL Server seguirá la secuencia. La función "ident_incr()" retorna el valor de incremento del campo "identity" de la tabla nombrada: select ident_incr('libros'). Hemos visto que en un campo declarado "identity" no puede ingresarse explícitamente un valor. 14 .Los valores secuenciales de un campo "identity" se generan tomando como referencia el último valor ingresado. podemos ingresar valor en un campo "identity" seteando la opción "identity_insert" en "on". Si no se coloca un valor para el campo de identidad. los siguientes "102". es decir. la sentencia no se ejecuta y aparece un mensaje de error: insert into libros (titulo.

vaciamos la tabla con "truncate table". al ingresar un nuevo registro el valor del código se iniciará en 1 nuevamente. por ello hay que tener cuidado al explicitar un valor porque se puede ingresar un valor repetido. si usamos "truncate table" para borrar todos los registros. Por ejemplo. al cargarse el valor en el campo de identidad. . usamos: truncate table libros. éste guardará el valor de código "3". También podemos eliminar todos los registros de una tabla con "truncate table". tenemos la tabla "libros" con el campo "codigo" definido "identity". Por ejemplo. Otra diferencia es la siguiente: cuando la tabla tiene un campo "identity".El atributo "identity" no implica unicidad. al ingresar otra vez un registro. queremos vaciar la tabla "libros". permite repetición de valores. 16 . 15 . si borramos todos los registros con "delete" y luego ingresamos un registro. si en cambio.Truncate table Aprendimos que para borrar todos los registro de una tabla se usa "delete" sin condición "where". La diferencia con "delete" es la velocidad. La sentencia "truncate table" vacía la tabla (elimina todos los registros) y conserva la estructura de la tabla. continúa con la secuencia teniendo en cuenta el valor mayor que se había guardado. "truncate table" la vacía. Para desactivar la opción "identity_insert" tipeamos: set identity_insert libros off. es decir.Otros tipos de datos en SQL Server Ya explicamos que al crear una tabla debemos elegir la estructura adecuada. es más rápido "truncate table" que "delete" (se nota cuando la cantidad de registros es muy grande) ya que éste borra los registros uno a uno. y el valor más alto de ese campo es "2". la secuencia del campo de identidad vuelve a iniciarse en 1. esto es. La diferencia con "drop table" es que esta sentencia borra la tabla. según el caso. El tipo de dato especificado en la definición de cada campo indica los valores permitidos para cada uno de ellos. si borramos todos los registros con "delete" y luego ingresamos un registro. definir los campos y sus tipos más precisos.

códigos de identificación. por ejemplo. símbolos y dígitos con los que no se realizan operaciones matemáticas. Para guardar valores decimales aproximados: float y real. números telefónicos. A continuación analizaremos en detalle cada tipo de dato básicos. 17 . . si un campo numérico almacenará solamente valores enteros el tipo "integer" es más adecuado que. Hay más tipos. Las cadenas se colocan entre comillas simples.Tipo de dato (texto) Ya explicamos que al crear una tabla debemos elegir la estructura adecuada. monedas. Su rango va de 1 a 8000 caracteres. Entonces. Por ejemplo.. nvarchar. 2. 3. por ejemplo. en campos que hacen referencia a cantidades. Existen otros tipos de datos que analizaremos en secciones próximas. subtipos. char(x): define una cadena de longitud fija determinada por el argumento "x". Tenemos los siguientes tipos: 1.Hasta ahora hemos visto 3 tipos de datos: varchar. números de documentos. Si se omite el argumento coloca 1 por defecto. TEXTO: Para almacenar texto usamos cadenas de caracteres. SQL Server ofrece los siguientes tipos: char. Para almacenar valores monetarios: money y smallmoney. usamos el tipo integer (y sus subtipos: tinyint. Su rango es de 1 a 8000 caracteres. por ejemplo. Para almacenar TEXTO usamos cadenas de caracteres. cuando creamos una tabla y definir sus campos debemos elegir el tipo de dato más preciso. símbolos y dígitos con los que no se realizan operaciones matemáticas. precios. integer y float. esto es. definir los campos y sus tipos más precisos. Podemos almacenar letras. Para almacenar valores con decimales exactos. Para almacenar valores enteros. varchar. Podemos almacenar letras. utilizamos: numeric o decimal (son equivalentes). números de documentos. FECHAS y HORAS: para guardar fechas y horas SQL Server dispone de 2 tipos: datetime y smalldatetime. 2. por ejemplo un "float". decimales. según el caso. si necesitamos almacenar nombres usamos texto. etc. Si se omite el argumento coloca 1 por defecto. NUMEROS: Existe variedad de tipos numéricos para representar enteros. varchar(x): define una cadena de caracteres de longitud variable en la cual determinamos el máximo de caracteres con el argumento "x" que va entre paréntesis. Las cadenas se colocan entre comillas simples. si necesitamos almacenar precios. Los valores que podemos guardar son: 1. lo más lógico es utilizar el tipo "money". códigos de identificación. números telefónicos. text y ntext. nchar. smallint y bigint). incluso.

3. 4. 5. 6.

Si la longitud es invariable, es conveniente utilizar el tipo char; caso contrario, el tipo varchar. Ocupa tantos bytes como se definen con el argumento "x". "char" viene de character, que significa caracter en inglés. text: guarda datos binarios de longitud variable, puede contener hasta 2000000000 caracteres. No admite argumento para especificar su longitud. nvarchar(x): es similar a "varchar", excepto que permite almacenar caracteres Unicode, su rango va de 0 a 4000 caracteres porque se emplean 2 bytes por cada caracter. nchar(x): es similar a "char" excpeto que acepta caracteres Unicode, su rango va de 0 a 4000 caracteres porque se emplean 2 bytes por cada caracter. ntext: es similar a "text" excepto que permite almacenar caracteres Unicode, puede contener hasta 1000000000 caracteres. No admite argumento para especificar su longitud.

En general se usarán los 3 primeros. Si intentamos almacenar en un campo una cadena de caracteres de mayor longitud que la definida, aparece un mensaje indicando tal situación y la sentencia no se ejecuta. Por ejemplo, si definimos un campo de tipo varchar(10) y le asignamos la cadena 'Aprenda PHP' (11 caracteres), aparece un mensaje y la sentencia no se ejecuta. Si ingresamos un valor numérico (omitiendo las comillas), lo convierte a cadena y lo ingresa como tal. Por ejemplo, si en un campo definido como varchar(5) ingresamos el valor 12345, lo toma como si hubiésemos tipeado '12345', igualmente, si ingresamos el valor 23.56, lo convierte a '23.56'. Si el valor numérico, al ser convertido a cadena supera la longitud definida, aparece un mensaje de error y la sentencia no se ejecuta. Es importante elegir el tipo de dato adecuado según el caso, el más preciso. Para almacenar cadenas que varían en su longitud, es decir, no todos los registros tendrán la misma longitud en un campo determinado, se emplea "varchar" en lugar de "char". Por ejemplo, en campos que guardamos nombres y apellidos, no todos los nombres y apellidos tienen la misma longitud. Para almacenar cadenas que no varían en su longitud, es decir, todos los registros tendrán la misma longitud en un campo determinado, se emplea "char". Por ejemplo, definimos un campo "codigo" que constará de 5 caracteres, todos los registros tendrán un código de 5 caracteres, ni más ni menos. Para almacenar valores superiores a 8000 caracteres se debe emplear "text". Tipo Bytes de almacenamiento _______________________________________ varchar(x) 0 a 8K char(x) 0 a 8K

text nvarchar(x) 0 a 8K nchar(x) 0 a 8K ntext

0 a 2GB

0 a 2GB

18 - Tipo de dato (numérico)

Ya explicamos que al crear una tabla debemos elegir la estructura adecuada, esto es, definir los campos y sus tipos más precisos, según el caso. Para almacenar valores NUMERICOS SQL Server dispone de varios tipos. Para almacenar valores ENTEROS, por ejemplo, en campos que hacen referencia a cantidades, usamos: 1) integer o int: su rango es de -2000000000 a 2000000000 aprox. El tipo "integer" tiene subtipos: - smallint: Puede contener hasta 5 digitos. Su rango va desde –32000 hasta 32000 aprox. - tinyint: Puede almacenar valores entre 0 y 255. - bigint: De –9000000000000000000 hasta 9000000000000000000 aprox. Para almacenar valores numéricos EXACTOS con decimales, especificando la cantidad de cifras a la izquierda y derecha del separador decimal, utilizamos: 2) decimal o numeric (t,d): Pueden tener hasta 38 digitos, guarda un valor exacto. El primer argumento indica el total de dígitos y el segundo, la cantidad de decimales. Por ejemplo, si queremos almacenar valores entre -99.99 y 99.99 debemos definir el campo como tipo "decimal(4,2)". Si no se indica el valor del segundo argumento, por defecto es "0". Por ejemplo, si definimos "decimal(4)" se pueden guardar valores entre -9999 y 9999. El rango depende de los argumentos, también los bytes que ocupa. Se utiliza el punto como separador de decimales. Si ingresamos un valor con más decimales que los permitidos, redondea al más cercano; por ejemplo, si definimos "decimal(4,2)" e ingresamos el valor "12.686", guardará "12.69", redondeando hacia arriba; si ingresamos el valor "12.682", guardará "12.67", redondeando hacia abajo. Para almacenar valores numéricos APROXIMADOS con decimales utilizamos: 3) float y real: De 1.79E+308 hasta 1.79E+38. Guarda valores aproximados. 4) real: Desde 3.40E+308 hasta 3.40E+38. Guarda valores aproximados. Para almacenar valores MONETARIOS empleamos:

5) money: Puede tener hasta 19 digitos y sólo 4 de ellos puede ir luego del separador decimal; entre – 900000000000000.5808 aprox y 900000000000000.5807. 6) smallmoney: Entre –200000.3648 y 200000.3647 aprox. Para todos los tipos numéricos: - si intentamos ingresar un valor fuera de rango, no lo permite. - si ingresamos una cadena, SQL Server intenta convertirla a valor numérico, si dicha cadena consta solamente de dígitos, la conversión se realiza, luego verifica si está dentro del rango, si es así, la ingresa, sino, muestra un mensaje de error y no ejecuta la sentencia. Si la cadena contiene caracteres que SQL Server no puede convertir a valor numérico, muestra un mensaje de error y la sentencia no se ejecuta. Por ejemplo, definimos un campo de tipo decimal(5,2), si ingresamos la cadena '12.22', la convierte al valor numérico 12.22 y la ingresa; si intentamos ingresar la cadena '1234.56', la convierte al valor numérico 1234.56, pero como el máximo valor permitido es 999.99, muestra un mensaje indicando que está fuera de rango. Si intentamos ingresar el valor '12y.25', SQL Server no puede realizar la conversión y muestra un mensaje de error. Es importante elegir el tipo de dato adecuado según el caso, el más preciso. Por ejemplo, si un campo numérico almacenará valores positivos menores a 255, el tipo "int" no es el más adecuado, conviene el tipo "tinyint", de esta manera usamos el menor espacio de almacenamiento posible. Si vamos a guardar valores monetarios menores a 200000 conviene emplear "smallmoney" en lugar de "money". Tipo Bytes de almacenamiento _______________________________________ int 4 smallint 2 tinyint 1 bigint 8 decimal float real money smallmoney 4 2 a 17 4u8 4u8 8

19 - Tipo de dato (fecha y hora)

Ya explicamos que al crear una tabla debemos elegir la estructura adecuada, esto es, definir los campos y sus tipos más precisos, según el caso.

si ingresamos '10:15'. sin hora. tipeamos: set dateformat dmy. Las fechas se ingresan entre comillas simples.milisegundos".000'. Para almacenar valores de tipo fecha se permiten como separadores "/". en tal caso. Por ejemplo. en tal caso la hora se guarda como "00:00:00". independientemente del formato de ingreso que hayamos seteado. El formato por defecto es "mdy". 15/4/1996 15/96/4. Por ejemplo.". coloca la fecha "1900-01-01". mostrará '1900-01-01 10:15. mes y año) empleamos "set dateformat".000'. 4/96/15. Estos son los formatos: -mdy: -myd: -dmy: -dym: -ydm: -ydm: 4/15/96 (mes y día con 1 ó 2 dígitos y año con 2 ó 4 dígitos). Tipo Bytes de almacenamiento _______________________________________ datetime 8 smalldatetime 4 20 .Para almacenar valores de tipo FECHA Y HORA SQL Server dispone de dos tipos: 1) datetime: puede almacenar valores desde 01 de enero de 1753 hasta 31 de diciembre de 9999. Podemos emplear los operadores relacionales vistos para comparar fechas. 96/15/4.Ingresar algunos campos (insert into) . SQL Server reconoce varios formatos de entrada de datos de tipo fecha. Podemos ingresar una fecha. Podemos ingresar una hora sin fecha. Para ingresar una fecha con formato "día-mes-año". 1996/15/4. "-" y ". lo mostrará así: '2001-12-25 00:00:00. 2) smalldatetime: el rango va de 01 de enero de 1900 hasta 06 de junio de 2079. Para establecer el orden de las partes de una fecha (dia. si ingresamos '2512-01' (año de 2 dígitos). Todos los valores de tipo "datetime" se muestran en formato "año-mes-día hora:minuto:segundo .

. autor) values ('El aleph'. .si ingresamos valores para todos los campos podemos obviar la lista de campos. si omitimos el valor para un campo "not null". Por ejemplo. Si ingresamos valores para todos los campos.la lista de campos debe coincidir en cantidad y tipo de valores con la lista de valores luego de "values". . para el cual no hemos explicitado un valor. También es posible ingresar valores para algunos campos. es decir.se pueden omitir valores para campos declarados "not null" siempre que tengan definido un valor por defecto con la cláusula "default" (tema que veremos a continuación). Un valor por defecto se inserta cuando no está presente al ingresar un registro y en algunos casos en que el dato ingresado es inválido.podemos omitir valores para los campos que NO hayan sido declarados "not null". si tenemos creada la tabla "libros" con los campos "titulo". A estos valores se les denomina valores por defecto o predeterminados. aparece un mensaje de error y la sentencia no se ejecuta. Ingresamos valores solamente para los campos "titulo" y "autor": insert into libros (titulo. . Al ingresar registros debemos tener en cuenta: .'Borges').se DEBE omitir el valor para el campo"identity". Si se listan más (o menos) campos que los valores ingresados. .'Planeta'). se ingresa automaticamente "null" y si el campo está declarado "identity". "autor" y "editorial". la sentencia no se ejecuta.Valores por defecto (default) Hemos visto que si al insertar registros no se especifica un valor para un campo que admite valores nulos.Hemos aprendido a ingresar registros listando todos los campos y colocando valores para todos y cada uno de ellos luego de "values". podemos ingresar un registro de la siguiente manera: insert into libros values ('Uno'. que permitan valores nulos (se guardará "null"). podemos omitir la lista de nombres de los campos.'Richard Bach'. se inserta el siguiente de la secuencia. 21 . SQL Server almacenará el valor "null" en el campo "editorial". Salvo que identity_insert este en on.

autor. muestra el valor por defecto del campo. se pueden explicitar valores por defecto con la cláusula "default".precio. el valor por defecto es "null".default.2). Podemos establecer valores por defecto para los campos cuando creamos la tabla. precio decimal(5. Para todos los tipos. no existe valor por defecto. titulo varchar(40). La sentencia anterior almacenará un registro con los valores predetermiandos para cada uno de sus campos. si al definir el campo explicitamos un valor mediante la cláusula "default". el siguiente valor de la secuencia en "codigo". autor varchar(30) not null default 'Desconocido'. Para campos declarados "not null". es decir. por ejemplo: insert into libros (titulo. a menos que se declare explícitamente con la cláusula "default".100). Si al ingresar un nuevo registro omitimos los valores para el campo "autor" y "cantidad". editorial varchar(20). Si no se explicita. la cláusula "default" permite especificar el valor por defecto de un campo. que admiten valores nulos. el valor por defecto es "null". en "autor" colocará "Desconocido" y en cantidad "0". También se puede utilizar "default" para dar el valor por defecto a los campos en sentencias "insert".Para campos de cualquier tipo no declarados "not null". Ahora. ése será el valor por defecto. cantidad tinyint default 0 ). siempre que el campo no haya sido declarado "not null". permitir valores nulos o tener un valor por defecto). excepto los declarados "identity". Por ejemplo. Sql Server insertará los valores por defecto. Los campos para los cuales no se ingresan valores en un "insert" tomarán los valores por defecto: . queremos que el valor por defecto del campo "autor" de la tabla "libros" sea "Desconocido" y el valor por defecto del campo "cantidad" sea "0": create table libros( codigo int identity. se puede ingresar un registro de la siguiente manera: insert into libros default values. Para ello utilizamos "default" al definir el campo. Si todos los campos de una tabla tienen valores predeterminados (ya sea por ser "identity". Entonces. Entonces. al visualizar la estructura de la tabla con "sp_columns" podemos entender lo que informa la columna "COLUMN_DEF".cantidad) values ('El gato con botas'.default.

cantidad from libros.cantidad.Columnas calculadas (operadores aritméticos y de concatenación) Aprendimos que los operadores son símbolos que permiten realizar distintos tipos de operaciones. división (/) y módulo (%) (el resto de dividir números enteros). Es posible obtener salidas en las cuales una columna sea el resultado de un cálculo y no un campo de una tabla.si está declarado explícitamente "not null". precio. no admite cláusula "default". Que un campo tenga valor por defecto no significa que no admita valores nulos.si tiene cláusula "default" (admita o no valores nulos).si permite valores nulos y no tiene cláusula "default". 3) aritméticos y 4) de concatenación. pero también podemos hacer que SQL Server realice el cálculo y lo incluya en una columna extra en la salida: select titulo. "00:00:00". Una tabla puede tener todos sus campos con valores por defecto.precio. Son: multiplicación (*). Un campo sólo puede tener un valor por defecto. suma (+) y resta (-). . si omitimos la parte de la fecha. Si queremos saber el monto total en dinero de un título podemos multiplicar el precio por la cantidad por cada título. el valor definido como predeterminado. almacenará "null". . 2) lógicos (lo veremos más adelante.si tiene el atributo "identity": el valor de inicio de la secuencia si es el primero o el siguiente valor de la secuencia.para campos de tipo fecha y hora. 22 . el valor predeterminado para la fecha es "190001-01" y si omitimos la parte de la hora. no hay valor por defecto. puede o no admitirlos. Los operadores aritméticos permiten realizar cálculos con valores numéricos. . Dijimos que SQL Server tiene 4 tipos de operadores: 1) relacionales o de comparación (los vimos). Si queremos saber el precio de cada libro con un 10% de descuento podemos incluir en la sentencia los siguientes cálculos: . así que causará un error y el "insert" no se ejecutará. no tiene valor "default" y no tiene el atributo "identity". . Si queremos ver los títulos. precio y cantidad de cada libro escribimos la siguiente sentencia: select titulo.. precio*cantidad from libros.

Alias Una manera de hacer más comprensible el resultado de una consulta consiste en cambiar los encabezados de las columnas. Para concatenar el título. Note que concatenamos además unos guiones para separar los campos.1). Ejemplo: select 5/0. . se coloca la palabra clave "as" seguido del texto del encabezado. Si el alias consta de una sola cadena las comillas no son necesarias.1) from libros. domicilio. Los operadores de concatenación: permite concatenar cadenas. pero si contiene más de una palabra. tenemos la tabla "agenda" con un campo "nombre" (entre otros) en el cual se almacena el nombre y apellido de nuestros amigos. es necesario colocarla entre comillas simples: select nombre as 'Nombre y apellido'.select titulo. Por ejemplo. para ello colocamos un alias de la siguiente manera: select nombre as NombreYApellido. queremos que al mostrar la información de dicha tabla aparezca como encabezado del campo "nombre" el texto "nombre y apellido".precio.telefono from agenda. el más (+). el autor y la editorial de cada libro usamos el operador de concatenación ("+"): select titulo+'-'+autor+'-'+editorial from libros. También podemos actualizar los datos empleando operadores aritméticos: update libros set precio=precio-(precio*0. Para reemplazar el nombre de un campo por otro. 23 .telefono from agenda. domicilio. Todas las operaciones matemáticas retornan "null" en caso de error. precio-(precio*0.

Entonces. que veremos más adelante.matemáticas: realizan operaciones numéricas. sirven para hacer más comprensible el resultado.de metadatos: informan sobre las bases de datos y los objetos. Ejemplo: select @@version. 2) escalares: toman un solo valor y retornan un único valor. son opcionales.de fecha y hora: operan con valores "datetime" y "smalldatetime". Las funciones de SQL Server no pueden ser modificadas. La palabra clave "as" es opcional en algunos casos. "nchar". Se pueden clasificar de la siguiente manera: 1) de agregado: realizan operaciones que combinan varios valores y retornan un único valor. numérico o de fecha y hora. Pueden agruparse de la siguiente manera: . . . "sum". En estos casos. 24 . . un "alias" se usa como nombre de un campo o de una expresión. . SQL Server ofrece varios tipos de funciones para realizar distintas operaciones. versión y tipo de procesador de SQL Server.de cursores: retornan información sobre el estado de un cursor. geométricas y trigonométricas. Reciben un parámetro de tipo fecha y hora y retornan un valor de cadena. Una función tiene un nombre. "nvarchar". retorna la fecha. "varchar".de cadena: operan con valores "char". También se puede crear un alias para columnas calculadas. . Son "count".Un alias puede contener hasta 128 caracteres. son obligatorios. en otros casos. . pero es conveniente usarla.de seguridad: devuelven información referente a usuarios y funciones.de configuración: retornan información referida a la configuración. "min" y "max". retorna un parámetro de salida y opcionalmente acepta parámetros de entrada. . las funciones definidas por el usuario si. "binary" y "varbinary" y devuelven un valor de cadena o numérico.Funciones Una función es un conjunto de sentencias que operan como una unidad lógica.

select str(-123. Ejemplo: select substring('Buenas tardes'. objetos y configuraciones del sistema. .Funciones para el manejo de cadenas Microsoft SQL Server tiene algunas funciones para trabajar con cadenas de caracteres. retorna '-123.texto e imagen: realizan operaciones con valor de entrada de tipo text o image y retornan información referente al mismo. El segundo y tercer argumento son opcionales y deben ser positivos.str(numero.estadísticas del sistema: retornan información referente al rendimiento del sistema.substring(cadena.7.8.del sistema: informan sobre opciones. retorna "tardes". empezando desde la posición especificada por el segundo argumento y de tantos caracteres de longitud como indica el tercer argumento. Ejemplo: select user_name(). Ejemplo: se convierte el valor numérico "123. Estas son algunas: . .longitud): devuelve una parte de la cadena especificada como primer argumento. especificando 7 de longitud y 3 decimales: select str(123. 3) de conjuntos de filas: retornan conjuntos de registros.456" a cadena.456.456.6)..inicio. Se pueden emplear las funciones del sistema en cualquier lugar en el que se permita una expresión en una sentencia "select". String significa cadena en inglés. el segundo la longitud del resultado (debe ser mayor o igual a la parte entera del número más el signo si lo tuviese) y el tercero.longitud.3).46'. . . 25 .7. el primer parámetro indica el valor numérico a convertir.3).cantidaddecimales): convierte números a caracteres. Estudiaremos algunas de ellas. la cantidad de decimales.

reemplazando la cantidad de caracteres indicada por el tercer argumento en la cadena que es primer parámetro.456).456. la longitud predeterminada es 10 y la cantidad de decimales 0 y se redondea a entero.longitud): retorna la cantidad (longitud) de caracteres de la cadena comenzando desde la izquierda.inicio. . retorna '123'.'opqrs'). retorna '123'. retorna "abopqrse". que significa longitud en inglés. Los argumentos numéricos deben ser positivos y menor o igual a la longitud de la primera cadena. Si el tercer argumento es mayor que la primera cadena.cadena2): inserta la cadena enviada como cuarto argumento. devuelve 4. "len" viene de length.3. Es decir.stuff(cadena1. caso contrario. devuelve asteriscos (*). Ejemplo: se convierte el valor numérico "123.2. Ejemplo: select len('Hola').456. retorna "null". Ejemplo: select char(65).len(cadena): retorna la longitud de la cadena enviada como argumento. Si el segundo parámetro es menor a la parte entera del número. select str(123. Stuff significa rellenar en inglés. coloca en la posición 2 la cadena "opqrs" y reemplaza 2 caracteres de la primer cadena. retorna "A". Ejemplo: select stuff('abcde'.char(x): retorna un caracter en código ASCII del entero enviado como argumento. primer caracter.cantidad. en la posición indicada en el segundo argumento. Ejemplo: select str(123. Ejemplo: . retorna "**".3). .2. . .Si no se colocan el segundo y tercer argumeno.left(cadena.456" a cadena: select str(123. se elimina hasta el primer carácter.3).

longitud): retorna la cantidad (longitud) de caracteres de la cadena comenzando desde la derecha. retorna " Hola".8).cadenareemplazar): retorna la cadena con todas las ocurrencias de la subcadena reemplazo por la subcadena a reemplazar. Ejemplo: select lower('HOLA ESTUDIAnte'). retorna "nos dias".sqlserverya.replace(cadena.select left('buenos dias'. Ejemplo: select right('buenos dias'. Ejemplo: select upper('HOLA ESTUDIAnte').reverse(cadena): devuelve la cadena invirtiendo el order de los caracteres. . Ejemplo: select ltrim(' retorna "Hola ".sqlserverya. Ejemplo: select reverse('Hola').cadenareemplazo.'w'). Ejemplo: select rtrim(' Hola ').right(cadena. -upper(cadena): retornan la cadena con todos los caracteres en mayúsculas. Hola '). .com'. Ejemplo: select replace('xxx. retorna "buenos d".com'. retorna "hola estudiante". último caracter.rtrim(cadena): retorna la cadena con los espacios de la derecha eliminados.8). -lower(cadena): retornan la cadena con todos los caracteres en minúsculas. . .'x'. Trim significa recortar. retorna "www. -ltrim(cadena): retorna la cadena con los espacios de la izquierda eliminados. lower significa reducir en inglés. retorna "aloH". .

retorna "HolaHolaHola".14). Si no la encuentra retorna 0.space(cantidad): retorna una cadena de espacios de longitud indicada por "cantidad". select charindex('or'. 'Jorge Luis Borges'). . retorna 0. 'Jorge Luis Borges'). retorna 0. retorna 2. retorna 13.3).'Jorge Luis Borges'.charindex(subcadena.cadena. que debe ser un valor positivo.patindex(patron. la búsqueda se inicia desde 0.replicate(cadena.'Jorge Luis Borges'. . retorna 2. Si no la encuentra. select charindex('or'. Si el tercer argumento no se coloca. . Ejemplo: select replicate ('Hola'. comenzando la búsqueda desde la posición indicada por "inicio". . select patindex('%or%'.inicio): devuelve la posición donde comienza la subcadena en la cadena. retorna 7. select charindex('or'.5). retorna 0. select patindex('%ar%'. Ejemplos: select charindex('or'.. 'Jorge Luis Borges'). retorna 0.cadena): devuelve la posición de comienzo (de la primera ocurrencia) del patrón especificado en la cadena enviada como segundo argumento.'Jorge Luis Borges').cantidad): repite una cadena la cantidad de veces especificada. 'Jorge Luis Borges'). Ejemplos: select patindex('%Luis%'. Ejemplo: select 'Hola'+space(1)+'que tal'.

Funciones matemáticas Las funciones matemáticas realizan operaciones con expresiones numéricas y retornan un resultado. retorna 12. Ejemplo: select ceiling(12. Ejemplo: select power(2. Se pueden emplear estas funciones enviando como argumento el nombre de un campo de tipo caracter. operan con tipos de datos numéricos. select 10%2.34). retorna 13. .retorna "Hola que tal". retorna 0. -floor(x): redondea hacia abajo el argumento "x". Ejemplo: select floor(12.34). Aquí presentamos algunas. Ejemplo: select abs(-20). retorna 20.y): retorna el valor de "x" elevado a la "y" potencia. retorna 8.%: %: devuelve el resto de una división. Microsoft SQL Server tiene algunas funciones para trabajar con números. Ejemplos: select 10%3. -ceiling(x): redondea hacia arriba el argumento "x". -abs(x): retorna el valor absoluto del argumento "x". retorna 1.3). 26 . . -power(x.

day (dia). es decir. Los valores para "partedefecha" pueden ser: year (año). -square(x): retorna el cuadrado del argumento.2). smallint o int.456. -sign(x): si el argumento es un valor positivo devuelve 1.456. Si "longitud" es positivo.460". trimestre.-1 si es negativo y si es 0. week (semana).datepart(partedefecha. retorna "123. retorna "100.1).-1). 0. retorna "123. 27 .000".-round(numero.000". redondea desde el primer valor entero (hacia la izquierda). redondea desde el segundo decimal. select round(123. el número es redondeado desde la parte entera según el valor de "longitud".Funciones para el uso de fechas y horas Microsoft SQL Server ofrece algunas funciones para trabajar con fechas y horas.456. . etc. si es negativo. hora. el número de decimales es redondeado según "longitud". es decir. el año. Ejemplos: . es decir.fecha): retorna la parte específica de una fecha.longitud): retorna un número redondeado a la longitud especificada. Ejemplo: select square(3). minute (minuto). SQL Server dispone de funciones trigonométricas que retornan radianes. Estas son algunas: . Ejemplo: select getdate(). redondea desde el segundo valor entero (hacia la izquierda). retorna "120.456. redondea desde el primer decimal. hour (hora).400". es decir. retorna 9. quarter (cuarto). día. "longitud" debe ser tinyint.getdate(): retorna la fecha y hora actuales. -srqt(x): devuelve la raiz cuadrada del valor enviado como argumento.-2). select round(123. Ejemplos: select round(123. second (segundo) y millisecond (milisegundo). month (mes). Se pueden emplear estas funciones enviando como argumento el nombre de un campo de tipo numérico. select round(123.

select datepart(month,getdate()); retorna el número de mes actual; select datepart(day,getdate()); retorna el día actual; select datepart(hour,getdate()); retorna la hora actual; - datename(partedefecha,fecha): retorna el nombre de una parte específica de una fecha. Los valores para "partedefecha" pueden ser los mismos que se explicaron anteriormente. Ejemplos: select datename(month,getdate()); retorna el nombre del mes actual; select datename(day,getdate()); - dateadd(partedelafecha,numero,fecha): agrega un intervalo a la fecha especificada, es decir, retorna una fecha adicionando a la fecha enviada como tercer argumento, el intervalo de tiempo indicado por el primer parámetro, tantas veces como lo indica el segundo parámetro. Los valores para el primer argumento pueden ser: year (año), quarter (cuarto), month (mes), day (dia), week (semana), hour (hora), minute (minuto), second (segundo) y millisecond (milisegundo). Ejemplos: select dateadd(day,3,'1980/11/02'); retorna "1980/11/05", agrega 3 días. select dateadd(month,3,'1980/11/02'); retorna "1981/02/02", agrega 3 meses. select dateadd(hour,2,'1980/11/02'); retorna "1980/02/02 2:00:00", agrega 2 horas. select dateadd(minute,16,'1980/11/02'); retorna "1980/02/02 00:16:00", agrega 16 minutos.

- datediff(partedelafecha,fecha1,fecha2): calcula el intervalo de tiempo (según el primer argumento) entre las 2 fechas. El resultado es un valor entero que corresponde a fecha2-fecha1. Los valores de "partedelafecha) pueden ser los mismos que se especificaron anteriormente. Ejemplos: select datediff (day,'2005/10/28','2006/10/28'); retorna 365 (días). select datediff(month,'2005/10/28','2006/11/29'); retorna 13 (meses). - day(fecha): retorna el día de la fecha especificada. Ejemplo: select day(getdate()); - month(fecha): retorna el mes de la fecha especificada. Ejemplo: select month(getdate()); - year(fecha): retorna el año de la fecha especificada. Ejemplo: select year(getdate()); Se pueden emplear estas funciones enviando como argumento el nombre de un campo de tipo datetime o smalldatetime. 28 - Ordenar registros (order by)

Podemos ordenar el resultado de un "select" para que los registros se muestren ordenados por algún campo, para ello usamos la cláusula "order by". La sintaxis básica es la siguiente: select *from NOMBRETABLA order by CAMPO; Por ejemplo, recuperamos los registros de la tabla "libros" ordenados por el título: select *from libros order by titulo; Aparecen los registros ordenados alfabéticamente por el campo especificado.

También podemos colocar el número de orden del campo por el que queremos que se ordene en lugar de su nombre, es decir, referenciar a los campos por su posición en la lista de selección. Por ejemplo, queremos el resultado del "select" ordenado por "precio": select titulo,autor,precio from libros order by 3; Por defecto, si no aclaramos en la sentencia, los ordena de manera ascendente (de menor a mayor). Podemos ordenarlos de mayor a menor, para ello agregamos la palabra clave "desc": select *libros order by editorial desc; También podemos ordenar por varios campos, por ejemplo, por "titulo" y "editorial": select *from libros order by titulo,editorial; Incluso, podemos ordenar en distintos sentidos, por ejemplo, por "titulo" en sentido ascendente y "editorial" en sentido descendente: select *from libros order by titulo asc, editorial desc; Debe aclararse al lado de cada campo, pues estas palabras claves afectan al campo inmediatamente anterior. Es posible ordenar por un campo que no se lista en la selección. Se permite ordenar por valores calculados o expresiones. La cláusula "order by" no puede emplearse para campos text, ntext e image. 29 - Operadores lógicos ( and - or - not)

Hasta el momento, hemos aprendido a establecer una condición con "where" utilizando operadores relacionales. Podemos establecer más de una condición con la cláusula "where", para ello aprenderemos los operadores lógicos. Son los siguientes: and, significa "y", or, significa "y/o", not, significa "no", invierte el resultado (), paréntesis

cumplen con las 2 condiciones. aquellos cuya editorial NO sea "Planeta": select *from libros where not editorial='Planeta'. las siguientes expresiones devuelven un resultado diferente: select*from libros where (autor='Borges') or (editorial='Paidos' and precio<20). El operador "not" invierte el resultado de la condición a la cual antecede. para que se evalúen como una sola expresión. indicamos que recupere los libros en los cuales el valor del campo "autor" sea "Borges" y/o el valor del campo "editorial" sea "Planeta". select *from libros . Cuando explicitamos varias condiciones con diferentes operadores lógicos (combinamos "and". no cumplen con la condición a la cual afecta el "NOT". con la segunda condición o con ambas condiciones. Queremos recuperar los libros que NO cumplan la condición dada. Queremos ver los libros cuyo autor sea "Borges" y/o cuya editorial sea "Planeta": select *from libros where autor='Borges' or editorial='Planeta'. Los registros recuperados con una sentencia que une 2 condiciones con el operador "or". Los registros recuperados en una sentencia que une 2 condiciones con el operador "and". necesitamos 2 condiciones: select *from libros where (autor='Borges') and (precio<=20). Los paréntesis se usan para encerrar condiciones. por ejemplo. seleccionará los registros que cumplan con la primera condición. Los registros recuperados en una sentencia en la cual aparece el operador "not". En la sentencia anterior usamos el operador "or". es decir. Si queremos recuperar todos los libros cuyo autor sea igual a "Borges" y cuyo precio no supere los 20 pesos.Los operadores lógicos se usan para combinar condiciones. cumplen 1 de las condiciones o ambas. además permite diferenciar las expresiones más claramente. "or") permite establecer el orden de prioridad de la evaluación. Por ejemplo.

Se emplea el operador "is null" para recuperar los registros en los cuales esté almacenado el valor "null" en un campo específico: select *from libros where editorial is null. El orden de prioridad de los operadores lógicos es el siguiente: "not" se aplica antes que "and" y "and" antes que "or". se puede emplear "is not null". Otro operador relacional es "between". se recomienda utilizarlos para evitar confusiones. "and" significa "y".Otros operadores relacionales (is null) Hemos aprendido los operadores relacionales "=" (igual). Hasta ahora. > (mayor). "<>" (distinto). si no se especifica un orden de evaluación mediante el uso de paréntesis. <> (distinto). >= (mayor o igual). indica que se cumpla una u otra condición (o ambas). <= (menor o igual). Entonces. evite las negativas ("is not null") porque con ellas se evalúan todos los registros y esto hace más lenta la recuperación de los datos. esto mostrará los registros con valores conocidos. para establecer más de una condición en un "where" es necesario emplear operadores lógicos. Para obtener los registros que no contiene "null". < (menor). Dijimos que no eran los únicos. Si bien los paréntesis no son obligatorios en todos los casos. ">=" (mayor o igual) y "<=" (menor o igual). is null/is not null (si un valor es NULL o no). "<" (menor). emplee condiciones de búsqueda positivas ("is null"). para recuperar de la tabla "libros" los libros con precio mayor o igual a 20 y menor o igual a 40. Existen otro operador relacional "is null". trabajan con intervalos de valores. "or" significa "y/o". por ello se recomienda usar los paréntesis.Otros operadores relacionales (between) Hemos visto los operadores relacionales: = (igual). indica que se cumplan ambas condiciones. Siempre que sea posible.where (autor='Borges' or editorial='Paidos') and (precio<20). ">" (mayor). usamos 2 condiciones unidas por el operador lógico "and": . "not" significa "no". El orden en el que se evalúan los operadores con igual nivel de precedencia es indefinido. 30 . indica que no se cumpla la condición especificada. 31 .

Entonces. Trabaja con intervalo de valores. recuperamos los libros cuyo precio NO se encuentre entre 20 y 35. Hasta ahora. Este operador se puede emplear con tipos de datos numéricos y money (en tales casos incluyen los valores mínimo y máximo) y tipos de datos fecha y hora (incluye sólo el valor mínimo).select *from libros where precio>=20 and precio<=40. es decir. "between" significa "entre". Podemos usar "between" y así simplificar la consulta: select *from libros where precio between 20 and 40. 2 cadenas). Por ejemplo. No tiene en cuenta los valores "null". Podemos usar "in" y simplificar la consulta: . es decir. En la siguiente sentencia usamos "in" para averiguar si el valor del campo autor está incluido en la lista de valores especificada (en este caso. emplee condiciones de búsqueda positivas ("between").Otros operadores relacionales (in) Se utiliza "in" para averiguar si el valor de un campo está incluido en una lista de valores especificada. Si agregamos el operador "not" antes de "between" el resultado se invierte. 32 . evite las negativas ("not between") porque hace más lenta la recuperación de los datos. Siempre que sea posible. se puede usar el operador "between" para reducir las condiciones "where". para recuperar los libros cuyo autor sea 'Paenza' o 'Borges' usábamos 2 condiciones: select *from libros where autor='Borges' or autor='Paenza'. se recuperan los registros que están fuera del intervalo especificado. los menores a 15 y mayores a 25: select *from libros where precio not between 20 and 35. Averiguamos si el valor de un campo dado (precio) está entre los valores mínimo y máximo especificados (20 y 40 respectivamente).

not like) Existe un operador relacional que se usa para realizar comparaciones exclusivamente de cadenas.Búsqueda de patrones (like . "like" y "not like". Imaginemos que tenemos registrados estos 2 libros: "El Aleph".select *from libros where autor in('Borges'. busca coincidencias de cadenas completas. Si queremos recuperar todos los libros de "Borges" y especificamos la siguiente condición: . Recuerde: siempre que sea posible. 33 . invertimos el resultado. realiza una búsqueda exacta.'Paenza'). sabemos recuperar los libros cuyo autor sea igual a la cadena "Borges": select *from libros where autor='Borges'. El operador igual ("=") nos permite comparar cadenas de caracteres. emplee condiciones de búsqueda positivas ("in"). es decir. evite las negativas ("not in") porque con ellas se evalún todos los registros y esto hace más lenta la recuperación de los datos.L. recuperamos los valores que no se encuentran (coindicen) con la lista de valores.'Paenza'). con "not" antecediendo la condición. pero al realizar la comparación. También podemos usar "in" anteponiendo "not": select *from libros where autor not in ('Borges'. Los valores "null" no se consideran. Para recuperar los libros cuyo autor no sea 'Paenza' ni 'Borges' usábamos: select *from libros where autor<>'Borges' and autor<>'Paenza'. Por ejemplo. "J. Borges". "Antologia poetica". Hemos realizado consultas utilizando operadores relacionales para comparar cadenas. "Borges". Empleando "in" averiguamos si el valor del campo está incluido en la lista de valores especificada.

El símbolo "%" (porcentaje) reemplaza cualquier cantidad de caracteres (incluyendo ningún caracter). Borges". Así como "%" reemplaza cualquier cantidad de caracteres. Por ejemplo. "like" y "not like" son operadores de comparación que señalan igualdad o diferencia. Para seleccionar todos los libros que NO comiencen con "M": select *from libros where titulo not like 'M%'. sólo aparecerá el primer registro. Otro caracter comodín es [] reemplaza cualquier carácter contenido en el conjunto especificado dentro de los corchetes.editorial from libros where editorial like '[P-S]%'. Note que el símbolo "%" ya no está al comienzo. también el operador "<>" (distinto) comparan cadenas de caracteres completas. podemos comparar trozos de cadenas de caracteres para realizar consultas.select *from libros where autor='Borges'. .L. Esto sucede porque el operador "=" (igual). Entonces. el guión bajo "_" reemplaza un caracter. ya que la cadena "Borges" no es igual a la cadena "J. Para comparar porciones de cadenas utilizamos los operadores "like" y "not like". Para recuperar todos los registros cuyo autor contenga la cadena "Borges" debemos tipear: select *from libros where autor like "%Borges%". cualquier cantidad de caracteres. queremos ver los libros de "Lewis Carroll" pero no recordamos si se escribe "Carroll" o "Carrolt". entonces tipeamos esta condición: select *from libros where autor like "%Carrol_".autor. es otro caracter comodín. con esto indicamos que el título debe tener como primera letra la "M" y luego. Para seleccionar todos los libros que comiencen con "M": select *from libros where titulo like 'M%'. Para seleccionar los libros cuya editorial comienza con las letras entre la "P" y la "S" usamos la siguiente sintaxis: select titulo. Es un caracter comodín.

. Queremos los libros que NO incluyen centavos en sus precios: select titulo.. like '%[[]%': busca cadenas que contengan el signo '['. like '%[_]%': busca cadenas que contengan el signo '_'. Para averiguar la cantidad sin necesidad de contarlos manualmente usamos la función "count()": . calcular sumas. nvarchar o datetime. queremos buscar todos los libros cuyo precio se encuentre entre 10.. debe incluirlo dentro de corchetes.. 'A[_]9%': busca cadenas que comiencen con 'A_9'.f.c. Imaginemos que nuestra tabla "libros" contiene muchos registros.00'.99: select titulo.editorial from libros where editorial like '[^PN]%'.c. varchar..Ejemplos: . "like" se emplea con tipos de datos char.a.f o i.. . .. El cuarto caracter comodín es [^] reemplaza cualquier caracter NO presente en el conjunto especificado dentro de los corchetes... .Contar registros (count) Existen en SQL Server funciones que nos permiten contar registros. Para búsquedas de caracteres comodines como literales. Si empleamos "like" con tipos de datos que no son caracteres. Estas funciones se denominan funciones de agregado y operan sobre un conjunto de valores (registros). like like like like '[a-cf-i]%': busca cadenas que comiencen con a..b. promedios.. no con datos individuales y devuelven un único valor. .00 y 19..g.. Para seleccionar los libros cuya editorial NO comienza con las letras "P" ni "N" tipeamos: select titulo. nchar.h o i. Por ejemplo. 'A[nm]%': busca cadenas que comiencen con 'An' o 'Am'. 34 . '[-acfi]%': busca cadenas que comiencen con -.. si busca: .autor.%'. like '%[%]%': busca cadenas que contengan el signo '%'.precio from libros where precio like '%. obtener valores máximos y mínimos. por ejemplo. . SQL Server convierte (si es posible) el tipo de dato a caracter.precio from libros where precio like '1_.

la diferencia es que "count_big" retorna un valor "bigint" y "count". 35 . sin considerar los repetidos. si en lugar de un asterisco colocamos como argumento el nombre de un campo. Averiguemos la cantidad de libros usando la función "count_big()": select count_big(*) from libros. "count(*)" cuenta registros. Queremos saber la cantidad de libros de la editorial "Planeta": select count(*) from libros where editorial='Planeta'. Contamos los libros de editorial "Planeta": . un "int". No es lo mismo.Contar registros (count_big) Retorna la cantidad de registros. incluyendo los valores nulos y duplicados. La función "count()" cuenta la cantidad de registros de una tabla. Es similar a la función "count(*)". incluyendo los que tienen valor nulo. "count_big(CAMPO)" retorna la cantidad de registros cuyo valor en el campo especificado entre paréntesis no es nulo. También podemos utilizar esta función junto con la cláusula "where" para una consulta más específica. Para contar los registros que tienen precio (sin tener en cuenta los que tienen valor nulo). "count_big(distinct CAMPO)" retorna la cantidad de registros cuyo valor en el campo especificado no es nulo. Note que "count(*)" retorna la cantidad de registros de una tabla (incluyendo los que tienen valor "null") mientras que "count(precio)" retorna la cantidad de registros en los cuales el campo "precio" no es nulo.select count(*) from libros. se contabilizan los registros cuyo valor en ese campo NO es nulo. "count_big(*)" cuenta la cantidad de registros de una tabla. Note que incluye todos los libros aunque tengan valor nulo en algún campo. usamos la función "count()" y en los paréntesis colocamos el nombre del campo que necesitamos contar: select count(precio) from libros.

. . Todas estas funciones retornan "null" si ningún registro cumple con la condición del "where". La función "sum()" retorna la suma de los valores que contiene el campo especificado. Ya hemos aprendido una de ellas.select count_big(*) from libros where editorial='Planeta'.max . promedios. "count()".sum y avg: sólo en campos de tipo numérico. Contamos las editoriales (sin repetir): select count_big(distinct editorial) from libros. Contamos los registros que tienen precio (sin tener en cuenta los que tienen valor nulo): select count_big(precio) from libros. El tipo de dato del campo determina las funciones que se pueden emplear con ellas. excepto "count" que en tal caso retorna cero. debemos sumar todos los valores del campo "cantidad": select sum(cantidad) from libros.sum . obtener valores máximos y mínimos. Si queremos saber la cantidad total de libros que tenemos disponibles para la venta.Funciones de agrupamiento (count . 36 . Las relaciones entre las funciones de agrupamiento y los tipos de datos es la siguiente: . Se pueden usar en una instrucción "select" y combinarlas con la cláusula "group by".min y max: con cualquier tipo de dato. las funciones de agregado.count: se puede emplear con cualquier tipo de dato.avg) Hemos visto que SQL Server tiene funciones que nos permiten contar registros. calcular sumas.min . . veamos otras.

incluidos los que contienen "null". y repetirla con cada valor de "editorial": select count(*) from libros where editorial='Emece'. Entonces. Queremos saber el promedio del precio de los libros referentes a "PHP": select avg(precio) from libros where titulo like '%PHP%'. combinando las funciones de agregado con la cláusula "group by". "count(*)" cuenta todos los registros. el resultado devuelve un total de 16 filas porque no considera aquellos con valor nulo. 37 . Queremos saber la cantidad de libros de cada editorial. Todas las funciones de agregado. Queremos saber cuál es el mayor precio de todos los libros: select max(precio) from libros.Para averiguar el valor máximo o mínimo de un campo usamos las funciones "max()" y "min()" respectivamente. que agrupa registros para consultas detalladas. Podemos generar valores de resumen para un solo campo. porque operan sobre conjuntos de registros. Las funciones de agregado solas producen un valor de resumen para todos los registros de un campo. Tratamiento de los valores nulos: Si realiza una consulta con la función "count" de un campo que contiene 18 registros. podemos tipear la siguiente sentencia: select count(*) from libros where editorial='Planeta'. 2 de los cuales contienen valor nulo. dentro del paréntesis de la función colocamos el nombre del campo del cuál queremos el máximo valor. . no con datos individuales.Agrupar registros (group by) Hemos aprendido que las funciones de agregado permiten realizar varios cálculos operando con conjuntos de registros. Ahora podemos entender porque estas funciones se denominan "funciones de agrupamiento". excluye los valores nulos de los campos. excepto "count(*)". La función "avg()" retorna el valor promedio de los valores del campo especificado.

para saber la cantidad de libros que tenemos de cada editorial.. También se puede agrupar por más de un campo. Recuerde la diferencia de los valores que retorna la función "count()" cuando enviamos como argumento un asterisco o el nombre de un campo: en el primer caso cuenta todos los registros incluyendo los que tienen valor nulo. Como resultado aparecen los nombres de las editoriales y la cantidad de registros de cada una. sin contar los que tienen precio nulo. luego del "group by" se listan los campos. en el segundo. La instrucción anterior solicita que muestre el nombre de la editorial y cuente la cantidad agrupando los registros por el campo "editorial". CAMPO2. Los valores nulos se procesan como otro grupo. . select CAMPO1. Pero hay otra manera. agregamos "group by" (que agrupa registros) y el campo por el que deseamos que se realice el agrupamiento. . Como resultado aparecen los nombres de las editoriales y la cantidad de registros para cada valor del campo. Para obtener la cantidad libros con precio no nulo.CAMPO2. count(*) from libros group by editorial. los registros en los cuales el campo especificado es no nulo. de cada editorial utilizamos la función "count()" enviándole como argumento el campo "precio".. separados por comas. en tal caso. utilizando la cláusula "group by": select editorial. Entonces. la sintaxis básica es la siguiente: select CAMPO. Todos los campos que se especifican en la cláusula "group by" deben estar en la lista de selección. FUNCIONDEAGREGADO from NOMBRETABLA group by CAMPO1. FUNCIONDEAGREGADO from NOMBRETABLA group by CAMPO. utilizamos la función "count()".select count(*) from libros where editorial='Paidos'. también colocamos el nombre del campo a recuperar. count(precio) from libros group by editorial. agregamos "group by" y el campo por el que deseamos que se realice el agrupamiento (editorial): select editorial.

38 . Para saber el máximo y mínimo valor de los libros agrupados por editorial: select editorial. Vamos a contar y agrupar por editorial considerando solamente los libros cuyo precio sea menor a 30 pesos: select editorial. Note que las editoriales que no tienen libros que cumplan la condición. Para calcular el promedio del valor de los libros agrupados por editorial: select editorial. incluso los que devuelven cero o "null" en la columna de agregado. debemos emplear la palabra clave "all" al lado de "group by": select editorial. Si incluye una cláusula "where". Es posible limitar la consulta con "where".Seleccionar grupos (having) . avg(precio) from libros group by editorial. max(precio) as mayor. Para que aparezcan todos los valores de editorial. count(*) from libros where precio<30 group by all editorial. sum(precio) from libros group by editorial. count(*) from libros where precio<30 group by editorial.Para conocer el total en dinero de los libros agrupados por editorial: select editorial. usamos "group by" para organizar registros en grupos y obtener un resumen de dichos grupos. SQL Server produce una columna de valores por cada grupo. no aparecen en la salida. min(precio) as menor from libros group by editorial. devolviendo filas por cada grupo especificado. sólo se agrupan los registros que cumplen las condiciones. Entonces.

para seleccionar ciertas filas retornadas por la cláusula "group by". count(*) from libros group by editorial. Si queremos saber la cantidad de libros agrupados por editorial pero considerando sólo algunos grupos. la segunda establece condiciones para la selección de registros de una salida "group by". Ambas devuelven el mismo resultado. por ejemplo. Se utiliza "having". En algunos casos es posible confundir las cláusulas "where" y "having". La segunda. Queremos el promedio de los precios de los libros agrupados por editorial. la primera establece condiciones para la selección de registros de un "select". avg(precio) from libros group by editorial having avg(precio)>25. los que devuelvan un valor mayor a 2. la cláusula "having" permite seleccionar (o rechazar) un grupo de registros. Queremos contar los registros agrupados por editorial sin tener en cuenta a la editorial "Planeta". los agrupa para contarlos y finalmente rechaza fila con la cuenta correspondiente a la editorial "Planeta". selecciona todos los registros. . selecciona todos los registros rechazando los de editorial "Planeta" y luego los agrupa para contarlos. count(*) from libros where editorial<>'Planeta' group by editorial. No debemos confundir la cláusula "where" con la cláusula "having". usamos la siguiente instrucción: select editorial. pero solamente de aquellos grupos cuyo promedio supere los 25 pesos: select editorial. select editorial. pero son diferentes. Si queremos saber la cantidad de libros agrupados por editorial usamos la siguiente instrucción ya aprendida: select editorial. count(*) from libros group by editorial having editorial<>'Planeta'. La primera. Veamos otros ejemplos.Así como la cláusula "where" permite seleccionar (o rechazar) registros individuales. count(*) from libros group by editorial having count(*)>2. Analicemos las siguientes sentencias: select editorial. seguido de la condición de búsqueda.

sin considerar los que tienen precio nulo. sexo. max(precio) as 'mayor' from libros group by editorial having min(precio)<100 and min(precio)>30 order by editorial. selecciona los registros rechazando los que no cumplan con la condición dada en "where". esto no puede hacerlo la cláusula "where". Por ejemplo queremos el promedio de los precios agrupados por editorial. de aquellas editoriales que tienen más de 2 libros: select editorial. or. Se emplea la cláusula "having" con funciones de agrupamiento. usamos la claúsula "having" para restringir las filas que devuelve una salida "group by". sin considerar la editorial "Planeta": select editorial. Podemos encontrar el mayor valor de los libros agrupados y ordenados por editorial y seleccionar las filas que tengan un valor menor a 100 y mayor a 30: select editorial. count(*) from libros where precio is not null group by editorial having editorial<>'Planeta'. Va siempre después de la cláusula "group by" y antes de la cláusula "order by" si la hubiere. 39 . Tenemos la tabla "visitantes" con los siguientes campos: nombre. tiene que combinarlas con operadores lógicos (and. El operador "rollup" resume valores de grupos. agrupados por editorial.Veamos otros ejemplos combinando "where" y "having". domicilio. avg(precio) from libros group by editorial having count(*) > 2. representan los valores de resumen de la precedente. ciudad. not). edad. telefono.Modificador del group by (with rollup) Podemos combinar "group by" con los operadores "rollup" y "cube" para generar valores de resumen a la salida. luego los agrupa por "editorial" y finalmente rechaza los grupos que no cumplan con la condición dada en el "having". Entonces. Aquí. montocompra. Cuando utilice varias condiciones. Queremos la cantidad de libros. . En una cláusula "having" puede haber hasta 128 condiciones.

con la columna correspondiente al segundo campo por el que se agrupa ("sexo" en este ejemplo) conteniendo "null". "ciudad" y "sexo": select ciudad. La salida muestra los totales por ciudad y sexo y produce tantas filas extras como valores existen del primer campo por el que se agrupa ("ciudad" en este caso). mostrando los totales para cada valor.sexo. y 1 fila extra mostrando el total de todos los visitantes (con las columnas correspondientes a ambos campos conteniendo "null"). Es posible incluir varias funciones de agrupamiento. La consulta anterior retorna los registros agrupados por ciudad y una fila extra en la que la primera columna contiene "null" y la columna con la cantidad muestra la cantidad total. por ejemplo. Si agrupamos por 2 campos. debemos realizar otra consulta: select count(*) as total from visitantes. Esta consulta muestra el total de visitantes agrupados por ciudad. La cláusula "group by" permite agregar el modificador "with rollup".count(*) as cantidad from visitantes group by ciudad with rollup. pero si queremos además la cantidad total de visitantes.count(*) as cantidad from visitantes group by ciudad.Si necesitamos la cantidad de visitantes por ciudad empleamos la siguiente sentencia: select ciudad.sexo with rollup. seteados a "null".count(*) as cantidad from visitantes group by ciudad.sexo. . Para obtener ambos resultados en una sola consulta podemos usar "with rollup" que nos devolverá ambas salidas en una sola consulta: select ciudad. Es decir. el cual agrega registros extras al resultado de una consulta. Con "rollup" se puede agrupar hasta por 10 campos. count(*) as cantidad. queremos la cantidad de visitantes y la suma de sus compras agrupados por ciudad y sexo: select ciudad. que muestran operaciones de resumen. aparece una fila extra con el/ los campos que no se consideran. por cada agrupación.

Si se agrupa por 2 campos SQL Server genera tantas filas extras como valores existen del primer campo (con el segundo campo seteado a "null") y una fila extra con ambos campos conteniendo "null". que agrega filas extras mostrando resultados de resumen por cada grupo y subgrupo.estadocivil y seccion (sexo seteado a "null").sexo with rollup.estadocivil. "rollup" es un modificador para "group by" que agrega filas extras mostrando resultados de resumen de los subgrupos. Si se emplea "cube": select sexo.total (todos los campos seteados a "null").seccion. Entonces. SQL Server genera varias filas extras con información de resumen para los siguientes subgrupos: . . Con "rollup" se puede emplear "where" y "having". count(*) from empleados group by sexo.sexo y seccion (estadocivil seteado a "null"). count(*) from empleados group by sexo.seccion with cube.sexo (estadocivil y seccion seteados a "null") y .sum(montocompra) as total from visitantes group by ciudad.Modificador del group by (with cube) Hemos aprendido el modificador "rollup".seccion with rollup. tenemos una tabla llamada "empleados" que contiene. retorna más filas extras además de las anteriores: .estadocivil. 40 . entre otros.estadocivil. . pero no es compatible con "all". Por ejemplo. . los campos "sexo".estadocivil. "estadocivil" y "seccion". Si se agrupa por esos tres campos (en ese orden) y se emplea "rollup": select sexo.seccion.sexo y estadocivil (seccion seteado a "null").

41 . permite diferenciar si los valores "null" que aparecen en el resultado son valores nulos de las tablas o si son una fila generada por los operadores "rollup" o "cube". Si tenemos una tabla "visitantes" con los siguientes registros almacenados: Nombre sexo ------------------------------Susana Molina f Marcela Mercado f Roberto Perez f Alberto Garcia m Teresa Garcia f ciudad Cordoba Cordoba null Cordoba Alta Gracia y contamos la cantidad agrupando por ciudad (note que hay un valor nulo en dicho campo) empleando "rollup": select ciudad. Con esta función aparece una nueva columna en la salida. retorna el valor 1 para indicar que la fila representa los valores de resumen de "rollup" o "cube" y el valor 0 para representar los valores de campo. Es decir. Es decir.Función grouping La función "grouping" se emplea con los operadores "rollup" y "cube" para distinguir los valores de detalle y de resumen en el resultado.seccion (sexo y estadocivil seteados a "null") y . Con "cube" se puede emplear "where" y "having". aparece la siguiente salida: ciudad ------------------------cantidad . Sólo se puede emplear la función "grouping" en los campos que aparecen en la cláusula "group by". Se pueden colocar hasta 10 campos en el "group by". una por cada "grouping". pero no es compatible con "all".estadocivil (sexo y seccion seteados a "null"). count(*) as cantidad from visitantes group by ciudad with rollup.. "cube" genera filas de resumen de subgrupos para todas las combinaciones posibles de los valores de los campos por los que agrupamos.

min(). Se usa con las funciones de agrupamiento: avg(). en la cual "null" es un valor del campo.Cláusulas compute y compute by Las cláusulas "compute" y "compute by" generan totales que aparecen en columnas extras al final del resultado. utilice la función "grouping" para distinguir los valores de detalle y de resumen en el resultado. contiene en dicha columna el valor 0. sum(). Para diferenciarla empleamos "grouping": select ciudad. que indica que el valor "null" es un valor del campo "ciudad". Produce filas de detalle y un valor único para una columna. count(). max(). indicando que es la fila de resumen generada por "rollup". 42 . aparece la siguiente salida: ciudad cantidad --------------------------------------NULL 1 Alta Gracia 1 Cordoba 3 NULL 5 resumen 0 0 0 1 La última fila contiene en la columna generada por "grouping" el valor 1. count(*) as cantidad. La sintaxis básica y general es la siguiente: select CAMPOS from TABLA . si emplea los operadores "rollup" y "cube" y los campos por los cuales agrupa admiten valores nulos. grouping(ciudad) as resumen from visitantes group by ciudad with rollup. Entonces. pero no es posible distinguirla de la primera fila. la primera fila.NULL Alta Gracia 1 Cordoba NULL 1 3 5 La última fila es la de resumen generada por "rollup".

Produce la misma salida que las siguientes 2 sentencias: select *from visitantes. Se generan filas de detalle y varios valores de resumen cuando cambian los valores del campo. Si la cláusula "order by" tiene los siguientes campos: . select avg(montocompra) from visitantes.ciudad compute count(provincia) by provincia.c.compute FUNCION(CAMPO)..ciudad. select nombre. Para ver todos los datos de los visitantes y el promedio del monto de compra de nuestra tabla "visitantes": select *from visitantes compute avg(montocompra).ciudad..b. Los campos que aparecen luego de la cláusula "compute by" DEBEN ser idénticos a un subconjunto de los campos que aparecen después de "order by" y estar en el mismo orden.provincia from visitantes order by provincia.ciudad.ciudad.provincia from visitantes order by provincia compute count(provincia) by provincia. Listando varios campos luego del "by" corta un grupo en subgrupos y aplica la función de agregado en cada nivel de agrupamiento: select nombre..montocompra from visitantes compute avg(edad).sum(montocompra). El campo que se coloque en la cláusula "compute" debe estar incluida en la lista de campos del "select".. En una misma instrucción se pueden colocar varias cláusulas "compute": select edad. order by a. Con "compute by" se DEBE usar también la cláusula "order by" y los campos que se incluyan luego de "by" deben estar en el "order by". la cláusula "compute by" puede incluir los siguientes subconjuntos de campos: . "Compute by" genera cortes de control y subtotales.

by a...b. compute . 43 . Los tipos de datos ntext. sum(montocompra) compute avg(montocompra). podemos utilizar la sentencia siguiente: select distinct autor from libros where autor is not null. Por ejemplo..ciudad compute avg(edad).count(provincia) by provincia... queremos conocer todos los autores de los cuales tenemos libros. by a.. si utilizamos esta sentencia: select autor from libros.ciudad..... no queremos incluir "null" en la lista. .. o . Aparecen repetidos. compute . compute .Registros duplicados (distinct) Con la cláusula "distinct" se especifica que los registros con ciertos datos duplicados sean obviadas en el resultado. En una misma instrucción se pueden colocar varias cláusulas "compute" combinadas con varias cláusulas "compute by": select *from visitantes order by provincia. es decir. by a..... text e image no se pueden incluir en una cláusula "compute" o "compute by".b.c.. o .. El resultado de la consulta anterior muestra el promedio de la compra y la cantidad al final de cada subgrupo de provincia y ciudad (compute by) y el promedio de las edades y el total del monto de compras de todos (compute). Note que en los tres casos anteriores aparece "null" como un valor para "autor"· Si sólo queremos la lista de autores conocidos. Para obtener la lista de autores sin repetición usamos: select distinct autor from libros... También podemos tipear: select autor from libros group by autor.

Para mostrar los títulos y editoriales de los libros sin repetir títulos ni editoriales. La cláusula "distinct" afecta a todos los campos presentados. sin considerar el valor "null" usamos: select count(distinct autor) from libros. no incluirá los valores "null" pero si los repetidos: select count(autor) from libros. aparecen títulos iguales pero con editorial diferente. usamos: select distinct titulo. Esta sentencia cuenta los registros que tienen autor. Podemos combinarla con "where".Cláusula top La palabra clave "top" se emplea para obtener sólo una cantidad limitada de registros. Note que los registros no están duplicados. 44 .Para contar los distintos autores. count(distinct autor) from libros group by editorial. También puede utilizarse con "group by" para contar los diferentes autores por editorial: select editorial. Entonces. los primeros n registros de una consulta. La palabra clave "distinct" no está permitida con las cláusulas "compute" y "compute by".editorial from libros order by titulo. "distinct" elimina registros duplicados. cada registro es diferente. Por ejemplo. Con la siguiente consulta obtenemos todos los datos de los primeros 2 libros de la tabla: . queremos conocer los distintos autores de la editorial "Planeta": select distinct autor from libros where editorial='Planeta'. Note que si contamos los autores sin "distinct".

. Se puede combinar con "order by": select top 3 titulo.autor from libros order by autor. etc. el número n) tiene un valor repetido en el registro n+1. 45 . Los valores no se repiten ni pueden ser nulos. y el n+2. Para un valor del campo clave existe solamente 1 registro. ordenados por autor. SQL Server muestra todos los registros. si el valor del campo por el cual se ordena del último registro retornado (el número n) está repetido en los siguientes registros (es decir. en caso que el registro número 4 (y los posteriores). Esta cláusula permite incluir en la seleccion.). Es decir.horallegada datetime.tipo char (1). 'a'= auto. el n+1 tiene el mismo valor que n. . que el último registro retornado si el último registro retornado (es decir. En la consulta anterior solicitamos los títulos y autores de los 3 primeros libros.Clave primaria compuesta Las claves primarias pueden ser simples. también aparecerán en la selección. luego del "select" se coloca "top" seguido de un número entero positivo y luego se continúa con la consulta. Veamos un ejemplo: select top 3 with ties *from libros order by autor. lo incluye en la selección. tengan el mismo valor en "autor" que el último registro retornado (número 3). Existe una playa de estacionamiento que almacena cada día los datos de los vehículos que ingresan en la tabla llamada "vehiculos" con los siguientes campos: . 'm'=moto. Es decir.patente char(6) not null. Si colocamos un valor para "top" que supera la cantidad de registros de la tabla. más de un campo. todos los registros que tengan el mismo valor del campo por el que se ordena. . Esta consulta solicita el retorno de los primeros 3 registros. Cuando se combina con "order by" es posible emplear también la cláusula "with ties". Recordemos que una clave primaria identifica 1 solo registro en una tabla. formadas por un solo campo o compuestas.select top 2 *from libros.

por si sólo cumple con la condición para ser clave. tampoco podemos usar la hora de entrada porque varios autos pueden ingresar a una misma hora. muestra un mensaje y la inserción no se realiza.horasalida datetime. Tampoco sirven los otros campos. la patente junto con la hora de llegada. horasalida datetime. Entonces. 'm'=moto horallegada datetime. debemos usar 2 campos.Clave primaria compuesta Las claves primarias pueden ser simples. SQL Server controla que los valores para los campos establecidos como clave primaria no estén repetidos en la tabla. es decir formada por más de un campo. Lo mismo sucede si realizamos una actualización. Usamos 2 campos como clave.. Recordemos que una clave primaria identifica 1 solo registro en una tabla. tipo char(1). En este ejemplo. Como ningún campo.horallegada) ). es decir. pero siempre será a distinta hora. Definimos una clave compuesta cuando ningún campo por si solo cumple con la condición para ser clave. un auto puede ingresar varias veces en un día a la playa. No podemos usar solamente la patente porque un mismo auto puede ingresar más de una vez en el día a la playa. Para un valor del campo clave existe solamente 1 registro. si estuviesen repetidos. Los valores no se repiten ni pueden ser nulos. Para establecer más de un campo como clave primaria usamos la siguiente sintaxis: create table vehiculos( patente char(6) not null.--'a'=auto. . más de un campo. si un solo campo no identifica unívocamente un registro podemos definir una clave primaria compuesta. así identificamos unívocamente cada registro. formadas por un solo campo o compuestas. primary key(patente. 45 . Necesitamos definir una clave primaria para una tabla con los datos descriptos arriba. Nombramos los campos que formarán parte de la clave separados por comas. debe identificar un solo registro. el valor no puede repetirse. Al ingresar los registros.

debemos usar 2 campos. 'm'=moto horallegada datetime. horallegada datetime. tipo char (1). Lo mismo sucede si realizamos una actualización. así identificamos unívocamente cada registro.--'a'=auto. Al ingresar los registros. por si sólo cumple con la condición para ser clave. el valor no puede repetirse. Para establecer más de un campo como clave primaria usamos la siguiente sintaxis: create table vehiculos( patente char(6) not null. horasalida datetime. Tampoco sirven los otros campos. es decir. muestra un mensaje y la inserción no se realiza. Necesitamos definir una clave primaria para una tabla con los datos descriptos arriba. En este ejemplo. Definimos una clave compuesta cuando ningún campo por si solo cumple con la condición para ser clave. la patente junto con la hora de llegada. No podemos usar solamente la patente porque un mismo auto puede ingresar más de una vez en el día a la playa.horallegada) ).Existe una playa de estacionamiento que almacena cada día los datos de los vehículos que ingresan en la tabla llamada "vehiculos" con los siguientes campos: patente char(6) not null. Usamos 2 campos como clave. 'm'=moto. Nombramos los campos que formarán parte de la clave separados por comas. si un solo campo no identifica unívocamente un registro podemos definir una clave primaria compuesta.Integridad de los datos . SQL Server controla que los valores para los campos establecidos como clave primaria no estén repetidos en la tabla. si estuviesen repetidos. Como ningún campo. 46 . es decir formada por más de un campo. tipo char(1). tampoco podemos usar la hora de entrada porque varios autos pueden ingresar a una misma hora. primary key(patente. pero siempre será a distinta hora. un auto puede ingresar varias veces en un día a la playa. horasalida datetime. debe identificar un solo registro. Entonces. 'a'= auto.

. Anteriormente. nos muestra información acerca de las restricciones de dicha tabla. las veremos ordenadamente y al finalizar haremos un resumen de las mismas. .). ). tener en cuenta la integridad de los datos. Hasta el momento. asegurando que los valores ingresados sean válidos y que las relaciones entre las tablas se mantenga. el valor por defecto. 47 . SQL Server ofrece más alternativas. SQL Server creaba automáticamente una restricción "default" para ese campo de esa tabla. . Se aconseja crear las tablas y luego agregar las restricciones. Cuando se agrega una restricción a una tabla. modificar y eliminar las restricciones sin eliminar la tabla y volver a crearla.Restricción default La restricción "default" especifica un valor por defecto para un campo cuando no se inserta explícitamente en un comando "insert".Es importante. Las restricciones (constraints) son un método para mantener la integridad de los datos. para restringir y validar los datos. Pueden definirse al crear la tabla ("create table") o agregarse a una tabla existente (empleando "alter table") y se pueden aplicar a un campo o a varios. numéricos. Se pueden crear. autor varchar(30) default 'Desconocido'.. El procedimiento almacenado del sistema "sp_helpconstraint" junto al nombre de la tabla. Se establecen a los campos y las tablas.. al diseñar una base de datos y las tablas que contiene. Hay varios tipos de restricciones. hemos controlado y restringido la entrada de valores a un campo mediante el tipo de dato que le definimos (cadena. la aceptación o no de valores nulos.. etc. además de las aprendidas. para establecer un valor por defecto para un campo empleábamos la cláusula "default" al crear la tabla. Cada vez que establecíamos un valor por defecto para un campo de una tabla. esto significa que la información almacenada en las tablas debe ser válida. También hemos asegurado que cada registro de una tabla sea único definiendo una clave primaria y empleando la propiedad identity. coherente y exacta. por ejemplo: create table libros( . Comenzamos por las restricciones. SQL Server comprueba los datos existentes.

En la sentencia siguiente agregamos una restricción "default" al campo autor de la tabla existente "libros".Dicha restricción. podemos establecer que el valor por defecto de un campo de tipo datetime sea "getdate()".constraint_type: el tipo de restricción y sobre qué campo está establecida (DEFAULT on column autor). . Una tabla puede tener varias restricciones "default" para sus distintos campos.status_enabled y status_for_replication: no tienen valores para este tipo de restricción. a la cual no le dábamos un nombre. Por convención. .delete_action y update_action: no tienen valores para este tipo de restricción. se puede establecer uno por campo y no se puede emplear junto con la propiedad "identity". Podemos ver información referente a las restriciones de una tabla con el procedimiento almacenado "sp_helpcontraint": sp_helpconstraint libros. cuando demos el nombre a las restricciones "default" emplearemos un formato similar al que le da SQL Server: "DF_NOMBRETABLA_NOMBRECAMPO". . Solamente se permite una restricción "default" por campo y no se puede emplear junto con la propiedad "identity". . el nombre del campo y letras y números aleatorios. recibía un nombre dado por SQL Server que consiste "DF" (por default). 48 . Podemos agregar una restricción "default" a una tabla existente con la sintaxis básica siguiente: alter table NOMBRETABLA add constraint NOMBRECONSTRAINT default VALORPORDEFECTO for CAMPO. La restricción "default" acepta valores tomados de funciones del sistema. la restricción "default" especifica un valor por defecto para un campo cuando no se inserta explícitamente en un "insert".constraint_name: el nombre de la restricción (DF_libros_autor).constraint_keys: el valor por defecto (Desconocido).Restricción check . aparecen varias columnas con la siguiente información: . Entonces. por ejemplo. que almacena el valor "Desconocido" en dicho campo si no ingresamos un valor en un "insert": alter table libros add constraint DF_libros_autor default 'Desconocido' for autor. seguido del nombre de la tabla.

La sintaxis básica es la siguiente: alter table NOMBRETABLA add constraint NOMBRECONSTRAINT check CONDICION.99 y 999. Los campos correspondientes a los precios (minorista y mayorista) se definen de tipo decimal(5. actúa en inserciones y actualizaciones. titulo. evitando que se ingresen valores inapropiados.99. es decir. la restricción no se puede establecer. Un campo puede tener varias restricciones restricciones "check" y una restricción "check" puede incluir varios campos.. Si la tabla contiene registros que no cumplen con la restricción que se va a establecer. aceptan valores entre -999. check (CAMPO like '[A-Z][A-Z][0-9][0-9]'). podemos controlar que el precio mayorista no sea mayor al precio minorista: alter table libros add constraint CK_libros_preciominmay check (preciomay<=preciomin). hasta que todos los registros cumplan con dicha restricción. 2 letras y 2 dígitos: . Este tipo de restricción verifica los datos cada vez que se ejecuta una sentencia "insert" o "update". Podemos controlar que no se ingresen valores negativos para dichos campos agregando una restricción "check": alter table libros add constraint CK_libros_precio_positivo check (preciomin>=0 and preciomay>=0). autor. es decir. . del campo y alguna palabra con la cual podamos identificar fácilmente de qué se trata la restricción. seguido del nombre de la tabla. editorial. Por convención. por si tenemos varias restricciones "check" para el mismo campo. Las condiciones para restricciones "check" también pueden pueden incluir un patrón o una lista de valores. Por ejemplo establecer que cierto campo conste de 4 caracteres.La restricción "check" especifica los valores que acepta un campo. La condición puede hacer referencia a otros campos de la misma tabla.2). Por ejemplo. Trabajamos con la tabla "libros" de una librería que tiene los siguientes campos: codigo. cuando demos el nombre a las restricciones "check" seguiremos la misma estructura: comenzamos con "CK".. preciomin (que indica el precio para los minoristas) y preciomay (que indica el precio para los mayoristas).

SQL Server no lo permite. Podemos hacerlo cuando agregamos la restricción "check" a una tabla para que SQL Server acepte los valores ya almacenados que infringen la restricción.nocheck) Sabemos que si agregamos una restricción a una tabla que contiene datos.. si no especificamos. la sintaxis básica es la siguiente: alter table TABLA with nocheck add constraint NOMBRERESTRICCION check (CONDICION)..O establecer que cierto campo asuma sólo los valores que se listan: . Para ello debemos incluir la opción "with nocheck" en la instrucción "alter table": alter table libros with nocheck add constraint CK_libros_precio check (precio>=0). 49 . la restricción no se establecece.'viernes')). SQL Server los controla para asegurarse que cumplen con la condición de la restricción. "null" es un valor aceptado aunque no esté incluido en la condición de restricción. Si intentamos establecer una restricción "check" para un campo que entra en conflicto con otra restricción "check" establecida al mismo campo. pero al intentar ingresar un registro. si algún registro no la cumple. aparece un mensaje de error.'miercoles'. check (CAMPO in ('lunes'. . Si un campo permite valores nulos. La restricción no se aplica en los datos existentes. la opción es "with check". No se puede aplicar esta restricción junto con la propiedad "identity". para evitar la comprobación de datos existentes al crear la restricción. Pero si establecemos una restricción "check" para un campo que entra en conflicto con una restricción "default" establecida para el mismo campo. Entonces. pero si intentamos ingresar un nuevo valor que no cumpla la restricción. SQL Server lo permite. SQL Server no lo permite.Deshabilitar restricciones (with check . Por defecto. Es posible deshabilitar esta comprobación en caso de restricciones "check".

. las cláusulas "check" y "nocheck" permiten habilitar o deshabilitar restricciones "check" (también las restricciones "foreign key" que veremos más adelante). la sintaxis básica es: alter table NOMBRETABLA OPCIONdeRESTRICCION constraint NOMBRERESTRICCION. Entonces.Restricción primary key Hemos visto las restricciones que se aplican a los campos. que aseguran valores únicos para cada registro.También podemos deshabilitar las restricciones para agregar o actualizar datos sin comprobarla: alter table libros nocheck constraint CK_libros_precio. Ahora veremos las restricciones que se aplican a las tablas. Anteriormente. 50 . Para saber si una restricción está habilitada o no. para establecer una clave primaria para una tabla empleábamos la siguiente sintaxis al crear la tabla. podemos ejecutar el procedimiento almacenado "sp_helpconstraint" y fijarnos lo que informa la columna "status_enabled". por ejemplo: create table libros( codigo int not null. a las demás se las debe eliminar ("default" y las que veremos posteriormente). titulo varchar(30). "default" y "check". habilita todas las restricciones que tiene la tabla nombrada. Para habilitar una restricción deshabilitada se ejecuta la misma instrucción pero con la cláusula "check" o "check all": alter table libros check constraint CK_libros_precio. Para habilitar o deshabilitar restricciones la comprobación de datos en inserciones o actualizaciones. Hay 2 tipos: 1) primary key y 2) unique. En el ejemplo anterior deshabilitamos la restricción "CK_libros_precio" para poder ingresar un valor negativo para "precio". Si se emplea "check constraint all" no se coloca nombre de restricciones. autor varchar(30).

la restricción no se establece. si no los cumple. que asegura la unicidad de cada registro de una tabla. si intentamos definir la restricción "primary key" para "libros" y hay registros con códigos repetidos o con un valor "null". podemos ver las restricciones "primary key" (y todos los tipos de restricciones) de dicha tabla. Cuando establecíamos una clave primaria al definir la tabla. Igualmente.. Si ejecutamos el procedimiento almacenado "sp_helpconstraint" junto al nombre de la tabla.). recibía un nombre dado por SQL Server que comienza con "PK" (por primary key).. . los campos que son clave primaria DEBEN haber sido definidos "not null" (o ser implícitamente "not null" si se definen identity). primary key(codigo) ). cuando demos el nombre a las restricciones "primary key" seguiremos el formato "PK_NOMBRETABLA_NOMBRECAMPO". Por convención. aparece un mensaje de error. si intentamos ingresar un registro con un valor para el campo "codigo" que ya existe o el valor "null". Dicha restricción. a la cual no le dábamos un nombre. seguido del nombre de la tabla y una serie de letras y números aleatorios. la restricción no se aplica y aparece un mensaje de error. En el siguiente ejemplo definimos una restricción "primary key" para nuestra tabla "libros" para asegurarnos que cada libro tendrá un código diferente y único: alter table libros add constraint PK_libros_codigo primary key(codigo). porque no se permiten valores duplicados ni nulos. pero al agregar una restricción "primary key". SQL Server creaba automáticamente una restricción "primary key" para dicha tabla.. Podemos agregar una restricción "primary key" a una tabla existente con la sintaxis básica siguiente: alter table NOMBRETABLA add constraint NOMBRECONSTRAINT primary key (CAMPO. Cada vez que establecíamos la clave primaria para la tabla. Sabemos que cuando agregamos una restricción a una tabla que contiene información. Un campo con una restricción "primary key" puede tener una restricción "check". automáticamente SQL Server redefinía el campo como "not null". Con esta restricción. Por ejemplo. SQL Server permite definir solamente una restricción "primary key" por tabla. SQL Server controla los datos existentes para confirmar que cumplen las exigencias de la restricción. si actualizamos.editorial varchar(20).

SQL Server controla la entrada de datos en inserciones y actualizaciones evitando que se ingresen valores duplicados. si podrá establecerse si tiene valores nulos.Restricción unique Hemos visto que las restricciones aplicadas a tablas aseguran valores únicos para cada registro. la restricción no podrá establecerse. SQL Server controla los datos existentes para confirmar que cumplen la condición de la restricción. Se emplea cuando ya se estableció una clave primaria (como un número de legajo) pero se necesita asegurar que otros datos también sean únicos y no se repitan (como número de documento). . Recuerde que cuando agregamos una restricción a una tabla que contiene información. Anteriormente aprendimos la restricción "primary key". si la tabla contiene números de documento duplicados. aparecerá un mensaje de error indicando que se intenta duplicar la clave. es decir. La restricción "unique" impide la duplicación de claves alternas (no primarias). En el caso del ejemplo anterior. si no los cumple. Se pueden aplicar varias restricciones de este tipo a una misma tabla. pero cuando empleemos varias tablas verá que es útil identificar las restricciones por tipo. 51 . Por convención. La sintaxis general es la siguiente: alter table NOMBRETABLA add constraint NOMBRERESTRICCION unique (CAMPO). pero no tiene sentido ya que el valor por defecto solamente podrá ingresarse una vez. se acepta.Un campo "primary key" también acepta una restricción "default" (excepto si es identity). si intenta ingresarse cuando otro registro ya lo tiene almacenado. y pueden aplicarse a uno o varios campos que no sean clave primaria. Ejemplo: alter table alumnos add constraint UQ_alumnos_documento unique (documento). Esta restricción permite valores nulos. En el ejemplo anterior se agrega una restricción "unique" sobre el campo "documento" de la tabla "alumnos". la restricción no se aplica y aparece un mensaje de error. especifica que dos registros no puedan tener el mismo valor en un campo. tabla y campo. otra restricción para las tablas es "unique". esto asegura que no se pueda ingresar un documento si ya existe. asi que si se ingresa el valor "null" para el campo "documento". cuando demos el nombre a las restricciones "unique" seguiremos la misma estructura: "UQ_NOMBRETABLA_NOMBRECAMPO". Se permiten valores nulos. Quizá parezca innecesario colocar el nombre de la tabla.

constraint_name: nombre de la restricción.status_enabled: solamente es aplicable para restricciones de tipo "check" y "foreign key". . . 54 .drop) Para eliminar una restricción.Crear y asociar reglas (create rule . Indica "n/a" en cualquier restricción para la que no se aplique. devuelve las siguientes columnas: . Cuando eliminamos una tabla. si es una "primary key" o "unique" muestra el/ los campos a los que se aplicaron la restricción. el valor por defecto. .constraint_keys: Si es una restricción "check" muestra la condición de chequeo.Información de restricciones (sp_helpconstraint) El procedimiento almacenado "sp_helpconstraint" seguido del nombre de una tabla muestra la información referente a todas las restricciones establecidas en dicha tabla.52 .constraint_type: tipo de restricción.status_for_replication: solamente es aplicable para restricciones de tipo "check" y "foreign key". Indica "n/a" en cualquier restricción para la que no se aplique. todas las restricciones que fueron establecidas en ella. .update_action: sólo es aplicable para restricciones de tipo "foreign key" (la veremos posteriormente).sp_bindrule) . Indica si está habilitada (Enabled) o no (Disabled). . Pueden eliminarse varias restricciones con una sola instrucción separándolas por comas. Si es una restricción de campo (default o check) indica sobre qué campo fue establecida. Para eliminar la restricción "DF_libros_autor" de la tabla libros tipeamos: alter table libros drop DF_libros_autor. si es una restricción "default".Eliminar restricciones (alter table . se eliminan también. . 53 .delete_action: solamente es aplicable para restricciones de tipo "foreign key" (la veremos posteriormente). Si es de tabla (primary key o unique) indica el tipo de índice creado (tema que veremos posteriormente). la sintaxis básica es la siguiente: alter table NOMBRETABLA drop NOMBRERESTRICCION.

Pueden ser: a) DEFAULT: especifica un valor por defecto para un campo cuando no se inserta explícitamente en un comando "insert". coincidan con una lista de valores o sigan un patrón. Se permiten valores nulos. Hay 2 tipos: a) PRIMARY KEY: identifica unívocamente cada uno de los registros. luego la palabra clave "as" seguido de una variable (a la cual la precede el signo arroba) y finalmente la condición. Las reglas especifican los valores que se pueden ingresar en un campo. b) UNIQUE: impide la duplicación de claves alternas (no primarias). RESTRICCIONES (constraints). luego de "create rule" se coloca el nombre de la regla. se emplea en inserciones y actualizaciones ("insert" y "update"). Se crea un índice automáticamente. II) DE LA TABLA (asegura un identificador único para cada registro de una tabla). Un campo puede tener solamente UNA regla asociado a él. 2. mediante el uso de: 1. . Una regla se asocia a un campo de una tabla (o a un tipo de dato definido por el usuario. VALORES PREDETERMINADOS (defaults). asegurando que los datos se encuentren en un intervalo de valores específico. Se crea un índice automáticamente. REGLAS (rules) y 3. que se establecen en tablas y campos y son controlados automáticamente por SQL Server. b) CHECK: especifica un rango de valores que acepta un campo. III) REFERENCIAL: lo veremos más adelante.Vimos que SQL Server ofrece varias alternativas para asegurar la integridad de datos. asegura que no haya valores duplicados ni valores nulos. Hay 3 tipos: I) DE LOS CAMPOS (hace referencia a los valores válidos para un campo determinado). Veamos las reglas. tema que veremos posteriormente). Sintaxis básica es la siguiente: create rule NOMBREREGLA as @VARIABLE CONDICION Entonces.

image. actúa en inserciones y actualizaciones. solamente se deshace la asociación.Por convención. SQL Server no lo informa al crear la regla ni al asociarla. no puede hacer referencia a los campos de una tabla. Asociamos la regla creada anteriormente al campo "sueldo" de la tabla "empleados": exec sp_bindrule RG_sueldo_intervalo. la regla se asocia igualmente. La condición se refiere a los valores permitidos para inserciones y actualizaciones y puede contener cualquier expresión válida para una cláusula "where". Si asocia una nueva regla a un campo que ya tiene asociada otra regla. nombraremos las reglas comenzando con "RG". dicha variable será reemplazada por el valor del campo cuando se asocie. la nueva regla reeemplaza la asociación anterior. La sentencia "create rule" no puede combinarse con otras sentencias en un lote. Si intentamos agregar (o actualizar) un registro con valor para el campo "sueldo" que no esté en el intervalo de valores especificado en la regla. La regla debe ser compatible con el tipo de datos del campo al cual se asocia. debemos asociarla a un campo ejecutando un procedimiento almacenado del sistema empleando la siguiente sintaxis básica: exec sp_bindrule NOMBREREGLA. es decir. La variable puede tener cualquier nombre. estableciendo un intervalo de valores: create rule RG_sueldo_intervalo as @sueldo between 100 and 1000 Luego de crear la regla. 'empleados. aparece un mensaje de error indicando que hay conflicto con la regla y la inserción (o actualización) no se realiza. si no los cumple.sueldo'. 'TABLA. las siguientes características explican algunas diferencias entre ellas: . pero al ejecutar una instrucción "insert" o "update" muestra un mensaje de error.CAMPO'. Creamos una regla para restringir los valores que se pueden ingresar en un campo "sueldo" de una tabla llamada "empleados". si esto no sucede. La función que cumple una regla es básicamente la misma que una restricción "check". pero al ejecutar una instrucción "insert" o "update" muestra un mensaje de error. No se puede crear una regla para campos de tipo text. pero debe estar precedido por el signo arroba (@). SQL Server NO controla los datos existentes para confirmar que cumplen con la regla como lo hace al aplicar restricciones. pero la primera regla no desaparece. o timestamp. el nombre del campo al que se asocia y alguna palabra que haga referencia a la condición.

ejecutando el procedimiento almacenado del sistema "sp_unbindrule": exec sp_unbindrule 'TABLA. . No es posible eliminar una regla si está asociada a un campo. . .podemos definir varias restricciones "check" sobre un campo. 55 . Luego de quitar la asociación la eliminamos: drop rule RG_sueldo_100a1000. una regla no. aparece un mensaje de error. Las reglas son objetos diferentes e independientes de las tablas. . Con "sp_helpconstraint" podemos ver las reglas asociadas a los campos de una tabla. primero se debe deshacer la asociación.drop rule) Para eliminar una regla. Si eliminamos una tabla. si eliminamos una tabla. las asociaciones de reglas de sus campos desaparecen. en tal caso en la columna "Object_type" aparece "rule". Con "sp_help" podemos ver todos los objetos de la base de datos activa. SQL Server no lo informa al crearlas y/o asociarlas.Eliminar y dasasociar reglas (sp_unbindrule . pero las reglas siguen existiendo en la base de datos. Quitamos la asociación de la regla "RG_sueldo_intervalo" con el campo "sueldo" de la tabla "empleados" tipeando: exec sp_unbindrule 'empleados. pero al intentar ingresar un valor que alguna de ellas no permita. aparece un mensaje de error y la eliminación no se realiza. una regla puede asociarse a distintos campos (incluso de distintas tablas). Con la instrucción "drop rule" eliminamos la regla: drop rule NOMBREREGLA. un campo solamente puede tener una regla asociada a él.una restricción "check" puede incluir varios campos. Si hay conflicto entre ellas.. incluyendo las reglas. Un campo puede tener reglas asociadas a él y restricciones "check". Si intentamos hacerlo. pero las reglas siguen existiendo. las restricciones también se borran.sueldo'.una restricción "check" se almacena con la tabla.una restricción "check" puede hacer referencia a otros campos de la misma tabla. cuando ésta se elimina. las asociaciones desaparecen.CAMPO'.

--búsqueda con comodín 57 . nombrando el campo al que está asociada.tipo regla name like 'RG%'. que nos muestra el nombre y varios datos de todos los objetos de la base de datos actual. en caso de ser una regla aparece el valor "R": select *from sysobjects.constraint_keys: muestra el texto de la regla. . podemos tipear: select *from sysobjects where xtype='R' and-. También se puede consultar la tabla del sistema "sysobjects".constraint_name: nombre de la regla. muestra nombre. Con "sp_help". La columna "xtype" indica el tipo de objeto. Para ver el texto de una regla empleamos el procedimiento almacenado "sp_helptext" seguido del nombre de la regla: sp_helptext NOMBREREGLA. tipo y fecha de creación. Si queremos ver todas las reglas creadas por nosotros.constraint_type: indica que es una regla con "RULE". "sp_helpconstraint" retorna una lista de todas las restricciones que tiene una tabla. no sabemos si las reglas existentes están o no asociadas a algún campo.56 . muestra la siguiente información: . Podemos ver las reglas asociadas a una tabla con este procedimiento almacenado: sp_helpconstraint NOMBRETABLA. . en este caso el nombre de una regla: sp_help NOMBREREGLA. propietario.Información de reglas (sp_help .sp_helpconstraint) Podemos utilizar el procedimiento almacenado "sp_help" con el nombre del objeto del cual queremos información.Valores predeterminados (create default) .

pero al ejecutar una instrucción "insert" muestra un mensaje de error. 'empleados. La función que cumple un valor predeterminado es básicamente la misma que una restricción "default". Veamos los valores predeterminados.Hemos visto que para mantener la integridad declarativa se emplean restricciones. las siguientes características explican algunas semejanzas y diferencias entre ellas: . el valor predeterminado especifica el valor del campo al que está asociado. Si no se coloca un valor cuando se ingresan datos. SQL Server no lo informa al crear el valor predeterminado ni al asociarlo. La siguiente sentencia asocia el valor predeterminado creado anteriormente al campo "domicilio" de la tabla "empleados": exec sp_bindefault VP_datodesconocido. 'empleados. 'NOMBRETABLA.domicilio'.un campo solamente puede tener definida UNA restricción "default". "VALORPREDETERMINADO" no puede hacer referencia a campos de una tabla (u otros objetos) y debe ser compatible con el tipo de datos y longitud del campo al cual se asocia. si esto no sucede. Los valores predeterminados se asocian con uno o varios campos (o tipos de datos definidos por el usuario). En el siguiente ejemplo creamos un valor predeterminado llamado "VP_datodesconocido' con el valor "Desconocido": create default VP_datodesconocido as 'Desconocido' Luego de crear un valor predeterminado. debemos asociarlo a un campo (o a un tipo de datos definido por el usuario) ejecutando el procedimiento almacenado del sistema "sp_bindefault": exec sp_bindefault NOMBRE. Sintaxis básica: create default NOMBREVALORPREDETERMINADO as VALORPREDETERMINADO.barrio'. reglas (que hemos estudiado en secciones anteriores) y valores predeterminados. Podemos asociar un valor predeterminado a varios campos. se definen una sola vez y se pueden usar muchas veces. .CAMPO'. un campo solamente puede tener UN valor predeterminado asociado a él. Asociamos el valor predeterminado "VP_datodesconocido" al campo "barrio" de la tabla "empleados": exec sp_bindefault VP_datodesconocido.

58 . Si hay conflicto entre ellas. tampoco un valor predeterminado.una restricción "default" no puede establecerse sobre un campo "identity". Con "sp_helpconstraint" podemos ver los valores predeterminados asociados a los campos de una tabla. aparece un mensaje de error. Si asocia a un campo que ya tiene asociado un valor predeterminado otro valor predeterminado.Desasociar y eliminar valores predeterminados Un valor predeterminado no puede eliminarse si no se ha desasociado previamente. pero al intentar ingresar un valor que alguna de ellas no permita. No se puede asociar un valor predeterminado a un campo que tiene una restricción "default". . Un campo con un valor predeterminado asociado puede tener reglas asociadas a él y restricciones "check". En el siguiente creamos un valor predeterminado que inserta ceros con el formato válido para un número de teléfono: create default VP_telefono as '(0000)0-000000'. de diferentes tablas). . Para deshacer una asociación empleamos el procedimiento almacenado "sp_unbindefault" seguido de la tabla y campo al que está asociado: . incluyendo los valores predeterminados.una restricción "default" se almacena con la tabla. Veamos otros ejemplos. la nueva asociación reemplaza a la anterior. cuando ésta se elimina. en tal caso en la columna "Object_type" aparece "default". las restricciones también. SQL Server no lo informa al crearlas y/o asociarlas. Con "sp_help" podemos ver todos los objetos de la base de datos activa. las asociaciones desaparecen. Los valores predeterminados son objetos diferentes e independientes de las tablas. un valor predeterminado puede asociarse a distintos campos (inclusive. La sentencia "create default" no puede combinarse con otra sentencia en un mismo lote. si eliminamos una tabla. Creamos un valor predeterminado que inserta el valor "0" en un campo de tipo numérico: create default VP_cero as 0. pero los valores predeterminados siguen existiendo en la base de datos..una restricción "default" se establece para un solo campo.

Si empleamos "sp_help". Con la instrucción "drop default" podemos eliminar un valor predeterminado: drop default NOMBREVALORPREDETERMINADO. Quitamos la asociación al campo "sueldo" de la tabla "empleados": sp_unbindefault 'empleados. en la columna "Object_type" (tipo de objeto) muestra "default". no sabemos si los valores predeterminados existentes están o no asociadas a algún campo. Si al procedimiento almacenado "sp_help" le agregamos el nombre de un valor predeterminado.Información de valores predeterminados Para obtener información de los valores predeterminados podemos emplear los mismos procedimientos almacenados que usamos para las reglas. nos muestra el nombre. Si eliminamos una tabla. Eliminamos el valor predeterminado llamado "VP_cero": drop default VP_cero. También los valores predeterminados asociados. muestra la siguiente información: . . Con "sp_help". "sp_helpconstraint" retorna una lista de todas las restricciones que tiene una tabla.constraint_keys: muestra el texto del valor predeterminado.sueldo'. nombrando el campo al que está asociado. propietario. . pero los valores predeterminados siguen existiendo. las asociaciones de valores predeterminados de sus campos desaparecen. vemos todos los objetos de la base de datos activa (incluyendo los valores predeterminados).sp_unbindefault 'TABLA.CAMPO'. Con "sp_helptext" seguido del nombre de un valor predeterminado podemos ver el texto de cualquier valor predeterminado: .constraint_name: nombre del valor predeterminado.constraint_type: indica que es un valor predeterminado con "DEFAULT". 59 . tipo y fecha de creación: sp_help NOMBREVALORPREDETERMINADO.

El objetivo de un indice es acelerar la recuperación de información. Es importante identificar el o los campos por los que sería útil crear un índice. Un índice posibilita el acceso directo y rápido haciendo más eficiente las búsquedas. SQL Server debe recorrer secuencialmente toda la tabla para encontrar un registro. en el caso de las tablas. mejora el rendimiento acelerando las consultas y otras operaciones. recorriendo la estructura de árbol del índice para localizar los registros y extrayendo los que cumplen las condiciones de la consulta. Los índices se emplean para facilitar la obtención de información de una tabla.tipo valor predeterminado name like 'VP%'. Los índices más adecuados son aquellos creados con campos que contienen valores únicos. Sin índice. claves externas o campos que combinan tablas. empleando índices. en caso de ser un valor predeterminado aparece el valor "D": select *from sysobjects.--búsqueda con comodín 60 . La indexación es una técnica que optimiza el acceso a los datos. cuando se realizan operaciones de ordenamiento y agrupamiento y cuando se combinan varias tablas (tema que veremos más adelante).sp_helptext NOMBREVALORPREDETERMINADO. localiza registros. La columna "xtype" indica el tipo de objeto. El indice de una tabla desempeña la misma función que el índice de un libro: permite encontrar datos rápidamente. comenzando el principio y extrayendo los registros que cumplen las condiciones de la consulta. . aquellos campos por los cuales se realizan búsqueda con frecuencia: claves primarias. podemos tipear: select *from sysobjects where xtype='D' and-. La desventaja es que consume espacio en el disco en disco y genera costo de mantenimiento (tiempo y recursos). Una tabla se indexa por un campo (o varios). 2. recorriendo las tablas. que nos muestra el nombre y varios datos de todos los objetos de la base de datos actual. Es útil cuando la tabla contiene miles de registros. Si queremos ver todos los valores predeterminados creados por nosotros. También se puede consultar la tabla del sistema "sysobjects".Indices SQL Server accede a los datos de dos maneras: 1.

Es posible crear índices en las vistas. los datos se almacenan en un lugar diferente al del índice. ntext e image no se pueden indizar. Un índice no agrupado se emplea cuando se realizan distintos tipos de busquedas frecuentemente. 1) Un INDICE AGRUPADO es similar a una guía telefónica. La diferencia básica entre índices agrupados y no agrupados es que los registros de un índice agrupado están ordenados y almacenados de forma secuencial en función de su clave. los punteros indican el lugar de almacenamiento de los elementos indizados en la tabla.No se recomienda crear índices por campos que no se usan con frecuencia en consultas o no contienen valores únicos. permitiendo el acceso directo y acelerando las búsquedas. La sintaxis básica es la siguiente: . SQL Server permite crear dos tipos de índices: 1) agrupados y 2) no agrupados. Se utilizan para campos por los que se realizan busquedas con frecuencia o se accede siguiendo un orden. 62 . Un índice agrupado determina la secuencia de almacenamiento de los registros en una tabla. Una tabla sólo puede tener UN índice agrupado.Creación de índices Para crear índices empleamos la instrucción "create index".Indices agrupados y no agrupados (clustered y nonclustered) Dijimos que SQL Server permite crear dos tipos de índices: 1) agrupados (clustered) y 2) no agrupados (nonclustered). los índices facilitan la recuperación de datos. porque los primeros modifican el orden físico de los registros. ordenándolos secuencialmente. Es recomendable crear los índices agrupados antes que los no agrupados. Si no se especifica un tipo de índice. Resumiendo. Los campos de tipo text. SQL Server crea automaticamente índices cuando se crea una restricción "primary key" o "unique" en una tabla. Una tabla puede tener hasta 249 índices no agrupados. El tamaño medio de un índice agrupado es aproximadamente el 5% del tamaño de la tabla. consultas y otras operaciones que optimizan el rendimiento general. de modo predeterminado será no agrupado. los registros con el mismo valor de campo se agrupan juntos. 61 . con campos en los que los datos son únicos. 2) Un INDICE NO AGRUPADO es como el índice de un libro.

editorial). Ahora podemos entender el resultado del procedimiento almacenado "sp_helpconstraint" cuando en la columna "constraint_type" mostraba el tipo de índice seguido de las palabras "clustered" o "non_clustered". SQL Server no lo permite. .tema que veremos posteriormente). Los campos de un índice compuesto tienen que ser de la misma tabla (excepto cuando se crea en una vista . SQL Server crea automáticamente índices cuando se establece una restricción "primary key" o "unique" en una tabla. Puede especificarse que un índice sea agrupado o no agrupado al agregar estas restricciones. "TIPODEINDICE" indica si es agrupado (clustered) o no agrupado (nonclustered). Un índice puede tener más de un campo como clave. Si no especificamos crea uno No agrupado. por ejemplo "I" y luego el nombre de la tabla y/o campo.create TIPODEINDICE index NOMBREINDICE on TABLA(CAMPO). Para identificar los índices fácilmente. es decir. Al crear una restricción "unique". Creamos un índice compuesto para el campo "autor" y "editorial": create index I_libros_autoreditorial on libros(autor. son índices compuestos. no haya valores repetidos. si no se especifica. el índice será agrupado (clustered) a menos que ya exista un índice agrupado para dicha tabla. también se puede especificar que sea "unique". el índice será no agrupado (nonclustered). Independientemente de si es agrupado o no. Al crear una restricción "primary key". si no se especifica. En este ejemplo se crea un índice no agrupado para el campo "titulo" de la tabla "libros": create nonclustered index I_libros_titulo on libros(titulo). Agregamos una restricción "primary key" al campo "codigo" de la tabla "libros" especificando que cree un índice NO agrupado: alter table libros add constraint PK_libros_codigo primary key nonclustered (codigo). Si se intenta crear un índice unique para un campo que tiene valores duplicados. podemos agregar un prefijo al nombre del índice. En este ejemplo se crea un índice agrupado único para el campo "codigo" de la tabla "libros": create unique clustered index I_libros_codigo on libros(codigo).

Todos los índices de la base de datos activa se almacenan en la tabla del sistema "sysindexes". . No se puede convertir un índice agrupado en No agrupado. También podemos modificar alguna de las características de un índice con esta opción. con ello evitamos eliminarlo y volver a crearlo. Para ver todos los índices de la base de datos activa creados por nosotros podemos tipear la siguiente consulta: select name from sysindexes where name like 'I_%'. La sintaxis es la siguiente: create TIPODEINDICE index NOMBREINDICE on TABLA(CAMPO) with drop_existing. . 63 .Para ver los indices de una tabla: sp_helpindex libros.Regenerar índices Vimos que para crear índices empleamos la instrucción "create index". En este ejemplo se crea un índice no agrupado para el campo "titulo" de la tabla "libros": create nonclustered index I_libros on libros(titulo). agregar campos. Empleando la opción "drop_existing" junto con "create index" permite regenerar un índice. si es agrupado (o no). a saber: . podemos consultar dicha tabla tipeando: select name from sysindexes.tipo: cambiándolo de no agrupado a agrupado (siempre que no exista uno agrupado para la misma tabla). Muestra el nombre del índice.único: se puede modificar un índice para que los valores sean únicos o dejen de serlo. primary (o unique) y el campo por el cual se indexa. eliminar algún campo de un índice compuesto.campo: se puede cambiar el campo por el cual se indexa. Regeneramos el índice "I_libros" y lo convertimos a agrupado: .

I_libros_titulo. 65 . consultando la tabla del sistema "sysindexes": if exists (select name from sysindexes where name = 'NOMBREINDICE') drop index NOMBRETABLA. Podemos averiguar si existe un índice para eliminarlo. se trabaja con más de una.create clustered index I_libros on libros(titulo) with drop_existing.NOMBREINDICE.I_libros_titulo. Eliminamos el índice "I_libros_titulo" si existe: if exists (select *from sysindexes where name = 'I_libros_titulo') drop index libros. Los índices que SQL Server crea automáticamente al establecer una restricción "primary key" o "unique" no pueden eliminarse con "drop index". se eliminan automáticamente cuando quitamos la restricción.editorial) with drop_existing. la siguiente es la sintaxis básica: drop index NOMBRETABLA. Agregamos un campo al índice "I_libros": create clustered index I_libros on libros(titulo.NOMBREINDICE. Esta opción no puede emplearse con índices creados a partir de una restricción "primary key" o "unique". Eliminamos el índice "I_libros_titulo": drop index libros.Eliminar índices Los índices creados con "create index" se eliminan con "drop index". . pero generalmente. 64 .Trabajar con varias tablas Hasta el momento hemos trabajado con una sola tabla.

los datos de nuestra tabla "libros" podrían separarse en 2 tablas. Veamos: create table libros( codigo int identity. una llamada "libros" y otra "editoriales" que guardará la información de las editoriales. autor varchar(30) not null default 'Desconocido'. Para obtener los datos de cada libro. create table editoriales( codigo tinyint identity. Al recuperar los datos de los libros con la siguiente instrucción: select* from libros. titulo varchar(40) not null.Para evitar la repetición de datos y ocupar menos espacio. pero no sabemos el nombre de la editorial. Cada tabla almacena parte de la información que necesitamos registrar. primary key (codigo) ). nombre varchar(20) not null. necesitamos consultar ambas tablas. . traer información de las dos. evitamos almacenar tantas veces los nombres de las editoriales en la tabla "libros" y guardamos el nombre en la tabla "editoriales". codigoeditorial tinyint not null.codigo. para indicar la editorial de cada libro agregamos un campo que hace referencia al código de la editorial en la tabla "libros" y en "editoriales".codigoeditorial=editoriales. Por ejemplo. se separa la información en varias tablas. Cuando obtenemos información de más de una tabla decimos que hacemos un "join" (combinación). primary key(codigo) ). De esta manera. precio decimal(5. Veamos un ejemplo: select *from libros join editoriales on libros.2). En nuestra tabla "libros" haremos referencia a la editorial colocando un código que la identifique. incluyendo el nombre de la editorial. vemos que en el campo "editorial" aparece el código.

66 . incluso puede combinarse una tabla consigo misma. combinaciones externas y 3. las tablas participantes se combinan según los campos comunes a ambas tablas. . Un join es una operación que relaciona dos o más tablas para obtener un resultado que incluya datos (campos y registros) de ambas. . Se emplea para obtener información de dos tablas y combinar dicha información en una salida. Analicemos la consulta anterior.Combinación interna (inner join) Un join es una operación que relaciona dos o más tablas para obtener un resultado que incluya datos (campos y registros) de ambas. . Hay hay tres tipos de combinaciones. las tablas participantes se combinan según los campos comunes a ambas tablas. La sintaxis básica es la siguiente: select CAMPOS from TABLA1 join TABLA2 on CONDICIONdeCOMBINACION. Ejemplo: select *from libros join editoriales on codigoeditorial=editoriales. También es posible emplear varias combinaciones en una consulta "select". que es la forma abreviada de "inner join".codigo.indicamos el nombre de la tabla luego del "from" ("libros"). combinaciones internas (inner join o join).especificamos los campos que aparecerán en el resultado en la lista de selección. 2.Resumiendo: si distribuimos la información en varias tablas evitamos la redundancia de datos y ocupamos menos espacio físico en el disco. Hay tres tipos de combinaciones: 1. En los siguientes capítulos explicamos cada una de ellas. La combinación interna emplea "join". combinaciones cruzadas.

Si una de las tablas tiene clave primaria compuesta. En algunos casos (como en este ejemplo) el uso de alias es para fines de simplificación y hace más legible la consulta si es larga y compleja.codigo" y solamente tipeamos "codigo". Se emplean campos comunes. es decir.codigo.. SQL Server no sabrá si nos referimos al campo "codigo" de "libros" o de "editoriales" y mostrará un mensaje de error indicando que "codigo" es ambiguo.nombre from libros as l join editoriales as e on l. es decir. DEBE especificarse a qué tabla pertenece anteponiendo el nombre de la tabla al nombre del campo. es necesario especificar qué registro de una tabla se combinará con qué registro de la otra tabla.. La condicion de combinación. esto es necesario para evitar confusiones y ambiguedades al momento de referenciar un campo. .titulo. el registro no aparece.). el o los campos por los que se van a combinar (parte "on"). que deben tener tipos de datos iguales o similares. Se puede incluir en la consulta join la cláusula "where" para restringir los registros que retorna el resultado. Cuando las tablas referenciadas tienen campos con igual nombre.autor. "on" hace coincidir registros de ambas tablas basándose en el valor de tal campo. también "order by". 67 . Note que en la consulta. el campo "codigoeditorial" de "libros" y el campo "codigo" de "editoriales" son los que enlazarán ambas tablas. que tienen en común. en el ejemplo. es decir. Para simplificar la sentencia podemos usar un alias para cada tabla: select l. En el ejemplo. se especifica según las claves primarias y externas. es decir. pero en algunas consultas es absolutamente necesario.Combinación externa izquierda (left join) . en la cláusula "on" se debe hacer referencia a la clave completa. se especifica qué tablas se van a combinar y cómo. al combinarla con la otra. Entonces.codigoeditorial=e. al nombrar el campo usamos el nombre de la tabla también. con "on". el campo por el cual se combinarán. Se emplea este tipo de combinación para encontrar registros de la primera tabla que se correspondan con los registros de la otra. separado por un punto (. Se debe especificar la condición para enlazarlas.cuando se combina información de varias tablas. Si un valor de la primera tabla no se encuentra en la segunda tabla. etc. si no especificamos "editoriales. la condición referenciará a todos los campos clave que identifican al registro.codigo. si las tablas que combinamos tienen nombres de campos iguales. "distinct".combinamos esa tabla con "join" y el nombre de la otra tabla ("editoriales"). que cumplan la condición del "on".

se pueden abreviar con "left join". es decir. En el siguiente ejemplo solicitamos el título y nombre de la editorial de los libros: select titulo. muestran todos los registros de las tablas relacionadas. pero con el valor "null" en el campo "titulo". Este tipo de combinación se emplea cuando se necesita una lista completa de los datos de una de las tablas y la información que cumple con la condición.Vimos que una combinación interna (join) encuentra registros de la primera tabla que se correspondan con los registros de la segunda.codigo. cuyo código de editorial no está presente en "libros" aparece en el resultado. no existe valor coincidente en la segunda. Se emplea una combinación externa izquierda para mostrar todos los registros de la tabla de la izquierda. Las combinaciones externas se realizan solamente entre 2 tablas. la tabla de la izquierda es la que se usa para localizar registros en la tabla de la derecha.nombre from editoriales as e left join libros as l on codigoeditorial = e. más los registros de la segunda tabla que no la cumplen. Entonces. el registro no aparece. se genera una fila extra (una por cada valor no encontrado) con todos los campos correspondientes a la tabla derecha seteados a "null". Vamos a estudiar las primeras. El resultado mostrará el título y nombre de la editorial. La sintaxis básica es la siguiente: select CAMPOS from TABLAIZQUIERDA left join TABLADERECHA on CONDICION. "outer join" (combinación externa). Hay tres tipos de combinaciones externas: "left outer join". aún cuando no haya valores coincidentes entre ellas. el registro muestra los campos de la segunda tabla seteados a "null". que cumplan la condición del "on" y si un valor de la primera tabla no se encuentra en la segunda tabla. Si no encuentra coincidencia con la tabla de la derecha. Las combinaciones externas combinan registros de dos tablas que cumplen la condición. es decir. "right join" y "full join" respectivamente. si un valor de la tabla de la izquierda no encuentra coincidencia en la tabla de la derecha. es decir. un "left join" se usa para hacer coincidir registros en una tabla (izquierda) con otra tabla (derecha). las editoriales de las cuales no hay libros. necesitamos otro tipo de combinación. es decir. . Si queremos saber qué registros de una tabla NO encuentran correspondencia en la otra. "right outer join" y "full outer join". Es importante la posición en que se colocan las tablas en un "left join".

que NO encuentran coincidencia en la tabla de la derecha: select titulo.codigo.nombre from editoriales as e left join libros as l on e. pero con el valor "null" en el campo "nombre". También podemos mostrar las editoriales que NO están presentes en "libros". el registro muestra los campos correspondientes a la tabla de la derecha seteados a "null". Una combinación externa derecha ("right outer join" o "right join") opera del mismo modo sólo que la tabla derecha es la que localiza los registros en la tabla izquierda.nombre from libros as l .nombre from libros as l left join editoriales as e on codigoeditorial = e. la diferencia está en el orden de las tablas: select titulo.Combinación externa derecha (right join) Vimos que una combinación externa izquierda (left join) encuentra registros de la tabla izquierda que se correspondan con los registros de la tabla derecha y si un valor de la tabla izquierda no se encuentra en la tabla derecha. es decir. El resultado mostrará el título del libro y el nombre de la editorial. la sentencia es similar a la anterior. Un "left join" puede tener clausula "where" que restringa el resultado de la consulta considerando solamente los registros que encuentran coincidencia en la tabla de la derecha. 68 .En el siguiente ejemplo solicitamos el título y el nombre la editorial.codigo=codigoeditorial where codigoeditorial is null.codigo=codigoeditorial where codigoeditorial is not null. En el siguiente ejemplo solicitamos el título y nombre de la editorial de los libros empleando un "right join": select titulo. es decir. cuyo valor de código está presente en "libros": select titulo.nombre from editoriales as e left join libros as l on e. los títulos cuyo código de editorial no está presente en "editoriales" aparecen en el resultado.

codigo=codigoeditorial . La sintaxis básica es la siguiente: select CAMPOS from TABLAIZQUIERDA right join TABLADERECHA on CONDICION. en el "right join" la segunda tabla (derecha) es la que busca coincidencias en la primera tabla (izquierda). que NO encuentran coincidencia en la tabla de la derecha empleando un "right join": select titulo. es decir. El resultado mostrará el título y nombre de la editorial. en el "right join" precedente. si un valor de la tabla de la derecha no encuentra coincidencia en la tabla izquierda. Un "right join" hace coincidir registros en una tabla (derecha) con otra tabla (izquierda).codigo. En un "left join" la primera tabla (izquierda) es la que busca coincidencias en la segunda tabla (derecha). Es FUNDAMENTAL tener en cuenta la posición en que se colocan las tablas en los "outer join".nombre from libros as l rightjoin editoriales as e on e.nombre from editoriales as e left join libros as l on codigoeditorial = e.codigo=codigoeditorial where codigoeditorial is not null. se genera una fila extra (una por cada valor no encontrado) con todos los campos correspondientes a la tabla izquierda seteados a "null". las editoriales de las cuales no hay libros. es decir. Mostramos las editoriales que NO están presentes en "libros". Note que la tabla que busca coincidencias ("editoriales") está en primer lugar porque es un "left join". En la siguiente consulta empleamos un "left join" para conseguir el mismo resultado que el "right join" anterior": select titulo.codigo.nombre from libros as l right join editoriales as e on e.right join editoriales as e on codigoeditorial = e. pero con el valor "null" en el campo "titulo". Un "right join" también puede tener cláusula "where" que restringa el resultado de la consulta considerando solamente los registros que encuentran coincidencia en la tabla izquierda: select titulo. cuyo código de editorial no está presente en "libros" aparece en el resultado. estaba en segundo lugar.

nombre from editoriales as e full join libros as l on codigoeditorial = e. La sintaxis básica es ésta: select CAMPOS from TABLA1 cross join TABLA2.where codigoeditorial is null. Veamos un ejemplo: select titulo. Para este tipo de join no se incluye una condición de enlace.codigo. 70 . La salida del "full join" precedente muestra todos los registros de ambas tablas. Una combinación externa completa ("full outer join" o "full join") retorna todos los registros de ambas tablas. si hay 5 registros en una tabla y 6 en la otra.Combinaciones cruzadas (cross join) Vimos que hay tres tipos de combinaciones: 1) combinaciones internas (join). y si la tabla de la derecha no encuentra correspondencia en la tabla izquierda. Se genera el producto cartesiano en el que el número de filas del resultado es igual al número de registros de la primera tabla multiplicado por el número de registros de la segunda tabla. incluyendo los libros cuyo código de editorial no existe en la tabla "editoriales" y las editoriales de las cuales no hay correspondencia en "libros".Combinación externa completa (full join) Vimos que un "left join" encuentra registros de la tabla izquierda que se correspondan con los registros de la tabla derecha y si un valor de la tabla izquierda no se encuentra en la tabla derecha. . right y full join) y 3) combinaciones cruzadas. retorna 30 filas. 69 . es decir. los campos de esta última aparecen conteniendo "null". 2) combinaciones externas (left. Si un registro de una tabla izquierda no encuentra coincidencia en la tabla derecha. Las combinaciones cruzadas (cross join) muestran todas las combinaciones de todos los registros de las tablas combinadas. el registro muestra los campos correspondientes a la tabla de la derecha seteados a "null". las columnas correspondientes a campos de la tabla derecha aparecen seteadas a "null". Aprendimos también que un "right join" opera del mismo modo sólo que la tabla derecha es la que localiza los registros en la tabla izquierda.

Podemos obtener la combinación de platos empleando un "cross join" con una sola tabla: select c1. .precio+c2. Un pequeño restaurante tiene almacenadas sus comidas en una tabla llamada "comidas" que consta de los siguientes campos: .precio+c2. Si necesitamos conocer todas las combinaciones posibles para un menú. Un pequeño restaurante almacena los nombres y precios de sus comidas en una tabla llamada "comidas" y en una tabla denominada "postres" los mismos datos de sus postres.rubro='postre'. para evitarlo debemos emplear un "where": select c1.rubro='plato' and c2.nombre as 'plato principal'. 71 .rubro char(6)-. En la consulta anterior aparecen filas duplicadas.nombre as 'plato principal'.Autocombinación Dijimos que es posible combinar una tabla consigo misma.precio as total from comidas as c1 cross join comidas as c2 where c1.precio as total from comidas as c1 cross join comidas as c2.nombre as postre. Como cualquier tipo de "join". c2.precio decimal (4.que indica con 'plato' si es un plato principal y 'postre' si es postre. c2. puede emplearse una cláusula "where" que condicione la salida. La salida muestra cada plato combinado con cada uno de los postres.nombre as 'plato principal'.nombre varchar(20). c1.nombre as 'postre' from comidas as c cross join postres as p.nombre as postre.Veamos un ejemplo.2) y . p. empleamos un "cross join": select c. c1. cada comida con cada postre. .

rubro='plato' and c2. max(precio) as 'mayor precio' from editoriales as e left join libros as l on codigoeditorial=e.Combinaciones y funciones de agrupamiento Podemos usar "group by" y las funciones de agrupamiento con combinaciones de tablas.rubro='postre'. c1.nombre.codigo group by nombre. 72 . Para que no aparezcan filas duplicadas se agrega un "where".codigo group by e. Note que las editoriales que no tienen libros no aparecen en la salida porque empleamos un "join".nombre as postre. debemos emplear un "where". Para ello debemos utilizar 2 alias para la tabla. hacemos un "left join" y agrupamos por nombre de la editorial: select nombre as editorial. .nombre as 'plato principal'. tipeamos: select nombre as editorial. También se puede realizar una autocombinación con "join": select c1.precio as total from comidas as c1 join comidas as c2 on c1.precio+c2. c2. Para evitar que aparezcan filas duplicadas.En la consulta anterior se empleó un "where" que especifica que se combine "plato" con "postre". Para ver la cantidad de libros de cada editorial consultando la tabla "libros" y "editoriales". En una autocombinación se combina una tabla con una copia de si misma. Empleamos otra función de agrupamiento con "left join". Para conocer el mayor precio de los libros de cada editorial usamos la función "max()".codigo<>c2. count(*) as cantidad from editoriales as e join libros as l on codigoeditorial=e.codigo where c1.

autor y editorial de todos los libros que encuentren o no coincidencia con "autores" ("right join") y a ese resultado lo combinamos con "editoriales". . Note que especificamos a qué tabla pertenecen los campos cuyo nombre se repiten en las tablas.codigo.nombre.En la sentencia anterior. Se pueden emplear varios join para enlazar varias tablas. combinamos esa tabla con la tabla "libros" especificando con "on" el campo por el cual se combinarán. En la consulta anterior solicitamos el título. Utilizamos alias para una sentencia más sencilla y comprensible. 73 .codigo join editoriales as e on codigoeditorial=e. encuentren o no coincidencia.nombre from autores as a right join libros as l on codigoautor=a.nombre from autores as a join libros as l on codigoautor=a.e. Indicamos el nombre de la tabla luego del "from" ("autores"). La librería almacena los datos de sus libros en tres tablas: libros. Cada resultado de un join es una tabla que puede combinarse con otro join.e.a. Note que no aparecen los libros cuyo código de autor no se encuentra en "autores" y cuya editorial no existe en "editoriales". editoriales y autores. Podemos combinar varios tipos de join en una misma sentencia: select titulo. Cada join combina 2 tablas. para la editorial de la cual no haya libros. mostrará. Analicemos la consulta anterior. esto es necesario para evitar confusiones y ambiguedades al momento de referenciar un campo.codigo.codigo left join editoriales as e on codigoeditorial=e.a.nombre. Para recuperar todos los datos de los libros empleamos la siguiente consulta: select titulo. esto es porque realizamos una combinación interna. luego debemos hacer coincidir los valores para el enlace con la tabla "editoriales" enlazándolas por los campos correspondientes.Combinación de más de dos tablas Podemos hacer un "join" con más de dos tablas. el valor "null" en la columna calculada. En la tabla "libros" un campo "codigoautor" hace referencia al autor y un campo "codigoeditorial" referencia la editorial.

externa o ajena. Eliminamos todos los libros de editorial "Emece": delete libros from libros join editoriales on codigoeditorial = editoriales. autor.Combinaciones con update y delete Las combinaciones no sólo se utilizan con la sentencia "select". recuerde que la tabla resultado del primer join es la que se combina con el segundo join. Podemos emplear "update" o "delete" con "join" para actualizar o eliminar registros de una tabla consultando otras tablas. 75 . En consultas en las cuales empleamos varios "join" es importante tener en cuenta el orden de las tablas y los tipos de "join".Clave foránea Un campo que no es clave primaria en una tabla y sirve para enlazar sus valores con otra tabla en la cual es clave primaria se denomina clave foránea. 74 .nombre='Emece'. precio y editoriales: codigo (clave primaria). codigoeditorial. el "left join" no se realiza entre las tablas "libros" y "editoriales" sino entre el resultado del "right join" y la tabla "editoriales".codigo where nombre='Planeta'.1) from libros join editoriales as e on codigoeditorial=e.codigo where editoriales. En el ejemplo anterior.Es posible realizar varias combinaciones para obtener información de varias tablas. En el siguiente ejemplo aumentamos en un 10% los precios de los libros de cierta editorial. también podemos emplearlas con "update" y "delete". Las tablas deben tener claves externas relacionadas con las tablas a combinar. titulo. . nombre. En el ejemplo de la librería en que utilizamos las tablas "libros" y "editoriales" con estos campos: libros: codigo (clave primaria). no la segunda tabla nombrada. necesitamos un "join" para localizar los registros de la editorial "Planeta" en la tabla "libros": update libros set precio=precio+(precio*0.

Si modificamos una. longitud o atributos de una clave foránea. Entonces. se emplea para enlazar la tabla "libros" con "editoriales" y es clave primaria en "editoriales" con el nombre "codigo". 76 . se define una referencia a un campo con una restricción "primary key" o "unique" de la misma tabla o de otra. es decir. 3) referencial: foreign key. debemos tener cuidado con las claves foráneas. para establecer un "join" con otra tabla en la cual es clave primaria. debemos modificar la otra para que los valores se correspondan. Cuando alteramos una tabla. . Por ejemplo. Las claves foráneas y las claves primarias deben ser del mismo tipo para poder enlazarse. Si modificamos el tipo. Analicémosla: . vimos que existen distintos tipos de restricciones: 1) de los campos: default y check 2) de la tabla: primary key y unique. una clave foránea es un campo (o varios) empleados para enlazar datos de 2 tablas. También controla que no pueda eliminarse un registro de una tabla ni modificar la clave primaria si una clave externa hace referencia al registro. ésta puede quedar inhabilitada para hacer los enlaces. Con la restricción "foreign key" se define un campo (o varios) cuyos valores coinciden con la clave primaria de la misma tabla o de otra. Aprendimos que las restricciones se establecen en tablas y campos asegurando que los datos sean válidos y que las relaciones entre las tablas se mantengan. que no se pueda eliminar o modificar un código de "editoriales" si existen libros con dicho código. La siguiente es la sintaxis parcial general para agregar una restricción "foreign key": alter table NOMBRETABLA1 add constraint NOMBRERESTRICCION foreign key (CAMPOCLAVEFORANEA) references NOMBRETABLA2 (CAMPOCLAVEPRIMARIA).Restricciones (foreign key) Hemos visto que una de las alternativas que SQL Server ofrece para asegurar la integridad de datos es el uso de restricciones (constraints).el campo "codigoeditorial" de "libros" es una clave foránea.NOMBRETABLA1 referencia el nombre de la tabla a la cual le aplicamos la restricción. controla que si se agrega un código de editorial en la tabla "libros". Por ejemplo. La integridad referencial asegura que se mantengan las referencias entre las claves primarias y las externas. tal código exista en la tabla "editoriales". la analizaremos ahora.

Esta restricción se puede definir dentro de la misma tabla (lo veremos más adelante) o entre distintas tablas. SQL server muestra un mensaje de error. Si al ingresar un registro (un libro). si intentamos agregar una restricción "foreign key" a la tabla "libros" y existe un libro con un valor de código para editorial que no existe en la tabla "editoriales". Actúa en eliminaciones y actualizaciones. Si intentamos eliminar un registro o modificar un valor de clave primaria de una tabla si una clave foránea hace referencia a dicho registro. La cantidad y tipo de datos de los campos especificados luego de "foreign key" DEBEN coincidir con la cantidad y tipo de datos de los campos de la cláusula "references". No se puede eliminar una tabla referenciada en una restricción "foreign key". SQL Server no lo permite (excepto si se permite la acción en cascada. Para agregar una restricción "foreign key" al campo "codigoeditorial" de "libros". porque esta restricción permite valores nulos (a menos que se haya especificado lo contrario al definir el campo). Esta restricción (a diferencia de "primary key" y "unique") no crea índice automaticamente. almacenará "null". SQL Server controla los datos existentes para confirmar que cumplen con la restricción. a la cual hace referencia la clave foránea. . Actúa en inserciones. En el ejemplo implementamos una restricción "foreign key" para asegurarnos que el código de la editorial de la de la tabla "libros" ("codigoeditorial") esté asociada con un código válido en la tabla "editoriales" ("codigo"). entre paréntesis se coloca el campo de la tabla a la que le aplicamos la restricción que será establecida como clave foránea. si intentamos eliminar una editorial a la que se hace referencia en "libros".. Cuando agregamos cualquier restricción a una tabla que contiene información. aparece un mensaje de error. . aparece un mensaje de error. Si intentamos ingresar un registro (un libro) con un valor de clave foránea (codigoeditorial) que no existe en la tabla referenciada (editoriales).NOMBRERESTRICCION es el nombre que le damos a la misma. . Una tabla puede tener varias restricciones "foreign key". tema que veremos posteriormente). tipeamos: alter table libros add constraint FK_libros_codigoeditorial foreign key (codigoeditorial) references editoriales(codigo). la restricción no se aplica y aparece un mensaje de error. La tabla referenciada debe tener definida una restricción "primary key" o "unique". Por ejemplo. si no la tiene. no colocamos el valor para el campo clave foránea (codigoeditorial). la restricción no se agrega. Por ejemplo. si no los cumple.luego de "references" indicamos el nombre de la tabla referenciada y el campo que es clave primaria en la misma.luego de "foreign key". aparece un mensaje de error.

La tabla contiene un campo que hace referencia al afiliado que lo incorporó a la mutual. La sintaxis es la misma. debe eliminarse y volverse a crear.Una restriccion "foreign key" no puede modificarse. La estructura de la tabla es la siguiente: create table afiliados( numero int identity not null. afiliadotitular int. la opción para eliminaciones y actualizaciones. el nombre del campo y la tabla y campo que referencia. 77 . primary key (documento). También informa si la tabla es referenciada por una clave foránea. Una mutual almacena los datos de sus afiliados en una tabla llamada "afiliados". excepto que la tabla se autoreferencia. del cual dependen. el campo "afiliadotitular" almacenará "null". En caso que un afiliado no haya sido incorporado a la mutual por otro afiliado. Para ver información acerca de esta restricción podemos ejecutar el procedimiento almacenado "sp_helpconstraint" junto al nombre de la tabla. Algunos afiliados inscriben a sus familiares. nombre.Restricciones foreign key en la misma tabla La restricción "foreign key". unique (numero) ). documento char(8) not null. Veamos un ejemplo en el cual definimos esta restricción dentro de la misma tabla. que define una referencia a un campo con una restricción "primary key" o "unique" se puede definir entre distintas tablas (como hemos aprendido) o dentro de la misma tabla. Establecemos una restricción "foreign key" para asegurarnos que el número de afiliado que se ingrese en el campo "afiliadotitular" exista en la tabla "afiliados": alter table afiliados add constraint FK_afiliados_afiliadotitular foreign key (afiliadotitular) references afiliados (numero). nombre varchar(30). el estado (temas que veremos más adelante). Nos muestra el tipo. .

Si intentamos eliminar un afiliado que es titular de otros afiliados. la opción de la restricción "foreign key" es "no action". La sintaxis completa para agregar esta restricción a una tabla es la siguiente: alter table TABLA1 add constraint NOMBRERESTRICCION foreign key (CAMPOCLAVEFORANEA) references TABLA2(CAMPOCLAVEPRIMARIA) on delete OPCION on update OPCION. dicho cambio se extiende al valor de clave externa de la otra tabla (integridad referencial en cascada). se genere un error y la acción no se realice. Estas cláusulas especifican cómo debe actuar SQL Server frente a eliminaciones y modificaciones de las tablas referenciadas en la restricción. si eliminamos o modificamos un valor de campo definido con una restricción "primary key" o "unique". Lo mismo sucede si intentamos actualizar un valor de clave primaria de una tabla referenciada por una "foreign key" existente en la tabla principal. a menos que se haya especificado la acción en cascada (próximo tema). y se intenta eliminar un registro de la tabla referenciada (editoriales) cuyo valor de clave primaria (codigo) existe en la tabla principal (libros). también se eliminen o modifiquen. SQL Server controlará que dicho número exista en la tabla.Luego de aplicar esta restricción. no se podrá hacer. si no existe. si al agregar una restricción foreign key: .no se especifica acción para eliminaciones (o se especifica "no_action"). para eliminaciones."cascade": indica que si eliminamos o actualizamos un valor de la clave primaria en la tabla referenciada (TABLA2). Si intentamos eliminar un registro de la tabla referenciada por una restricción "foreign key" cuyo valor de clave primaria existe referenciada en la tabla que tiene dicha restricción. Las opciones para estas cláusulas son las siguientes: . es decir. Sintetizando. por defecto. los registros coincidentes en la tabla principal (TABLA1). es la opción predeterminada. . Esto sucede porque."no action": indica que si intentamos eliminar o actualizar un valor de la clave primaria de la tabla referenciada (TABLA2) que tengan referencia en la tabla principal (TABLA1).Restricciones foreign key (acciones) Continuamos con la restricción "foreign key". cada vez que se ingrese un valor en el campo "afiliadotitular". La restricción "foreign key" tiene las cláusulas "on delete" y "on update" que son opcionales. la acción no se realiza. 78 . mostrará un mensaje de error. la acción no se ejecuta y aparece un mensaje de error. .

eliminamos una editorial de "editoriales" de las cuales hay libros. la acción no se realiza. SQL Server los controla para asegurarse que cumplen con la restricción. se elimina dicha editorial y todos los libros de tal editorial.se especifica "cascade" para actualizaciones ("on update cascade") y se modifica un valor de clave primaria (codigo) de la tabla referenciada (editoriales) que existe en la tabla principal (libros). es posible deshabilitar esta comprobación.nocheck) Sabemos que si agregamos una restricción a una tabla que contiene datos. y se intenta modificar un valor de clave primaria (codigo) de la tabla referenciada (editoriales) que existe en el campo clave foránea (codigoeditorial) de la tabla principal (libros). los datos no van a cumplir la restricción. Podemos hacerlo al momento de agregar la restricción a una tabla con datos. a las demás se las debe eliminar. Veamos un ejemplo. .no se especifica acción para actualizaciones (o se especifica "no_action"). Definimos una restricción "foreign key" a la tabla "libros" estableciendo el campo "codigoeditorial" como clave foránea que referencia al campo "codigo" de la tabla "editoriales"..Restricciones foreign key deshabilitar y eliminar (with check . incluyendo la opción "with nocheck" en la instrucción "alter table". Especificamos la acción en cascada para las actualizaciones y eliminaciones: alter table libros add constraint FK_libros_codigoeditorial foreign key (codigoeditorial) references editoriales(codigo) on update cascade on delete cascade.se especifica "cascade" para eliminaciones ("on delete cascade") y elimina un registro de la tabla referenciada (editoriales) cuyo valor de clave primaria (codigo) existe en la tabla principal(libros). la eliminación de la tabla referenciada (editoriales) se realiza y se eliminan de la tabla principal (libros) todos los registros cuyo valor coincide con el registro eliminado de la tabla referenciada (editoriales). La sintaxis básica al agregar la restriccción "foreign key" es la siguiente: alter table NOMBRETABLA1 with OPCIONDECHEQUEO add constraint NOMBRECONSTRAINT . si se emplea esta opción. La tabla "editoriales" tiene como clave primaria el campo "codigo". Se pueden deshabilitar las restricciones "check" y "foreign key". . Si luego de establecer la restricción anterior. 79 . SQL Server actualiza el registro de la tabla referenciada (editoriales) y todos los registros coincidentes en la tabla principal (libros). se modifica en "editoriales" y todos los valores iguales de "codigoeditorial" de libros también se modifican. Y si modificamos el valor de código de una editorial de "editoriales".

.foreign key (CAMPOCLAVEFORANEA) references NOMBRETABLA2 (CAMPOCLAVEPRIMARIA) on update OPCION on delete OPCION. En el siguiente ejemplo deshabilitamos la restricción creada anteriormente: alter table libros nocheck constraint FK_libros_codigoeditorial. la opción es "check". Para saber si una restricción está habilitada o no. podemos ejecutar el procedimiento almacenado "sp_helpconstraint" y entenderemos lo que informa la columna "status_enabled". La sintaxis general es: alter table NOMBRETABLA OPCIONDECHEQUEO constraint NOMBRERESTRICCION. Pueden emplearse para evitar la comprobación de datos existentes al crear la restricción o para deshabilitar la comprobación de datos al ingresar. eliminar o agregar datos a una tabla sin comprobar la restricción. En el siguiente ejemplo agregamos una restricción "foreign key" que controla que todos los códigos de editorial tengan un código válido. La opción "with OPCIONDECHEQUEO" especifica si se controlan los datos existentes o no con "check" y "nocheck" respectivamente. La comprobación de restricciones se puede deshabilitar para modificar. habilita todas las restricciones que tiene la tabla nombrada ("check" y "foreign key"). dicho código exista en "editoriales". Entonces. es decir. actualizar y eliminar algún registro que infrinja la restricción. La restricción no se aplica en los datos existentes pero si en los siguientes ingresos. si no se especifica. Si se emplea "check constraint all" no se coloca nombre de restricciones. modificaciones y actualizaciones: alter table libros with nocheck add constraint FK_libros_codigoeditorial foreing key (codigoeditorial) references editoriales(codigo). Por defecto. Para habilitar una restricción deshabilitada se ejecuta la misma instrucción pero con la cláusula "check" o "check all": alter table libros check constraint FK_libros_codigoeditorial. las cláusulas "check" y "nocheck" permiten habilitar o deshabilitar restricciones "foreign key" (y "check").

Indica "n/a" en cualquier restricción para la que no se aplique. Indica "n/a" en cualquier restricción para la que no se aplique. Si es una restricción de campo (default o check) indica sobre qué campo fue establecida. . si es una restricción "default". Indica si la acción de actualización es: No Action. Indica "n/a" en cualquier restricción para la que no se aplique. No se puede eliminar una tabla si una restricción "foreign key" hace referencia a ella.constraint_name: nombre de la restricción. En caso de valores predeterminados y reglas. Si es de tabla (primary key o unique) indica el tipo de índice creado.status_enabled: solamente es aplicable para restricciones de tipo "check" y "foreign key". .delete_action: solamente es aplicable para restricciones de tipo "foreign key". or n/a. no actúa o es en cascada. . 81 .Restricciones al crear la tabla . Eliminamos la restricción de "libros": alter table libros drop constraint FK_libros_codigoeditorial. Cascade. el valor por defecto. Indica si está habilitada (Enabled) o no (Disabled). 80 .constraint_keys: Si es una restricción "default" muestra la condición de chequeo. si es una "primary key". "unique" o "foreign key" muestra el/ los campos a los que se aplicaron la restricción.update_action: sólo es aplicable para restricciones de tipo "foreign key". la restricción también se elimina.constraint_type: tipo de restricción. .status_for_replication: solamente es aplicable para restricciones de tipo "check" y "foreign key". Si es una "foreign key" lo indica. Cuando eliminamos una tabla que tiene una restricción "foreign key".Restricciones foreign key (información) El procedimiento almacenado "sp_helpconstraint" devuelve las siguientes columnas: .Podemos eliminar una restricción "foreign key" con "alter table". La sintaxis básica es la misma que para cualquier otra restricción: alter table TABLA drop constraint NOMBRERESTRICCION. "No Action" si no actúa y "Cascade" si es en cascada. . Indica si la acción de eliminación actúa. . el texto que lo define. Indica "n/a" en cualquier restricción para la que no se aplique.

. constraint UQ_libros_tituloautor unique (titulo. también pueden establecerse al momento de crear una tabla (en la instrucción "create table").Hasta el momento hemos agregado restricciones a tablas existentes con "alter table" (manera aconsejada). Podemos aplicar restricciones a nivel de campo (restricción de campo) o a nivel de tabla (restricción de tabla). codigoeditorial tinyint not null. En el siguiente ejemplo creamos la tabla "libros" con varias restricciones: create table libros( codigo int identity.una restricción "default" para el campo "precio" (restricción a nivel de campo). titulo varchar(40).una restricción "foreign key" para establecer el campo "codigoeditorial" como clave externa que haga referencia al campo "codigo" de "editoriales y permita actualizaciones en cascada y no eliminaciones (por defecto "no action"). . precio decimal(5. En el ejemplo anterior creamos: .codigoautor). constraint CK_precio_positivo check (precio>=0) ).una restricción "primary key" con índice agrupado para el campo "codigo" (a nivel de tabla). constraint PK_libros_codigo primary key clustered (codigo). constraint FK_libros_autores foreign key (codigoautor) references autores(codigo) on update cascade. . .2) constraint DF_precio default (0). codigoautor int not null.una restricción "check" para el campo "precio" que no admita valores negativos.una restricción "unique" con índice no agrupado (por defecto) para los campos "titulo" y "codigoautor" (a nivel de tabla). constraint FK_libros_editorial foreign key (codigoeditorial) references editoriales(codigo) on update cascade.una restricción "foreign key" para establecer el campo "codigoautor" como clave externa que haga referencia al campo "codigo" de "autores" y permita actualizaciones en cascada y no eliminaciones. . .

Agregar y eliminar campos ( alter table . modificar y eliminar campos de una tabla. Para obtener los datos necesarios de ambas tablas en una sola consulta necesitamos realizar una unión: select nombre. Puede dividir una consulta compleja en varias consultas "select" y luego emplear el operador "union" para combinarlas. Podemos utilizarla para agregar. domicilio from profesores. Puede emplear la cláusula "order by".drop) "alter table" permite modificar la estructura de una tabla.Unión El operador "union" combina el resultado de dos o más instrucciones "select" en un único resultado.add . Es necesario que las tablas referenciadas tengan tipos de datos similares. Para agregar un nuevo campo a una tabla empleamos la siguiente sintaxis básica: alter table NOMBRETABLA . Se deben especificar los nombres de los campos en la primera instrucción "select". 83 . el segundo. 82 . El primer "select" devuelve el nombre y domicilio de todos los alumnos. la misma cantidad de campos y el mismo orden de campos en la lista de selección de cada consulta. la tabla referenciada debe existir. Una academia de enseñanza almacena los datos de los alumnos en una tabla llamada "alumnos" y los datos de los profesores en otra denominada "profesores". Se usa cuando los datos que se quieren obtener pertenecen a distintas tablas y no se puede acceder a ellos con una sola consulta. No se incluyen las filas duplicadas en el resultado. a menos que coloque la opción "all".Si definimos una restricción "foreign key" al crear una tabla. Los encabezados del resultado de una unión son los que se especifican en el primer "select". el nombre y domicilio de todos los profesores. La academia necesita el nombre y domicilio de profesores y alumnos para enviarles una tarjeta de invitación. domicilio from alumnos union select nombre.

Puede verificarse la alteración de la estructura de la tabla ejecutando el procedimiento almacenado "sp_columns". Podemos eliminar varios campos en una sola sentencia: alter table libros drop column editorial. que acepta valores nulos: alter table libros add cantidad tinyint. de tipo tinyint. Para eliminar campos de una tabla la sintaxis básica es la siguiente: alter table NOMBRETABLA drop column NOMBRECAMPO.alter) Hemos visto que "alter table" permite modificar la estructura de una tabla.add NOMBRENUEVOCAMPO DEFINICION. 84 . No puede eliminarse un campo si es el único en la tabla. En el ejemplo anterior.Alterar campos (alter table . En el siguiente ejemplo agregamos el campo "cantidad" a la tabla "libros". SQL Server no permite agregar campos "not null" a menos que se especifique un valor por defecto: alter table libros add autor varchar(20) not null default 'Desconocido'. se agregó una restricción "default" para el nuevo campo. No pueden eliminarse los campos que son usados por un índice o tengan restricciones. Al agregar un campo puede especificarse que sea "identity" (siempre que no exista otro campo identity). La sintaxis básica para modificar un campo existente es la siguiente: . También podemos utilizarla para modificar campos de una tabla.edicion. En el siguiente ejemplo eliminamos el campo "precio" de la tabla "libros": alter table libros drop column precio. que puede verificarse ejecutando el procedimiento almacenado "sp_helpconstraint".

. No permite modificar: . .alter table NOMBRETABLA alter column CAMPO NUEVADEFINICION. En el siguiente ejemplo alteramos el campo "precio" de la tabla "libros" que fue definido "decimal(6. el campo "titulo" de tipo varchar(30) y una restricción "unique" con índice agrupado: alter table libros add titulo varchar(30) constraint UQ_libros_autor unique clustered.2) not null" para que no acepte valores nulos: alter table libros alter column precio decimal(6.). se puede ampliar la longitud de un campo de tipo caracter.un campo que es usado en un campo calculado. ntext y timestamp. un campo int guarda un valor 300 y se pretende modificarlo a tinyint.agregando o quitando el atributo "identity".2) null. Agregamos a la tabla "libros".Agregar campos y restricciones (alter table) Podemos agregar un campo a una tabla y en el mismo momento aplicarle una restricción. SQL Server tiene algunas excepciones al momento de modificar los campos.campos que son parte de índices o tienen restricciones. Modificamos el campo "titulo" extendiendo su longitud y para que NO admita valores nulos: alter table libros alter column titulo varchar(40) not null.campos que afecten a los datos existentes cuando una tabla contiene registros (ejemplo: un campo contiene valores nulos y se pretende redefinirlo como "not null".campos de tipo text. por ejemplo. la sintaxis básica es la siguiente: alter table TABLA add CAMPO DEFINICION constraint NOMBRERESTRICCION TIPO. Para agregar un campo y establecer una restricción. . . . 85 . image. etc. a menos que el cambio no afecte al índice o a la restricción.

Agregamos a la tabla "libros", el campo "codigo" de tipo int identity not null y una restricción "primary key" con índice no agrupado: alter table libros add codigo int identity not null constraint PK_libros_codigo primary key nonclustered; Agregamos a la tabla "libros", el campo "precio" de tipo decimal(6,2) y una restricción "check": alter table libros add precio decimal(6,2) constraint CK_libros_precio check (precio>=0); 86 - Campos calculados

Un campo calculado es un campo que no se almacena físicamente en la tabla. SQL Server emplea una fórmula que detalla el usuario al definir dicho campo para calcular el valor según otros campos de la misma tabla. Un campo calculado no puede: - definirse como "not null". - ser una subconsulta. - tener restricción "default" o "foreign key". - insertarse ni actualizarse. Puede ser empleado como llave de un índice o parte de restricciones "primary key" o "unique" si la expresión que la define no cambia en cada consulta. Creamos un campo calculado denominado "sueldototal" que suma al sueldo básico de cada empleado la cantidad abonada por los hijos (100 por cada hijo): create table empleados( documento char(8), nombre varchar(10), domicilio varchar(30), sueldobasico decimal(6,2), cantidadhijos tinyint default 0, sueldototal as sueldobasico + (cantidadhijos*100) );

También se puede agregar un campo calculado a una tabla existente: alter table NOMBRETABLA add NOMBRECAMPOCALCULADO as EXPRESION; alter table empleados add sueldototal as sueldo+(cantidadhijos*100); Los campos de los cuales depende el campo calculado no pueden eliminarse, se debe eliminar primero el campo calculado. 87 - Tipo de dato definido por el usuario (crear - informacion)

Cuando definimos un campo de una tabla debemos especificar el tipo de datos, sabemos que los tipos de datos especifican el tipo de información (caracteres, números, fechas) que pueden almacenarse en un campo. SQL Server proporciona distintos tipos de datos del sistema (char, varchar, int, decimal, datetime, etc.) y permite tipos de datos definidos por el usuario siempre que se basen en los tipos de datos existentes. Se pueden crear y eliminar tipos de datos definidos por el usuario. Se emplean cuando varias tablas deben almacenar el mismo tipo de datos en un campo y se quiere garantizar que todas tengan el mismo tipo y longitud. Para darle un nombre a un tipo de dato definido por el usuario debe considerar las mismas reglas que para cualquier identificador. No puede haber dos objetos con igual nombre en la misma base de datos. Para crear un tipo de datos definido por el usuario se emplea el procedimiento almacenado del sistema "sp_addtype". Sintaxis básica: exec sp_addtype NOMBRENUEVOTIPO, 'TIPODEDATODELSISTEMA', 'OPCIONNULL'; Creamos un tipo de datos definido por el usuario llamado "tipo_documento" que admite valores nulos: exec sp_addtype tipo_documento, 'char(8)', 'null'; Ejecutando el procedimiento almacenado "sp_help" junto al nombre del tipo de dato definido por el usuario se obtiene información del mismo (nombre, el tipo de dato en que se basa, la longitud, si acepta valores nulos, si tiene valor por defecto y reglas asociadas). También podemos consultar la tabla "systypes" en la cual se almacena información de todos los tipos de datos: select name from systypes; 88 - Tipo de dato definido por el usuario (asociación de reglas)

Se puede asociar una regla a un tipo de datos definido por el usuario. Luego de crear la regla se establece la asociación; la sintaxis es la siguiente: exec sp_bindrule NOMBREREGLA, 'TIPODEDATODEFINIDOPORELUSUARIO', 'futureonly'; El parámetro "futureonly" es opcional, especifica que si existen campos (de cualquier tabla) con este tipo de dato, no se asocien a la regla; si creamos una nueva tabla con este tipo de dato, si deberán cumplir la regla. Si no se especifica este parámetro, todos los campos de este tipo de dato, existentes o que se creen posteriormente (de cualquier tabla), quedan asociados a la regla. Recuerde que SQL Server NO controla los datos existentes para confirmar que cumplen con la regla, si no los cumple, la regla se asocia igualmente; pero al ejecutar una instrucción "insert" o "update" muestra un mensaje de error. Si asocia una regla a un tipo de dato definido por el usuario que tiene otra regla asociada, esta última la reemplaza. Para quitar la asociación, empleamos el mismo procedimiento almacenado que aprendimos cuando quitamos asociaciones a campos, ejecutamos el procedimiento almacenado "sp_unbindrule" seguido del nombre del tipo de dato al que está asociada la regla: exec sp_unbindrule 'TIPODEDATODEFINIDOPORELUSUARIO'; Si asocia una regla a un campo cuyo tipo de dato definido por el usuario ya tiene una regla asociada, la nueva regla se aplica al campo, pero el tipo de dato continúa asociado a la regla. La regla asociada al campo prevalece sobre la asociada al tipo de dato. Por ejemplo, tenemos un campo "precio" de un tipo de dato definido por el usuario "tipo_precio", este tipo de dato tiene asociada una regla "RG_precio0a99" (precio entre 0 y 99), luego asociamos al campo "precio" la regla "RG_precio100a500" (precio entre 100 y 500); al ejecutar una instrucción "insert" admitirá valores entre 100 y 500, es decir, tendrá en cuenta la regla asociada al campo, aunque vaya contra la regla asociada al tipo de dato. Un tipo de dato definido por el usuario puede tener una sola regla asociada. Cuando obtenemos información del tipo da dato definido por el usuario ejecutando "sp_help", en la columna "rule_name" se muestra el nombre de la regla asociada a dicho tipo de dato; muestran "none" cuando no tiene regla asociada. 89 - Tipo de dato definido por el usuario (valores predeterminados)

Se puede asociar un valor predeterminado a un tipo de datos definido por el usuario. Luego de crear un valor predeterminado, se puede asociar a un tipo de dato definido por el usuario con la siguiente sintaxis: exec sp_bindefault NOMBREVALORPREDETERMINADO, 'TIPODEDATODEFINIDOPORELUSUARIO','futureonly';

todos los campos de este tipo de dato.Tipo de dato definido por el usuario (eliminar) Podemos eliminar un tipo de dato definido por el usuario con el procedimiento almacenado "sp_droptype": exec sp_droptype TIPODEDATODEFINIDOPORELUSUARIO. Eliminamos el tipo de datos definido por el usuario llamado "tipo_documento": exec sp_droptype tipo_documento. Si intentamos eliminar un tipo de dato inexistente. Podemos averiguar si un tipo de dato definido por el usuario existe para luego eliminarlo: if exists (select *from systypes where name = 'NOMBRETIPODEDATODEFINIDOPORELUSUARIO') . 90 . el último lo reemplaza. muestra "none" cuando no tiene ningún valor predeterminado asociado. si creamos una nueva tabla con este tipo de dato. Debe tener en cuenta que NO se puede aplicar una restricción "default" en un campo con un tipo de datos definido por el usuario si dicho campo o tipo de dato tienen asociado un valor predeterminado. no se asocien al valor predeterminado. Si asocia un valor predeterminado a un tipo de dato definido por el usuario que tiene otro valor predeterminado asociado. el valor predeterminado no queda asociado en el campo que tiene la restricción "default". en la columna "default_name" se muestra el nombre del valor predeterminado asociado a dicho tipo de dato. Si un campo de un tipo de dato definido por el usuario tiene una restricción "default" y luego se asocia un valor predeterminado al tipo de dato. si estará asociado al valor predeterminado. Para quitar la asociación. aparece un mensaje indicando que no existe. existentes o que se creen posteriormente (de cualquier tabla). quedan asociados al valor predeterminado. Los tipos de datos definidos por el usuario se almacenan en la tabla del sistema "systypes".El parámetro "futureonly" es opcional. Cuando obtenemos información del tipo da dato definido por el usuario ejecutando "sp_help". especifica que si existen campos (de cualquier tabla) con este tipo de dato. Si no se especifica este parámetro. Un tipo de dato definido por el usuario puede tener un solo valor predeterminado asociado. empleamos el mismo procedimiento almacenado que aprendimos cuando quitamos asociaciones a campos: sp_unbindefault 'TIPODEDATODEFINIDOPORELUSUARIO'.

si es así. entonces se la divide en varios pasos lógicos y se obtiene el resultado con una única instrucción y cuando la consulta depende de los resultados de otra consulta. si una tabla tiene un campo definido con tal tipo de dato. por ejemplo. 3. desaparecen las asociaciones de las reglas y valores predeterminados. Hay tres tipos básicos de subconsultas: 1.en lugar de una expresión. no se eliminan. 91 . Se pueden emplear subconsultas: . No se puede eliminar un tipo de datos definido por el usuario si alguna tabla (u otro objeto) hace uso de él.que retornen un conjunto de registros de varios campos en lugar de una tabla o para obtener el mismo resultado que una combinación (join). se combinan con "in". "update" o "delete" (o en otra subconsulta). Generalmente. Las subconsultas se emplean cuando una consulta es muy compleja. se admiten hasta 32 niveles de anidación. pero tales reglas y valores predeterminados. una subconsulta se puede reemplazar por combinaciones y estas últimas son más eficientes. "some" y "all". siguen existiendo en la base de datos. los que testean la existencia con "exists". . Las subconsultas se DEBEN incluir entre paréntesis. Reglas a tener en cuenta al emplear subconsultas: . Consultamos la tabla "systypes" para ver si existe el tipo de dato "tipo_documento". "insert". Si eliminamos un tipo de datos definido por el usuario. Puede haber subconsultas dentro de subconsultas. siempre que devuelvan un solo valor o una lista de valores. lo eliminamos: if exists (select *from systypes where name = 'tipo_documento') exec sp_droptype tipo_documento. las que retornan un solo valor escalar que se utiliza con un operador de comparación o en lugar de una expresión. 2. o los operadores "any".Subconsultas Una subconsulta (subquery) es una sentencia "select" anidada en otra sentencia "select". las que retornan una lista de valores.exec sp_droptype TIPODEDATODEFINIDOPORELUSUARIO.

92 . anteriormente debíamos averiguar en una consulta el precio del libro más costoso y luego."order by" puede emplearse solamente si se especifica "top" también. . ."distinct" no puede usarse con subconsultas que incluyan "group by".si una tabla se nombra solamente en un subconsulta y no en la consulta externa.. en otra consulta.las subconsultas luego de un operador de comparación (que no es seguido por "any" o "all") no pueden incluir cláusulas "group by" ni "having". Si queremos saber el precio de un determinado libro y la diferencia con el precio del libro más costoso. calcular la diferencia con el valor del libro que solicitamos. . . Las subconsultas que retornan un solo valor escalar se utiliza con un operador de comparación o en lugar de una expresión: select CAMPOS from TABLA where CAMPO OPERADOR (SUBCONSULTA).no pueden emplearse las cláusulas "compute" y "compute by". Podemos conseguirlo en una sola sentencia combinando dos consultas: . select CAMPO OPERADOR (SUBCONSULTA) from TABLA. . . este debe ser compatible con el campo en la lista de selección de la subconsulta.no se pueden emplear subconsultas que recuperen campos de tipos text o image. .la lista de selección de una subconsulta que va luego de un operador de comparación puede incluir sólo una expresión o campo (excepto si se emplea "exists" y "in"). .una subconsulta puede estar anidada dentro del "where" o "having" de una consulta externa o dentro de otra subconsulta. los campos no serán incluidos en la salida (en la lista de selección de la consulta externa).si el "where" de la consulta exterior incluye un campo. Dicha subconsulta debe devolver un valor escalar (o una lista de valores de un campo). .Subconsultas como expresión Una subconsulta puede reemplazar una expresión.una vista creada con una subconsulta no puede actualizarse.

select titulo. Recuerde que la lista de selección de una subconsulta que va luego de un operador de comparación puede incluir sólo una expresión o campo (excepto si se emplea "exists" o "in"). precio from libros where precio= (select max(precio) from libros). "insert". En el ejemplo anterior se muestra el título. 93 . Se pueden emplear en "select".autor. . Para actualizar un registro empleando subconsulta la sintaxis básica es la siguiente: update TABLA set CAMPO=NUEVOVALOR where CAMPO= (SUBCONSULTA). las subconsultas que retornan una lista de valores reemplazan a una expresión en una cláusula "where" que contiene la palabra clave "in". precio-(select max(precio) from libros) as diferencia from libros where titulo='Uno'. No olvide que las subconsultas luego de un operador de comparación (que no es seguido por "any" o "all") no pueden incluir cláusulas "group by". Para eliminar registros empleando subconsulta empleamos la siguiente sintaxis básica: delete from TABLA where CAMPO=(SUBCONSULTA). "update" y "delete".Subconsultas con in Vimos que una subconsulta puede reemplazar una expresión. Queremos saber el título. Dicha subconsulta debe devolver un valor escalar o una lista de valores de un campo. autor y precio del libro más costoso: select titulo. el precio de un libro y la diferencia entre el precio del libro y el máximo valor de precio.precio. Note que el campo del "where" de la consulta exterior es compatible con el valor retornado por la expresión de la subconsulta.

por ejemplo.El resultado de una subconsulta con "in" (o "not in") es una lista.where EXPRESION in (SUBCONSULTA).. Si es posible. son más eficientes. Luego que la subconsulta retorna resultados. pero una subconsulta no siempre puede reemplazarse por una combinación que retorne el mismo resultado. Podemos reemplazar por un "join" la consulta anterior: select distinct nombre from editoriales as e join libros on codigoeditorial=e. la consulta exterior los usa. así puede verificar que retorna lo necesario. La sintaxis básica es la siguiente: . Una combinación (join) siempre puede ser expresada como una subconsulta. es aconsejable emplear combinaciones en lugar de subconsultas. La subconsulta (consulta interna) retorna una lista de valores de un solo campo (codigo) que la consulta exterior luego emplea al recuperar los datos. Este ejemplo muestra los nombres de las editoriales que ha publicado libros de un determinado autor: select nombre from editoriales where codigo in (select codigoeditorial from libros where autor='Richard Bach'). .. También podemos buscar valores No coincidentes con una lista de valores que retorna una subconsulta. las editoriales que no han publicado libros de un autor específico: select nombre from editoriales where codigo not in (select codigoeditorial from libros where autor='Richard Bach').codigo where autor='Richard Bach'. porque a veces resulta difícil verlo en consultas anidadas. Se recomienda probar las subconsultas antes de incluirlas en una consulta exterior.

sino "false". es decir. La sintaxis básica es: .codigo from editoriales as e join libros as l on codigoeditorial=e. si los libros de "Borges" coinciden con ALGUNA de las editoriales que publicó libros de "Richard Bach": select titulo from libros where autor='Borges' and codigoeditorial = any (select e. luego. la consulta externa compara cada valor de "codigoeditorial" con cada valor de la lista devolviendo los títulos de "Borges" que coinciden. "all" también compara un valor escalar con una serie de valores.autor='Richard Bach')..94 . Sintaxis: VALORESCALAR OPERADORDECOMPARACION all (SUBCONSULTA). Chequea si TODOS los valores de la lista de la consulta externa se encuentran en la lista de valores devuelta por la consulta interna.all "any" y "some" son sinónimos. La consulta interna (subconsulta) retorna una lista de valores de un solo campo (puede ejecutar la subconsulta como una consulta para probarla). Compara un valor escalar con los valores de un campo y devuelven "true" si la comparación con cada valor de la lista de la subconsulta es verdadera. Queremos saber los títulos de los libros de "Borges" que pertenecen a editoriales que han publicado también libros de "Richard Bach".VALORESCALAR OPERADORDECOMPARACION ANY (SUBCONSULTA). Chequean si alguna fila de la lista resultado de una subconsulta se encuentra el valor especificado en la condición.Subconsultas any . Queremos saber si TODAS las editoriales que publicaron libros de "Borges" coinciden con TODAS las editoriales que publicaron libros de "Richard Bach": select titulo .some . El tipo de datos que se comparan deben ser compatibles..codigo where l.

. es decir.codigo from editoriales as e join libros as l on codigoeditorial=e. si ALGUNO cumple la condición. es mayor a ALGUN precio de "Richard Bach".precio from libros where autor='Borges' and precio > any (select precio from libros where autor='Bach'). Emplear "= any" es lo mismo que emplear "in". El precio de cada libro de "Borges" es comparado con cada valor de la lista de valores retornada por la subconsulta. luego. Emplear "<> all" es lo mismo que emplear "not in". si cumple la condición. se lista. se lista. devuelve los títulos. La consulta interna (subconsulta) retorna una lista de valores de un solo campo (puede ejecutar la subconsulta como una consulta para probarla). El precio de cada libro de "Borges" es comparado con cada valor de la lista de valores retornada por la subconsulta. Veamos la diferencia si empleamos "all" en lugar de "any": select titulo.from libros where autor='Borges' and codigoeditorial = all (select e. Veamos otro ejemplo con un operador de comparación diferente: Queremos saber si ALGUN precio de los libros de "Borges" es mayor a ALGUN precio de los libros de "Richard Bach": select titulo.codigo where l. si es mayor a TODOS los precios de "Richard Bach" (o al mayor).autor='Richard Bach'). si TODOS coinciden. es decir. la consulta externa compara cada valor de "codigoeditorial" con cada valor de la lista.precio from libros where autor='borges' and precio > all (select precio from libros where autor='bach').

preciounitario*cantidad) from Detalles as d where f. A este tipo de subconsulta se la denomina consulta correlacionada. específicamente. el cliente.numero=d. Se necesita una lista de todas las facturas que incluya el número. 96 . la consulta interna devuelve la suma.Recuerde que solamente las subconsultas luego de un operador de comparación al cual es seguido por "any" o "all") pueden incluir cláusulas "group by". el primer "select" (externo) devuelve todos los datos de cada factura. El proceso se repite para el registro de la consulta externa. . (select count(d. la fecha. si existe. la cantidad de artículos comprados y el total: select f.numerofactura) as total from facturas as f. la fecha y el nombre del cliente y una tabla denominada "detalles" en la cual se almacenan los distintos items correspondientes a cada factura: el nombre del artículo.numerofactura) as cantidad.*. se realiza la subconsulta para cada registro de la consulta externa.Exists y No Exists Los operadores "exists" y "not exists" se emplean para determinar si hay o no datos en una lista de valores. la consulta externa pasa otro "numero" a la consulta interna y SQL Server repite la evaluación. Estos operadores pueden emplearse con subconsultas correlacionadas para restringir el resultado de una consulta exterior a los registros que cumplen la subconsulta (consulta interior). el precio (unitario) y la cantidad. el tercer "select" retorna una lista de valores de una sola columna con el total por factura (el número de factura lo toma del "select" exterior). En este caso. la consulta externa pasa un valor de "numero" a la consulta interna. 95 .numero) se compara con el campo de la tabla externa. Estos operadores retornan "true" (si las subconsultas retornan registros) o "false" (si las subconsultas no retornan registros).numeroitem) from Detalles as d where f.numero=d. La consulta interna toma ese valor y determina si existe en "detalles". (select sum(d. El campo de la tabla dentro de la subconsulta (f. La consulta interna se evalúa tantas veces como registros tiene la consulta externa. El segundo "select" retorna una lista de valores de una sola columna con la cantidad de items por factura (el número de factura lo toma del "select" exterior).Subconsultas correlacionadas Un almacén almacena la información de sus ventas en una tabla llamada "facturas" en la cual guarda el número de factura.

Cuando se coloca en una subconsulta el operador "exists", SQL Server analiza si hay datos que coinciden con la subconsulta, no se devuelve ningún registro, es como un test de existencia; SQL Server termina la recuperación de registros cuando por lo menos un registro cumple la condición "where" de la subconsulta. La sintaxis básica es la siguiente: ... where exists (SUBCONSULTA); En este ejemplo se usa una subconsulta correlacionada con un operador "exists" en la cláusula "where" para devolver una lista de clientes que compraron el artículo "lapiz": select cliente,numero from facturas as f where exists (select *from Detalles as d where f.numero=d.numerofactura and d.articulo='lapiz'); Puede obtener el mismo resultado empleando una combinación. Podemos buscar los clientes que no han adquirido el artículo "lapiz" empleando "if not exists": select cliente,numero from facturas as f where not exists (select *from Detalles as d where f.numero=d.numerofactura and d.articulo='lapiz'); 97 - Subconsulta simil autocombinación

Algunas sentencias en las cuales la consulta interna y la externa emplean la misma tabla pueden reemplazarse por una autocombinación. Por ejemplo, queremos una lista de los libros que han sido publicados por distintas editoriales. select distinct l1.titulo from libros as l1 where l1.titulo in (select l2.titulo from libros as l2 where l1.editorial <> l2.editorial);

En el ejemplo anterior empleamos una subconsulta correlacionada y las consultas interna y externa emplean la misma tabla. La subconsulta devuelve una lista de valores por ello se emplea "in" y sustituye una expresión en una cláusula "where". Con el siguiente "join" se obtiene el mismo resultado: select distinct l1.titulo from libros as l1 join libros as l2 on l1.titulo=l1.titulo and l1.autor=l2.autor where l1.editorial<>l2.editorial; Otro ejemplo: Buscamos todos los libros que tienen el mismo precio que "El aleph" empleando subconsulta: select titulo from libros where titulo<>'El aleph' and precio = (select precio from libros where titulo='El aleph'); La subconsulta retorna un solo valor. Buscamos los libros cuyo precio supere el precio promedio de los libros por editorial: select l1.titulo,l1.editorial,l1.precio from libros as l1 where l1.precio > (select avg(l2.precio) from libros as l2 where l1.editorial= l2.editorial); Por cada valor de l1, se evalúa la subconsulta, si el precio es mayor que el promedio. 98 - Subconsulta en lugar de una tabla

Se pueden emplear subconsultas que retornen un conjunto de registros de varios campos en lugar de una tabla. Se la denomina tabla derivada y se coloca en la cláusula "from" para que la use un "select" externo. La tabla derivada debe ir entre paréntesis y tener un alias para poder referenciarla. La sintaxis básica es la siguiente:

select ALIASdeTABLADERIVADA.CAMPO from (TABLADERIVADA) as ALIAS; La tabla derivada es una subsonsulta. Podemos probar la consulta que retorna la tabla derivada y luego agregar el "select" externo: select f.*, (select sum(d.precio*cantidad) from Detalles as d where f.numero=d.numerofactura) as total from facturas as f; La consulta anterior contiene una subconsulta correlacionada; retorna todos los datos de "facturas" y el monto total por factura de "detalles". Esta consulta retorna varios registros y varios campos y será la tabla derivada que emplearemos en la siguiente consulta: select td.numero,c.nombre,td.total from clientes as c join (select f.*, (select sum(d.precio*cantidad) from Detalles as d where f.numero=d.numerofactura) as total from facturas as f) as td on td.codigocliente=c.codigo; La consulta anterior retorna, de la tabla derivada (referenciada con "td") el número de factura y el monto total, y de la tabla "clientes", el nombre del cliente. Note que este "join" no emplea 2 tablas, sino una tabla propiamente dicha y una tabla derivada, que es en realidad una subconsulta. 99 - Subconsulta (update - delete)

Dijimos que podemos emplear subconsultas en sentencias "insert", "update", "delete", además de "select". La sintaxis básica para realizar actualizaciones con subconsulta es la siguiente: update TABLA set CAMPO=NUEVOVALOR where CAMPO= (SUBCONSULTA); Actualizamos el precio de todos los libros de editorial "Emece": update libros set precio=precio+(precio*0.1) where codigoeditorial=

codigo from editoriales as e join libros on codigoeditorial=e. La sintaxis básica para realizar eliminaciones con subconsulta es la siguiente: delete from TABLA where CAMPO in (SUBCONSULTA).codigo where autor='Juan Perez'). Podemos ingresar registros en una tabla empleando un "select". Eliminamos todos los libros de las editoriales que tiene publicados libros de "Juan Perez": delete from libros where codigoeditorial in (select e. Un profesor almacena las notas de sus alumnos en una tabla llamada "alumnos". Ingresamos registros en la tabla "aprobados" seleccionando registros de la tabla "alumnos": . La subconsulta es una combinación que retorna una lista de valores que la consulta externa emplea al seleccionar los registros para la eliminación. 100 . "update" y "delete". La subconsulta retorna un único valor.(select codigo from editoriales where nombre='Emece'). con algunos campos iguales a la tabla "alumnos" pero en ella solamente almacenará los alumnos que han aprobado el ciclo. Tiene otra tabla llamada "aprobados". También podemos hacerlo con un join. también puede estar dentro de un "insert". La sintaxis básica es la siguiente: insert into TABLAENQUESEINGRESA (CAMPOSTABLA1) select (CAMPOSTABLACONSULTADA) from TABLACONSULTADA.Subconsulta (insert) Aprendimos que una subconsulta puede estar dentro de un "select".

nota) from alumnos.Crear tabla a partir de otra (select .nota) select (documento. se crea una nueva tabla y se inserta en ella el resultado de una consulta a otra tabla. .insert into aprobados (documento. 101 . La tabla "editoriales". se puede insertar registros en una tabla con la salida devuelta por una consulta a otra tabla. La tabla libros contiene varios registros. para ello escribimos la consulta y le anteponemos "insert into" junto al nombre de la tabla en la cual ingresaremos los registros y los campos que se cargarán (si se ingresan todos los campos no es necesario listarlos). Entonces. Se pueden insertar valores en una tabla con el resultado de una consulta que incluya cualquier tipo de "join".into) Podemos crear una tabla e insertar datos en ella en una sola sentencia consultando otra tabla (o varias) con esta sintaxis: select CAMPOSNUEVATABLA into NUEVATABLA from TABLA where CONDICION. La cantidad de columnas devueltas en la consulta debe ser la misma que la cantidad de campos a cargar en el "insert". si se quiere dar otro nombre a los campos de la nueva tabla se deben especificar alias. contendrá solamente un campo llamado "nombre". que no existe. Podemos crear la tabla "editoriales" con el campo "nombre" consultando la tabla "libros" y en el mismo momento insertar la información: select distinct editorial as nombre into editoriales from libros. tipo de dato y valores almacenados que los campos listados de la tabla consultada. Los campos de la nueva tabla tienen el mismo nombre. Tenemos la tabla "libros" de una librería y queremos crear una tabla llamada "editoriales" que contenga los nombres de las editoriales. Es decir. La tabla "editoriales" se ha creado con el campo "nombre" seleccionado del campo "editorial" de "libros".

. "go" es un signo de finalización de un lote de sentencias..go Esto solo se aplica cuando instale el SQL Server en su máquina. Habrá notado que no se puede ejecutar un procedimiento almacenado luego de otras sentencias a menos que se incluya "execute" (o "exec"). muestra un mensaje de error porque no puede procesar ambas sentencias como un solo lote. create procedure. No es una sentencia. 102 .. exec sp_helpconstraint empleados. Para que no ocurra debemos tipear: select *from empleados. create trigger. into" con combinaciones. funciones de agrupamiento y "order by" en las consultas. go sp_helpconstraint empleados. Las sentencias no deben ocupar la misma linea en la que está "go".. go create rule. se coloca "into" seguido del nombre de la nueva tabla y se sigue con la consulta. sp_helpconstraint empleados.create view. Cada una de ellas necesita ejecutarse separándolas con "go". es un comando. o separar los lotes con "go": select *from empleados. luego de la lista de selección de campos de la tabla a consultar. Podemos emplear "group by". El lote de sentencias está compuesto por todas las sentencias antes de "go" o todas las sentencias entre dos "go". Las siguientes sentencias no pueden ejecutarse en el mismo lote: create rule.. para crear una tabla que contenga datos de 2 o más tablas. create default.. si tipeamos: select *from empleados. Por ejemplo. También podemos emplear "select.. Por ejemplo: create table. go .Entonces.

una unión de varias tablas. Las vistas permiten: .Recuerde que si coloca "go" no debe incluir el "punto y coma" (. . un resumen estadístico de una tabla. .mejorar el rendimiento: se puede evitar tipear instrucciones repetidamente almacenando en una vista el resultado de una consulta compleja que incluya información de varias tablas.ocultar información: permitiendo el acceso a algunos datos y manteniendo oculto el resto de la información que no se incluye en la vista. pudiendo modificar tales datos. Una vista se define usando un "select". en lugar de concederle permisos para acceder a ciertos campos. Las tablas consultadas en una vista se llaman tablas base. una vista almacena una consulta como un objeto para utilizarse posteriormente. En general. así se protegen las tablas base de cambios en su estructura.simplificar la administración de los permisos de usuario: se pueden dar al usuario permisos para que solamente pueda acceder a los datos a través de vistas. Podemos crear vistas con: un subconjunto de registros y campos de una tabla. Entonces. se puede dar un nombre a cualquier consulta y almacenarla como una vista. Una vista es como una tabla virtual que almacena una consulta.Vistas Una vista es una alternativa para mostrar datos de varias tablas. No está de más recordar que esto solo se aplica cuando instale el SQL Server en su máquina y ejecute los comandos desde el Query Analyzer. una combinación de varias tablas. La sintaxis básica parcial para crear una vista es la siguiente: create view NOMBREVISTA as SENTENCIASSELECT from TABLA. Los datos accesibles a través de la vista no están almacenados en la base de datos como un objeto. Una vista suele llamarse también tabla virtual porque los resultados que retorna y la manera de referenciarlas es la misma que para una tabla.) al finalizar una instrucción. combinación de vistas y tablas. 103 . un subconjunto de otra vista. El usuario opera con los datos de una vista como si se tratara de una tabla. El contenido de una vista se muestra con un "select": .

Note que en la vista definida en el ejemplo.select *from NOMBREVISTA. aparecería un mensaje de error. Otra sintaxis es la siguiente: create view NOMBREVISTA (NOMBRESDEENCABEZADOS) as SENTENCIASSELECT from TABLA. s. cantidadhijos from empleados as e join secciones as s on codigo=seccion Para ver la información contenida en la vista creada anteriormente tipeamos: select *from vista_empleados. Se debe colocar nombre de campo cuando es un campo calculado o si hay 2 campos con el mismo nombre.sexo. por ejemplo. Los nombres de los campos y expresiones de la consulta que define una vista DEBEN ser únicos (no puede haber dos campos o encabezados con igual nombre). si no lo hubiésemos hecho aparecería un mensaje de error porque dicha expresión DEBE tener un encabezado. si sucediera.nombre" le colocamos un alias porque ya había un encabezado (el alias de la concatenación) llamado "nombre" y no pueden repetirse.nombre) as nombre.count(*) as cantidad from vista_empleados. al campo "s. Para distinguir una tabla de una vista podemos fijar una convención para darle nombres. colocar el sufijo “vista” y luego el nombre de las tablas consultadas en ellas. Los campos y expresiones de la consulta que define una vista DEBEN tener un nombre.nombre as seccion. Creamos otra vista de "empleados" denominada "vista_empleados_ingreso" que almacena la cantidad de empleados por año: . que es resultado de una combinación en la cual se muestran 4 campos: create view vista_empleados as select (apellido+' '+e. al concatenar los campos "apellido" y "nombre" colocamos un alias. Podemos realizar consultas a una vista como si se tratara de una tabla: select seccion. Note que en el ejemplo. SQL Server no lo coloca por defecto. En el siguiente ejemplo creamos la vista "vista_empleados". Los nombres para vistas deben seguir las mismas reglas que cualquier identificador.

excepto si ha sido encriptado. así que para obtener información de ellos pueden usarse los siguientes procedimientos almacenados del sistema: "sp_help" sin parámetros nos muestra todos los objetos de la base de datos seleccionada. Se pueden construir vistas sobre otras vistas.cantidad) as select datepart(year. SQL Server verifica que existan las tablas a las que se hacen referencia en ella.create view vista_empleados_ingreso (fecha.no puede incluir las cláusulas "compute" ni "compute by" ni la palabra clave "into". incluidas las vistas.no puede combinarse con otras instrucciones en un mismo lote.Vistas (información) Las vistas son objetos.no se pueden crear vistas temporales ni crear vistas sobre tablas temporales.fechaingreso). se emplean los nombres de los campos o alias (que en este caso habría que agregar) colocados en el "select" que define la vista. 104 . . Existen algunas restricciones para el uso de "create view".count(*) from empleados group by datepart(year. obtenemos la fecha de creación. . En la columna "Object_type" aparece "view" si es una vista.no se pueden asociar reglas ni valores por defecto a las vistas. Al crear una vista. Las vistas se crean en la base de datos activa. los campos y demás información. obtenemos 2 resultados: .fechaingreso) La diferencia es que se colocan entre paréntesis los encabezados de las columnas que aparecerán en la vista. a saber: . Si no los colocamos y empleamos la sintaxis vista anteriormente. Los nombres que se colocan entre paréntesis deben ser tantos como los campos o expresiones que se definen en la vista. "sp_helptext" seguido del nombre de una vista nos muestra el texto que la define. Si le enviamos como argumento el nombre de una vista. . Ejecutando "sp_depends" seguido del nombre de un objeto. Se aconseja probar la sentencia "select" con la cual definiremos la vista antes de crearla para asegurarnos que el resultado que retorna es el imaginado. propietario.

. aparece 'V'. etc.--búsqueda con comodín 105 .nombre. Nos muestra nombre y varios datos de todos los objetos de la base de datos actual. También se puede consultar la tabla del sistema "sysobjects": select *from sysobjects.nombre y tipo de los objetos que dependen del objeto nombrado. restricciones. La columna "xtype" indica el tipo de objeto. las tablas referenciadas en la misma. etc. podemos tipear: select *from sysobjects where xtype='V' and-.tipo vista name like 'vista%'. Si ejecutamos el procedimiento seguido del nombre de una tabla: sp_depends empleados. campos. es decir. vistas. aparecen los objetos que dependen de la tabla. tipo. Podemos ocultar el texto que define una vista empleando la siguiente sintaxis al crearla: create view NOMBREVISTA with encryption as SENTENCIASSELECT from TABLA. Si queremos ver todas las vistas creadas por nosotros. . de los objetos de los cuales depende el objeto nombrado y . si es una vista.vistas (encriptar) Podemos ver el texto que define una vista ejecutando el procedimiento almacenado del sistema "sp_helptext" seguido del nombre de la vista: sp_helptext NOMBREVISTA. aparecen las tablas (y demás objetos) de las cuales depende la vista. Si ejecutamos el procedimiento "sp_depends" seguido del nombre de una vista: sp_depends vista_empleados.

Por ejemplo. hay que eliminarla explícitamente. s. se recomienda ejecutar el procedimiento almacenado de sistema "sp_depends" para averiguar si hay objetos que hagan referencia a él. 107 . Creamos una vista con su definición oculta: create view vista_empleados with encryption as select (apellido+' '+e. Si se elimina una tabla a la que hace referencia una vista. Antes de eliminar un objeto. Solo el propietario puede eliminar una vista. Eliminamos la vista denominada "vista_empleados": drop view vista_empleados.Vistas (eliminar) Para quitar una vista se emplea "drop view": drop view NOMBREVISTA. la vista no se elimina."with encryption" indica a SQL Server que codifique las sentencias que definen la vista. 106 .nombre as seccion.Vistas (with check option) Es posible obligar a todas las instrucciones de modificación de datos que se ejecutan en una vista a cumplir ciertos criterios. aparece un mensaje indicando tal situación y el texto no se muestra.nombre) as nombre.sexo. creamos la siguiente vista: create view vista_empleados . cantidadhijos from empleados as e join secciones as s on codigo=seccion Si ejecutamos el procedimiento almacenado del sistema "sp_helptext" seguido del nombre de una vista encriptada.

Vistas (modificar datos de una tabla a través de vistas) Si se modifican los datos de una vista. Si elimina una vista y vuelve a crearla. s. pero no el campo "seccion" porque está restringuido. Además. Se puede insertar. 108 .nombre. La vista definida anteriormente muestra solamente algunos de los datos de los empleados de la sección "Administracion". se modifica la tabla base. teniendo en cuenta lo siguiente. . Podemos actualizar el nombre.nombre='Administracion' with check option. e.pueden generar errores si afectan a campos a las que la vista no hace referencia. Por ejemplo.Vistas modificar (alter view) Para modificar una vista puede eliminarla y volver a crearla o emplear "alter view".as select apellido.nombre as seccion from empleados as e join secciones as s on seccion=codigo where s.la opción "with check option" obliga a todas las instrucciones de modificación que se ejecutan en la vista a cumplir ciertos criterios que se especifican al definir la vista.no se pueden cambiar los campos resultado de un cálculo. las modificaciones que se realizan a las vistas: . actualizar o eliminar datos de una tabla a través de una vista. . solamente se permiten modificaciones a los empleados de esa sección. Con "alter view" se modifica la definición de una vista sin afectar los procedimientos almacenados y los permisos. 109 . apellido y sexo a través de la vista. Pueden modificarse datos de una vista que combina varias tablas pero la modificación solamente debe afectar a una sola tabla. sexo. si se ingresa un registro en una vista que consulta una tabla que tiene campos not null que no están incluidos en la vista. .para eliminar datos de una vista solamente UNA tabla puede ser listada en el "from" de la definicion de la misma. debe reasignar los permisos asociados a ella.no pueden afectar a más de una tabla consultada. Sintaxis básica para alterar una vista: . .

si no encuentra ninguna coincidencia. debe alterar la vista. . en caso de no hacerlo. Finalmente se coloca "end" para indicar que el "case" ha finalizado. se ejecuta el "else".nombre (30 caracteres).domicilio from empleados as e join secciones as s on codigo=seccion Si creó la vista con "with encryption" y quiere modificarla manteniendo la encriptación.nombre as seccion. si encuentra un valor coincidente en algún "where" ejecuta el "then" correspondiente a ese "where". si no hay parte "else" retorna "null". else RESULTADO3 end Por cada valor hay un "when" y un "then".nota (valor entero entre 0 y 10.. Un profesor guarda las notas de sus alumnos de un curso en una tabla llamada "alumnos" que consta de los siguientes campos: .. los nuevos campos no aparecerán en la vista.alter view NOMBREVISTA with encryption--opcional as SELECT En el ejemplo siguiente se altera vista_empleados para agregar el campo "domicilio": alter view vista_empleados with encryption as select (apellido+' '+e. .nombre) as nombre. 110 . esto es porque los campos se seleccionan al ejecutar "create view". s. Si crea una vista con "select *" y luego agrega campos a la estructura de las tablas involucradas. desaparece. cantidadhijos. puede ser nulo).Lenguaje de control de flujo (case) La función "case" compara 2 o más valores y devuelve un resultado. debe colocarla nuevamente. La sintaxis es la siguiente: case VALORACOMPARAR when VALOR1 then RESULTADO1 when VALOR2 then RESULTADO2 .sexo.

condicion= case when nota<4 then 'libre' when nota >=4 and nota<7 then 'regular' when nota>=7 then 'promocionado' . 2 ó 3: 'libre'.. notas de los alumnos y en una columna extra llamada "resultado" empleamos un case que testee la nota y muestre un mensaje diferente si en dicho campo hay un valor: . 5 ó 6: 'regular'. nota. resultado= case nota when 0 then 'libre' when 1 then 'libre' when 2 then 'libre' when 3 then 'libre' when 4 then 'regular' when 5 then 'regular' when 6 then 'regular' when 7 then 'promocionado' when 8 then 'promocionado' when 9 then 'promocionado' when 10 then 'promocionado' end from alumnos. Podemos realizar comparaciones en cada "where". La sintaxis es la siguiente: case when VALORACOMPARAR OPERADOR VALOR1 then RESULTADO1 when VALORACOMPARAR OPERADOR VALOR2 then RESULTADO2 . 8.. está entre 4 y 7 o supera el 7: select nombre. en caso que el valor no encuentre coincidencia con ninguno valor "when". Note que como omitimos la parte "else".7. 1. por ello los valores devueltos son iguales para algunos casos. Esta es la sentencia: select nombre.Queremos mostrar los nombres. retorna "null". Note que cada "where" compara un valor puntual. 9 ó 10: 'promocionado'. else RESULTADO3 end Mostramos los nombres de los alumnos y en una columna extra llamada "resultado" empleamos un case que teste si la nota es menor a 4.0.nota. .4. .

. Veamos un ejemplo. else": testean una condición.. si no hay. if. end. SQL Server ejecuta la sentencia (en este caso. Tales palabras son: begin. ."while": ejecuta repetidamente una instrucción siempre que la condición sea verdadera. queremos mostrar todos los títulos de los cuales no hay libros disponibles (cantidad=0). mostrar un mensaje indicando tal situación: if exists (select *from libros where cantidad=0) (select titulo from libros where cantidad=0) else select 'No hay libros sin stock'."if."begin. ejecuta la sentencia del "else" (si existe)... mostrar un mensaje: if exists (select *from libros where editorial='Emece') begin update libros set precio=precio-(precio*0. se emplean cuando un bloque de sentencias debe ser ejecutado si una condición se cumple y si no se cumple. si no hay. else. si es falsa. break y continue. se debe ejecutar otro bloque de sentencias diferente. queremos hacer un descuento en el precio. end" encierran un bloque de sentencias para que sean tratados como unidad...else 'sin nota' end from alumnos. . una subconsulta) luego del "if" si la condición es verdadera. while. . Podemos emplear "if. goto.. Tenemos nuestra tabla "libros"."break" y "continue": controlan la operación de las instrucciones incluidas en el bucle "while". los bloques de sentencias y procedimientos almacenados. return. Puede utilizar una expresión "case" en cualquier lugar en el que pueda utilizar una expresión... del 10% a todos los libros de una determinada editorial..1) where editorial='Emece' select 'libros actualizados' end . 111 .Lenguaje de control de flujo (if) Existen palabras especiales que pertenecen al lenguaje de control de flujo que controlan la ejecución de las sentencias. waitfor.else" en actualizaciones.. También se puede emplear con "group by" y funciones de agrupamiento. Por ejemplo.

112 . mostramos un mensaje: if exists (select *from libros where cantidad=0) delete from libros where cantidad=0 else select 'No hay registros eliminados. si no hay. Por lo tanto.end". Las variables de usuario comienzan con "@" (arroba) seguido del nombre (sin espacios). Ejemplo: declare @nombre varchar(20) Puede declarar varias variables en una misma sentencia: declare @nombre varchar(20). En el siguiente ejemplo eliminamos los libros cuya cantidad es cero. debemos declarar y emplear la variable en el mismo lote de sentencias. se deben ejecutar 2 sentencias. en otro bloque de sentencias pretendemos emplearla. @edad int No existen variables globales en SQL Server. Las variables de usuario son específicas de cada conexión y son liberadas automáticamente al abandonar la conexión. Una variable debe ser declarada antes de usarse. Note que si la condición es verdadera. Por ejemplo. Una variable declarada existe dentro del entorno en que se declara. porque si declaramos una variable y luego. dicho nombre puede contener cualquier caracter. si ejecutamos estas sentencias en diferentes lotes: .else select 'no hay registros actualizados'.Variables de usuario Las variables nos permiten almacenar un valor y recuperarlo más adelante para emplearlos en otras sentencias... se deben encerrar en un bloque "begin. Una variable local se declara así: declare @NOMBREVARIABLE TIPO colocando "declare" el nombre de la variable que comienza con el símbolo arroba (@) y el tipo de dato. dicha variable ya no existe.

Disponemos punto y coma solo al final de la última instrucción del lote. Una variable puede tener comodines: declare @patron varchar(30) set @patron='B%' select autor from libros where autor like @patron. Una variable a la cual no se le ha asignado un valor contiene "null". la sintaxis es: select @nombre = autor from libros where titulo='Uno' Podemos ver el contenido de una variable con: select @nombre. Si le asignamos un valor resultado de una consulta. La utilidad de las variables consiste en que almacenan valores para utilizarlos en otras consultas. select @variable. Para ello podemos emplear una variable para almacenar el precio más alto: declare @mayorprecio select @mayorprecio:=max(precio) from libros y luego mostrar todos los datos de dicho libro empleando la variable anterior: . Debemos tipear: declare @variable varchar(10) select @variable. Por ejemplo. queremos saber todos los datos del libro con mayor precio de la tabla "libros" de una librería. aparece un mensaje indicando que la variable "@variable" debe ser declarada.declare @variable varchar(10). Se le asigna un valor inicial con "set": set @edad=45 Para almacenar un valor en una variable se coloca el signo igual (=) entre la variable y el valor a asignar.

caracteres unicode y no unicode y datos binarios. en otra sentencia. Para declarar un campo de alguno de estos tipos de datos. NOMBRECAMPO text . Es decir. . (2 GB).Los campos de estos tipos de datos no pueden emplearse para índices. el máximo es de 2000000000 caracteres aprox. "ntext" almacena datos unicode de longitud variable y el máximo es de aproximadamente 1000000000 caracteres. "text" almacena datos binarios no unicode de longitud variable.. de datos binarios. Como estos tipos de datos tiene gran tamaño. ntext e image. . Ninguno de estos tipos de datos admiten argumento para especificar su longitud.select *from libros where precio=@mayorprecio. ntext y image Los tipos de datos "ntext". Se emplean estos tipos de datos para almacenar valores superiores a 8000 caracteres.. 113 . colocamos el nombre del campo seguido del tipo de dato: .No pueden definirse variables de estos tipos de datos. "text" e "image" representan tipos de datos de longitud fija y variable en los que se pueden guardar gran cantidad de información.. SQL Server los almacena fuera de los registros. en bytes.. Una variable puede ser definida con cualquier tipo de dato. en su lugar guarda un puntero (de 16 bytes) que apunta a otro sitio que contiene los datos.La única restricción que puede aplicar a estos tipos de datos es "default". excepto text. "image" es un tipo de dato de longitud variable que puede contener de 0 a 2000000000 bytes (2 GB) aprox. mostramos los datos de todos los libros cuyo precio es igual al valor de la variable. declaramos la variable y guardamos en ella el precio más alto y luego. incluso de un tipo de dato definido por el usuario.. o "varchar".Tipos de datos text. . el tamaño es el doble de los caracteres ingresados (2 GB). Se emplea para almacenar gran cantidad de información o gráficos. No puede emplearse en parámetros de procedimientos almacenados. Otras consideraciones importantes: . como en el caso de los tipos "char".

retorna un puntero a null.CAMPO'. Los argumentos son: el nombre de la tabla y campo y el nombre del puntero a texto que se va a controlar. Retorna 1 si el puntero es válido y 0 si no lo es. 114 . en el registro guarda un puntero (de 16 bytes) que apunta a otro sitio. Sintaxis: textvalid ('TABLA. con las funciones para leer.sinopsis'. Si el campo no tiene texto..Se pueden asociar valores predeterminados pero no reglas a campos de estos tipos de datos.Tipo de dato text . . escribir y actualizar. No se puede emplear "updatetext".ntext e image (punteros) Explicamos anteriormente que como estos tipos de datos tiene gran tamaño. textptr(sinopsis) from libros. Podemos ver esa dirección tipeando la siguiente sentencia: select titulo. El campo debe ser tipo text.No pueden alterarse campos de estos tipos con "alter table". tal valor puede emplearse para manipular los datos de este tipo. ntext o image. . que contiene la dirección en la cual se guardan los datos propiamente dichos. En el campo de tipo "text" no se almacenan los datos sino la dirección en la cual se encuentran los datos. La función "textptr" devuelve el valor del puntero a texto que corresponde al campo text. "writetext" y "readtext" si el puntero no es válido. Si la consulta retorna más de un registro. ntext o image. "textptr" retorna un puntero a texto del último registro devuelto. por ello se debe usar la función "textvalid" para confirmar si el puntero a texto existe. Sintaxis: textptr(CAMPO). La función "textptr" retorna un puntero a texto (valor binario de 16). SQL Server almacena los datos fuera de los registros. La siguiente consulta muestra si los punteros son válidos en cada registro del campo "sinopsis" de la tabla "libros": select titulo. PUNTEROATEXTO). La funcion "textvalid" controla si un puntero a texto es válido. textvalid('libros. textptr(sinopsis)) as 'Puntero valido' from libros.

sinopsis'. @puntero).En el siguiente ejemplo.CANTIDAD: número de bytes o caracteres a leer desde la posición indicada por DESPLAZAMIENTO. empleando la variable: declare @puntero varbinary(16) select @puntero = textptr(sinopsis) from libros where titulo= 'Ilusiones' select textvalid('libros.ntext e image (leer) La función "readtext" lee valores de un campo text. 50 caracteres: declare @puntero varbinary(16) select @puntero=textptr(sinopsis) from libros where codigo=2 readtext libros. se leen 4KB bytes o hasta el final. ntext o image. Solo disponemos punto y coma al final para que SQL Server ejecute todas las instrucciones en un solo lote y exista la variable @puntero. 115 . binary(16). desde la posición 9. . Leemos la información almacenada en el campo "sinopsis" de "libros" del registro con código 2.CAMPO PUNTEROATEXTO DESPLAZAMIENTO CANTIDAD. Sintaxis: readtext TABLA. Analicemos la sintaxis: . .PUNTEROATEXTO: puntero a texto válido. ntext o image. Si al insertar registros se ingresa un valor "null" en un campo "text". comenzando desde una posición y leyendo un específico número de bytes. no se crea un puntero válido. "ntext" o "image" o no se ingresa valor.Tipo de dato text . Si es 0.sinopsis @puntero 9 50. .DESPLAZAMIENTO: número de bytes (para text o image) o caracteres (ntext) que se mueve el puntero antes de comenzar a leer. declaramos una variable de tipo "varbinary" a la cual le asignamos el valor del puntero a texto de un registro y luego vemos si dicho puntero es válido. Para crear un puntero a texto válido ejecute un "insert" o "update" con datos que no sean nulos para el campo text.

@puntero)=1) readtext libros. porque la función "writetext" requiere un puntero válido. no se crea un puntero válido y al intentar leer dicho campo ocurre un error. "DATO" es el texto que almacena. Para evitarlo podemos chequear el puntero antes de pasárselo a la función de lectura: declare @puntero varbinary(16) select @puntero=textptr(sinopsis) from libros where codigo=1 if (textvalid('libros. Luego de "writetext" se coloca el nombre de la tabla y el campo (text. "ntext" o "image" o no se ingresan datos. Sintaxis: writetext TABLA. ntext o image) a actualizar.sinopsis @puntero 'Este es un nuevo libro acerca de PHP escrito por el profesor Molina que aborda todos los temas necesarios para el aprendizaje desde cero de este lenguaje. puede ser una variable o un literal. "PUNTEROATEXTO" es el valor que almacena el puntero a texto del dato de tipo "text". porque la función "readtext" requiere un puntero válido. no se crea un puntero válido y al intentar escribir dicho campo ocurre un error.Tipo de dato text . "ntext" o "image".'. "ntext" o "image" o no se ingresan datos. Este ejemplo coloca el puntero a texto en una variable "@puntero" y luego "writetext" almacena el nuevo texto en el registro apuntado por "@puntero": declare @puntero binary(16) select @puntero = textptr (sinopsis) from libros where codigo=2 writetext libros. Para evitarlo podemos chequer el puntero antes de pasárselo a la función de escritura: declare @puntero varbinary(16) select @puntero=textptr(sinopsis) from libros where codigo=1 .CAMPO PUNTEROATEXTO DATO. "ntext" o "image".sinopsis @puntero 9 50 else select 'puntero invalido'. tal puntero debe ser válido. No puede emplearse en vistas. 116 .ntext e image (escribir) La función "writetext" sobreescribe (reemplaza) el texto de un campo "text".sinopsis'.Si al insertar registros se ingresa un valor "null" en un campo "text". Recuerde que si al insertar registros se ingresa un valor "null" en un campo "text".

. ntext.DESPLAZAMIENTODELPUNTERO: indica la posición en que inserta el nuevo dato. La sintaxis básica es la siguiente: updatetext TABLA. nvarchar. "null" (coloca el puntero al final). mayor a la longitud del texto (genera un mensaje de error). . ntext o image que se quiere actualizar. varbinary.DATOAINSERTAR: el dato que va a ser insertado en el campo. es decir. no se actualizó el registro'. "ntext" o "image". Analizamos la sintaxis: . de esta forma: . que apunta al dato text. ntext o image (retornado por la función "textptr"). ntext o image de otra tabla.CAMPO: campo y tabla que se va a actualizar. Es importante recordar que cada caracter "ntext" ocupa 2 bytes. 117 . "null" (borra todos los datos desde la posición indicada por el parámetro DESPLAZAMIENTODELPUNTERO hasta el final). se debe indicar el nombre de la tabla junto con el campo y el valor del puntero que apunta al tipo de dato text. un literal o una variable.sinopsis'. Si colocamos el valor 0 (no se borra ningún dato). . image.Tipo de dato text . Para actualizar campos de estos tipos también empleamos "updatetext". Si el dato es un campo text. Los valores pueden ser: 0 (el nuevo dato se inserta al comienzo). Especifica la cantidad de bytes (para campos text e image) o caracteres (para campos ntext) que debe moverse el puntero para insertar el dato. @puntero)=1) writetext libros.sinopsis @puntero 'Trata de una gaviota que vuela más alto que las demas. text. binary. Puede ser char.' else select 'puntero invalido. nchar. . retornado por la función "textptr".CAMPO PUNTEROATEXTO DESPLAZAMIENTODELPUNTERO LONGITUDDEBORRADO DATOAINSERTAR.PUNTEROATEXTO: valor del puntero. un valor mayor a cero y menor o igual a la longitud total del texto (inserta el nuevo dato en la posición indicada) y un valor mayor a la longitud total del campo (genera un mensaje de error). Es importante recordar que cada caracter ntext ocupa 2 bytes. reemplaza el contenido completo de un campo de tipo "text".if (textvalid('libros.LONGITUDDEBORRADO: indica la cantidad de bytes (para text e image) o caracteres (para ntext) a borrar comenzando de la posición indicada por el parámetro DESPLAZAMIENTODELPUNTERO. varchar. que permite cambiar una porción del campo (o todo el campo). un valor mayor que cero y menor o igual a la longitud del texto (borra tal cantidad) y un valor inválido.ntext e image (actualizar) Aprendimos que la función "writetext" sobreescribe.TABLA.

Entonces. guardamos en la variable el valor del puntero.sinopsis @puntero 18 0 'paso '. el campo ahora contendrá "Para aprencer PHP paso a paso"." Necesitamos agregar antes de "a paso" el texto "paso " para que el texto completo sea "Para aprender PHP paso a paso".CAMPO PUNTERO.TABLA. para ello debemos utilizar 2 punteros.sinopsis @puntero1. Entonces. Luego actualizamos el campo.ntext e image (funciones) .sinopsis @puntero2 0 null libros. finalmente actualizamos el registro de "ofertas" con el texto de "libros". declaramos una variable llamada "@puntero". obtenido con la función "textptr(sinopsis)". Tenemos la tabla libros. pudiendo cambiar una porción del texto. ntext e image. tipeamos: declare @puntero binary(16) select @puntero = textptr(sinopsis) from libros where titulo='Aprenda PHP' updatetext libros. con un campo de tipo text llamado "sinopsis". colocando el puntero en la posición 18. 118 . declare @puntero1 binary(16) select @puntero1 = textptr(sinopsis) from libros where titulo='Aprenda PHP' declare @puntero2 binary(16) select @puntero2 = textptr(sinopsis) from ofertas where titulo='Aprenda PHP' updatetext ofertas. Es posible guardar en un campo "text" de una tabla el contenido del campo "text" de otra tabla. En el siguiente ejemplo guardamos en una variable el valor del puntero a texto al campo "sinopsis" del libro "Aprenda PHP" de la tabla "libros". se emplea "updatetext" para modificar datos de campos de tipo text. tal puntero apunta al campo "sinopsis" del libro "Aprenda PHP". uno para obtener la dirección del campo que queremos actualizar y otro para obtener la dirección del campo del cual extraemos la información.Tipo de dato text . no borramos ningún byte y colocamos el texto a agregar. hay un registro cargado con el siguiente texto: "Para aprender PHP a paso. en otra variable guardamos el valor del puntero a texto al campo "sinopsis" del libro con código 1 de la tabla "ofertas".

El patrón es una cadena que puede incluir comodines. permiten recuperar información de las tablas del sistema y pueden ejecutarse en cualquier base de datos.patindex ('PATRON'. SQL Server permite los siguientes tipos de procedimientos almacenados: 1) del sistema: están almacenados en la base de datos "master" y llevan el prefijo "sp_".datalenght(CAMPO): devuelve el número de bytes de un determinado campo. mediante el uso de restricciones (constraints). que se almacena en el servidor. Permiten encapsular tareas repetitivas.INICIO. empezando desde la posición especificada por el segundo argumento y de tantos caracteres de longitud como indica el tercer argumento. pero "like" solamente puede incluirse en la cláusula "where". si el patrón no se encuentra.1. sinopsis) from libros. 119 .20) from libros.LONGITUD): devuelve una parte del texto especificado como primer argumento. Ejemplo: select titulo.CAMPO): retorna el comienzo de la primera ocurrencia de un patrón de la expresión especificada. . Un procedimiento almacenado es un conjunto de instrucciones a las que se les da un nombre. Ejemplo: select patindex('%PHP%'.substring(sinopsis.Las siguientes son otras funciones que pueden emplearse con estos tipos de datos: . Retorna "null" si el campo es nulo.substring (TEXTO. Con este tipo de datos también puede utilizarse "like". mediante la implementación de procedimientos almacenados y desencadenadores (triggers). la integridad: 1) DECLARATIVA. retorna cero. Nos detendremos ahora en procedimientos almacenados. . valores predeterminados (defaults) y reglas (rules) y 2) PROCEDIMENTAL. datalength(sinopsis) as longitud from libros order by titulo. .Procedimientos almacenados Vimos que SQL Server ofrece dos alternativas para asegurar la integridad de datos. Ejemplo: select titulo.

excepto: . cuyos nombres comienzan con 2 signos numeral (##). que se crean en la base de datos "tempdb".Procedimientos almacenados (crear . Los procedimientos almacenados pueden hacer referencia a tablas. los usuarios realizan operaciones enviando una única instrucción. . las instrucciones que contiene se analizan para verificar si son correctas sintácticamente. o globales. vistas.2) locales: los crea el usuario (próximo tema). 120 . cuyos nombres comienzan con un signo numeral (#). lo cual disminuye el número de solicitudes entre el cliente y el servidor. se crea el procedimiento. los globales están disponibles en las sesiones de todos los usuarios. con lo cual el acceso y las modificaciones de los datos se hacen en un solo sitio. Si se encuentra algún error. excepto los procedimientos almacenados temporales. Dynamic-Link Libraries). Generalmente llevan el prefijo "xp_". Si no se detectan errores. Un procedimiento almacenado pueden incluir cualquier cantidad y tipo de instrucciones. no se crea. 3) temporales: pueden ser locales. Al crear un procedimiento almacenado. En primer lugar se deben tipear y probar las instrucciones que se incluyen en el procedimiento almacenado. luego. Los objetos deben existir cuando se ejecute el procedimiento almacenado. . Ventajas: .comparten la lógica de la aplicación con las otras aplicaciones. se ejecutan fuera del entorno de SQL Server. en vez de enviar muchas instrucciones. a otros procedimientos almacenados y a tablas temporales. SQL Server guarda el nombre del procedimiento almacenado en la tabla del sistema "sysobjects" y su contenido en la tabla del sistema "syscomments" en la base de datos activa. a funciones definidas por el usuario. Los procedimientos almacenados temporales locales están disponibles en la sesión de un solo usuario y se eliminan automáticamente al finalizar la sesión. si se obtiene el resultado esperado. Un procedimiento almacenados puede hacer referencia a objetos que no existen al momento de crearlo.reducen el tráfico de red.permiten realizar todas las operaciones que los usuarios necesitan evitando que tengan acceso directo a las tablas. 4) extendidos: se implementan como bibliotecas de vínculos dinámicos (DLL.ejecutar) Los procedimientos almacenados se crean en la base de datos seleccionada. No los estudiaremos.

Si un procedimiento almacenado crea una tabla temporal. create procedure. La sintaxis básica parcial es: create procedure NOMBREPROCEDIMIENTO as INSTRUCCIONES. la creamos y luego ingresamos algunos registros. etc. Hemos empleado varias veces procedimientos almacenados del sistema ("sp_help". para ejecutar un procedimiento almacenado colocamos "execute" (o "exec") seguido del nombre del procedimiento. eliminaciones. ahora aprenderemos a crear nuestros propios procedimientos almacenados. create rule. se pueden realizar inserciones. que es la forma abreviada). Para crear un procedimiento almacenado empleamos la instrucción "create procedure". Entonces. create trigger y create view. actualizaciones. Para ejecutar el procedimiento almacenado creado anteriormente tipeamos: exec pa_libros_limite_stock.). etc. "sp_helpconstraint". siempre realizamos las mismas tareas: eliminamos la tabla si existe. tablas). "create procedure" debe ser la primera sentencia de un lote. Con las siguientes instrucciones creamos un procedimiento almacenado llamado "pa_libros_limite_stock" que muestra todos los libros de los cuales hay menos de 10 disponibles: create proc pa_libros_limite_stock as select *from libros where cantidad <=10. Entonces. Podemos crear un procedimiento almacenado que contenga todas estas instrucciones: create procedure pa_crear_libros as if object_id('libros')is not null . Cuando realizamos un ejercicio nuevo. creamos un procedimiento almacenado colocando "create procedure" (o "create proc".create default. en tal caso deben especificar el nombre del propietario. dicha tabla sólo existe dentro del procedimiento y desaparece al finalizar el mismo. Lo mismo sucede con las variables. Para diferenciar los procedimientos almacenados del sistema de los procedimientos almacenados locales use un prefijo diferente a "sp_" cuando les de el nombre. luego el nombre del procedimiento y seguido de "as" las sentencias que definen el procedimiento. Se pueden crear otros objetos (por ejemplo índices.

'Mario Molina'. comenzando el nombre con un signo arroba (@). Pueden declararse varios parámetros por procedimiento.'Emece'.35). primary key(codigo) ). deben explicitarse valores para cada uno de los parámetros (en el orden que fueron definidos).'Paenza'. titulo varchar(40). Y luego lo ejecutamos cada vez que comenzamos un nuevo ejercicio y así evitamos tipear tantas sentencias: exec pa_crear_libros. Los parámetros de entrada posibilitan pasar información a un procedimiento. Pueden ser de cualquier tipo de dato (excepto cursor).'Borges'. a menos que se haya definido un valor por defecto.'Richard Bach'. editorial varchar(20).'Planeta'. existen solamente dentro del mismo. respectivamente. La sintaxis es: create proc NOMBREPROCEDIMIENTO @NOMBREPARAMETRO TIPO =VALORPORDEFECTO as SENTENCIAS.12).18). en tal caso.15). values('Java en 10 minutos'. Cuando el procedimiento es ejecutado. precio decimal(5. insert insert insert insert insert insert into into into into into into libros libros libros libros libros libros values('Uno'.Procedimientos almacenados (parámetros de entrada) Los procedimientos almacenados pueden recibir y devolver información. de entrada y salida. Para que un procedimiento almacenado admita parámetros de entrada se deben declarar variables como parámetros al crearlo.'Planeta'.2). values('Aprenda PHP'.25). Los parámetros se definen luego del nombre del procedimiento.'Nuevo siglo'. values('El aleph'. para ello se emplean parámetros.45). autor varchar(30).'Richard Bach'. es decir. . 122 . pueden omitirse.'Nuevo siglo'. create table libros( codigo int identity. values('Matematica estas ahi'. Veamos los primeros. Los parámetros son locales al procedimiento. values('Ilusiones'.drop table libros.'Mario Molina'.'Paidos'. se separan por comas.

precio from libros where autor= @autor and editorial=@editorial. se puede especificar un valor por defecto. El procedimiento se ejecuta colocando "execute" (o "exec") seguido del nombre del procedimiento y un valor para el parámetro: exec pa_libros_autor 'Borges'. Creamos un procedimiento que recibe el nombre de un autor como parámetro para mostrar todos los libros del autor solicitado: create procedure pa_libros_autor @autor varchar(30) as select titulo. Creamos un procedimiento que recibe 2 parámetros. @editorial varchar(20) as select titulo. . Si no se coloca valor por defecto. opcionalmente. un procedimiento definido con parámetros no puede ejecutarse sin valores para ellos. Los valores de un parámetro pueden pasarse al procedimiento mediante el nombre del parámetro o por su posición. El valor por defecto puede ser "null" o una constante. El procedimiento se ejecuta colocando "execute" (o "exec") seguido del nombre del procedimiento y los valores para los parámetros separados por comas: exec pa_libros_autor_editorial 'Richard Bach'. el orden en que se colocan puede alterarse. @autor='Richard Bach'. también puede incluir comodines si el procedimiento emplea "like".'Planeta'.precio from libros where autor= @autor. editorial. Cuando pasamos valores con el nombre del parámetro. También podemos emplear la otra sintaxis en la cual pasamos valores a los parámetros por su nombre: exec pa_libros_autor_editorial @editorial='Planeta'. tal valor es el que asume el procedimiento al ser ejecutado si no recibe parámetros.Luego de definir un parámetro y su tipo. La sintaxis anterior ejecuta el procedimiento pasando valores a los parámetros por posición. el nombre de un autor y el de una editorial: create procedure pa_libros_autor_editorial @autor varchar(30).

usará los predeterminados. Si queremos especificar solamente el segundo parámetro. debemos emplear la sintaxis de paso de valores a parámetros por nombre: exec pa_libros_autor_editorial2 @editorial='Paidos'. Si enviamos un solo parámetro a un procedimiento que tiene definido más de un parámetro sin especificar a qué parámetro corresponde (valor por posición). Es decir. se asume que es el primero.precio from libros where autor= @autor and editorial=@editorial. Podemos emplear patrones de búsqueda en la consulta que define el procedimiento almacenado y utilizar comodines como valores por defecto: create proc pa_libros_autor_editorial3 @autor varchar(30) = '%'. SQL Server asume que los valores se dan en el orden que fueron definidos. La sentencia siguiente ejecuta el procedimiento almacenado "pa_libros_autor_editorial3" enviando un valor para el segundo parámetro. Si queremos ejecutar un procedimiento que permita omitir los valores para los parámetros debemos.precio from libros where autor like @autor and editorial like @editorial. La sentencia siguiente ejecuta el procedimiento almacenado "pa_libros_autor_editorial3" enviando un valor por posición. autor. exec pa_libros_autor_editorial3 'P%'.No podríamos ejecutar el procedimiento anterior sin valores para los parámetros.editorial. @editorial varchar(30) = '%' as select titulo. asume que es el primero. para el primer parámetro toma el valor por defecto: exec pa_libros_autor_editorial3 @editorial='P%'. al crear el procedimiento. Podemos ejecutar el procedimiento anterior sin enviarle valores. definir valores por defecto para cada parámetro: create procedure pa_libros_autor_editorial2 @autor varchar(30)='Richard Bach'. @editorial varchar(20)='Planeta' as select titulo.autor. no se puede interrumpir la secuencia.editorial. .

El valor se retorna a quien realizó la llamada con parámetros de salida. 121 . Podemos eliminar una tabla de la cual dependa un procedimiento. si no existe. al ejecutar el procedimiento. para evitarlo. Para que un procedimiento almacenado devuelva un valor se debe declarar una variable con la palabra clave "output" al crear el procedimiento: . 'P%'.Procedimientos almacenados (parámetros de salida) Dijimos que los procedimientos almacenados pueden devolver información. el procedimiento "pa_libros_autor". 123 .También podríamos haber tipeado: exec pa_libros_autor_editorial3 default. para ello se emplean parámetros de salida. Eliminamos el procedimiento almacenado llamado "pa_libros_autor": drop procedure pa_libros_autor. Eliminamos. pero luego. "drop procedure" puede abreviarse con "drop proc". SQL Server lo permite. aparecerá un mensaje de error porque la tabla referenciada no existe. Sintaxis: drop procedure NOMBREPROCEDIMIENTO. Si el procedimiento que queremos eliminar no existe. Se recomienda ejecutar el procedimiento almacenado del sistema "sp_depends" para ver si algún objeto depende del procedimiento que deseamos eliminar. si existe.Procedimientos almacenados (eliminar) Los procedimientos almacenados se eliminan con "drop procedure". aparece un mensaje de error. podemos emplear esta sintaxis: if object_id('NOMBREPROCEDIMIENTO') is not null drop procedure NOMBREPROCEDIMIENTO. mostramos un mensaje: if object_id('pa_libros_autor') is not null drop procedure pa_libros_autor else select 'No existe el procedimiento "pa_libros_autor"'.

@variable output select @variable. @PARAMETROSALIDA TIPO=VALORPORDEFECTO output as SENTENCIAS select @PARAMETROSALIDA=SENTENCIAS. Al ejecutarlo también debe emplearse "output": declare @variable decimal(4.editorial. editorial y precio de los libros de un determinado autor (enviado como parámetro de entrada) y nos retorne la suma y el promedio de los precios de todos los libros del autor enviado: create procedure pa_autor_sumaypromedio @autor varchar(30)='%'. @n2 decimal(4. @suma decimal(6. @promedio decimal(6.2) output.2) output as select titulo.2) execute pa_promedio 5. Declaramos una variable para guardar el valor devuelto por el procedimiento.2). ejecutamos el procedimiento enviándole 2 valores y mostramos el resultado. La instrucción que realiza la llamada al procedimiento debe contener un nombre de variable para almacenar el valor retornado. excepto text. Los parámetros de salida pueden ser de cualquier tipo de datos.2). Creamos un procedimiento almacenado que muestre los títulos.create procedure NOMBREPROCEDIMIENTO @PARAMETROENTRADA TIPO =VALORPORDEFECTO. @resultado decimal(4.2) output as select @resultado=(@n1+@n2)/2. Creamos un procedimiento almacenado al cual le enviamos 2 números y retorna el promedio: create procedure pa_promedio @n1 decimal(4.precio from libros where autor like @autor select @suma=sum(precio) from libros where autor like @autor . ntext e image.6.

124 .2). Si no se ingresa un valor. o se ingresa "null". . @autor varchar(30)=null. se muestra un mensaje y se sale del procedimiento: create procedure pa_libros_autor @autor varchar(30)=null as if @autor is null begin select 'Debe indicar un autor' return end. @p output select @s as total. @s output.Procedimientos almacenados (return) La instrucción "return" sale de una consulta o procedimiento y todas las instrucciones posteriores no son ejecutadas. Creamos un procedimiento almacenado que ingresa registros en la tabla "libros". con lo cual toma el valor por defecto "null". Si al ejecutar el procedimiento enviamos el valor "null" o no pasamos valor. Creamos un procedimiento que muestre todos los libros de un autor determinado que se ingresa como parámetro. es decir. en caso contrario.select @promedio=avg(precio) from libros where autor like @autor. El procedimiento retorna "1" si la inserción se realiza.2) execute pa_autor_sumaypromedio 'Richard Bach'. Los parámetros correspondientes al título y autor DEBEN ingresarse con un valor distinto de "null". Un procedimiento puede retornar un valor de estado para indicar si se ha ejecutado correctamente o no. select titulo from libros where autor = @autor. "return" puede retornar un valor entero. Ejecutamos el procedimiento y vemos el contenido de las variables en las que almacenamos los parámetros de salida del procedimiento: declare @s decimal(6. si se ingresan valores para título y autor y "0". @p as promedio. ejecuta la consulta luego del "else". @p decimal(6. se muestra un mensaje y se sale. los demás son opcionales. en caso que título o autor sean nulos: create procedure pa_libros_ingreso @titulo varchar(40)=null.

incluidos los procedimientos..Procedimientos almacenados (información) Los procedimientos almacenados son objetos. debemos declarar una variable en la cual se almacene el valor devuelto por el procedimiento. obtenemos la fecha de creación e información sobre sus parámetros. así que para obtener información de ellos pueden usarse los siguientes procedimientos almacenados del sistema y las siguientes tablas: .@autor."sp_help": sin parámetros nos muestra todos los objetos de la base de datos seleccionada. excepto si ha sido encriptado.@editorial varchar(20)=null.'Anónimo' if @retorno=1 print 'Registro ingresado' else select 'Registro no ingresado porque faltan datos'. También podríamos emplear un "if" para controlar el valor de la variable de retorno: declare @retorno int."sp_stored_procedures": muestra todos los procedimientos almacenados. . ejecutar el procedimiento asignándole el valor devuelto a la variable. Para ver el resultado."sp_helptext": seguido del nombre de un procedimiento almacenado nos muestra el texto que define el procedimiento.@editorial.2)=null as if (@titulo is null) or (@autor is null) return 0 else begin insert into libros values (@titulo. Si le enviamos como argumento el nombre de un procedimiento. exec @retorno=pa_libros_ingreso 'El gato con botas'. admite comodines para búsqueda de patrones). nvarchar..'. Este procedimiento almacenado puede recibir 3 parámetros: @sp_name (nombre. . los propietarios. @precio decimal(5. En la columna "Object_type" aparece "stored procedure" si es un procedimiento almacenado. luego.'Lewis Carroll' select 'Ingreso realizado=1' = @retorno exec @retorno=pa_libros_ingreso select 'Ingreso realizado=1' = @retorno. 125 . finalmente mostramos el contenido de la variable: declare @retorno int exec @retorno=pa_libros_ingreso 'Alicia en el pais. etc.@precio) return 1 end. .

debemos colocar la opción "with encryption" al crear el procedimiento: create procedure NOMBREPROCEDIMIENTO PARAMETROS with encryption as INSTRUCCIONES. Si no quiere que los usuarios puedan leer el contenido del procedimiento podemos indicarle a SQL Server que codifique la entrada a la tabla "syscomments" que contiene el texto. podemos ver todos los procedimientos almacenados creados por nosotros con esta sentencia: sp_stored_procedures @sp_name='pa_%'. ejecutamos "sp_depends" seguido del nombre de un procedimiento: sp_depends pa_autor_promedio. Si queremos ver todos los procedimientos almacenados creados por nosotros. La columna "xtype" indica el tipo de objeto. de los objetos de los cuales depende el objeto enviado y 2) nombre y tipo de los objetos que dependen del objeto nombrado. es decir.Procedimientos almacenados (encriptado) Dijimos que SQL Server guarda el nombre del procedimiento almacenado en la tabla del sistema "sysobjects" y su contenido en la tabla "syscomments". nos devuelve 2 resultados: 1) nombre.@sp_owner (propietario. podemos tipear: select *from sysobjects where xtype='P' and-.--búsqueda con comodín 126 . admite comodines) y @qualifier (nombre de la base de datos). las tablas referenciadas en el mismo. Por ejemplo. muestra "P". Ejemplo: select *from sysobjects. tipo. nvarchar. . etc. Por ejemplo. aparecen las tablas (y demás objetos) de las cuales depende el procedimiento."sp_depends": seguido del nombre de un objeto. aparecen los procedimientos (y demás objetos) que dependen de ella.tipo procedimiento name like 'pa%'. campos. . Para ello.La tabla del sistema "sysobjects": muestra nombre y varios datos de todos los objetos de la base de datos actual. Podemos ejecutar el procedimiento seguido del nombre de una tabla: sp_depends libros. . Si es un procedimiento almacenado.

la editorial y precio: alter procedure pa_libros_autor @autor varchar(30)=null as if @autor is null begin select 'Debe indicar un autor' return end else select titulo. 128 . Modificamos el procedimiento almacenado "pa_libros_autor" para que muestre.Procedimientos almacenados (modificar) Los procedimientos almacenados pueden modificarse. Sintaxis: alter procedure NOMBREPROCEDIMIENTO @PARAMETRO TIPO = VALORPREDETERMINADO as SENTENCIAS.precio from libros where autor = @autor. no aparece. además del título.Esta opción es opcional. 127 . Si ejecutamos el procedimiento almacenado del sistema "sp_helptext" para ver su contenido.editorial. Un procedimiento almacenado existente puede modificarse con "alter procedure". Si quiere modificar un procedimiento que se creó con la opción "with encryption" y quiere conservarla. por necesidad de los usuarios o por cambios en la estructura de las tablas que referencia. Creamos el procedimiento almacenado "pa_libros_autor" con la opción de encriptado: create procedure pa_libros_autor @autor varchar(30)=null with encryption as select *from libros where autor=@autor.Procedimientos almacenados (insertar) . debe incluirla al alterarlo.

Procedimientos almacenados (anidados) Un procedimiento almacenado puede llamar a otro procedimiento almacenado. Las tablas deben existir y los tipos de datos deben coincidir. que ingresa libros en la tabla "ofertas": create proc pa_ofertas as select titulo.autor. @numero2 int.precio from libros where precio<50.Podemos ingresar datos en una tabla con el resultado devuelto por un procedimiento almacenado. La instrucción siguiente crea el procedimiento "pa_ofertas". B debe existir al crear A.editorial. Los procedimientos almacenados pueden anidarse hasta 32 niveles. Creamos otro procedimiento que nos retorne el factorial de un número. si un procedimiento A llama a otro procedimiento B. Es decir. El procedimiento que es invocado por otro debe existir cuando creamos el procedimiento que lo llama. 129 . Creamos un procedimiento almacenado que reciba 2 números enteros y nos retorne el producto de los mismos: create procedure pa_multiplicar @numero1 int. tal procedimiento llamará al procedimiento "pa_multiplicar": create procedure pa_factorial @numero int as declare @resultado int declare @num int . La siguiente instrucción ingresa en la tabla "ofertas" el resultado del procedimiento "pa_ofertas": insert into ofertas exec pa_ofertas. @producto int output as select @producto=@numero1*@numero2.

3) Podemos ejecutar el procedimiento almacenado del sistema "sp_recompile".set @resultado=1 set @num=@numero while (@num>1) begin exec pa_multiplicar @resultado. En general se recomienda no hacerlo excepto si se agrega un índice a una tabla referenciada por el procedimiento o si los datos han variado mucho desde la última compilación.@numero))+'!='+convert(char. SQL Server ofrece tres métodos para recompilar explícitamente un procedimiento almacenado: 1) Se puede indicar. @resultado output set @num=@num-1 end select rtrim(convert(char.@resultado). al crear el procedimiento. En este caso la sintaxis es la siguiente: create procedure NOMBREPROCEDIMIENTO PARAMETROS with recompile as SENTENCIAS. Se realiza la primera vez que se ejecuta un procedimiento almacenado o si el procedimiento almacenado se debe volver a compilar (recompilación). 130 . Cuando un procedimiento (A) llama a otro (B). SQL Server recompila automáticamente un procedimiento almacenado si se realiza algún cambio en la estructura de una tabla (o vista) referenciada en el procedimiento (alter table y alter view) y cuando se modifican las claves (insert o delete) de una tabla referenciada.@num. que SQL Server no guarde en la caché un plan de ejecución para el procedimiento sino que lo compile cada vez que se ejecute. Este procedimiento vuelve a compilar el procedimiento almacenado (o desencadenador) que se especifica. 2) Podemos especificar "with recompile" al momento de ejecutarlo: exec NOMBREPROCEDIMIENTO with recompile. el segundo (B) tiene acceso a todos los objetos que cree el primero (A). La sintaxis es: . Un procedimiento almacenado puede recompilarse explícitamente.Procedimientos Almacenados (recompilar) La compilación es un proceso que consiste en analizar el procedimiento almacenado y crear un plan de ejecución.

los procedimientos permiten el acceso a ellas. Si es el nombre de una tabla o vista. hemos creado procedimientos que incluyen una sola tabla o pocas instrucciones para aprender la sintaxis. todos los procedimientos almacenados que usan tal tabla (o vista) se vuelven a compilar. . tampoco puede ser referenciada por una vista. El parámetro enviado debe ser el nombre de un procedimiento. varias instrucciones y llamadas a otros procedimientos. Una tabla temporal no puede tener una restricción "foreign key" ni ser indexada.. además si no queremos que el usuario conozca la estructura de las tablas involucradas.Tablas temporales Las tablas temporales son visibles solamente en la sesión actual. Para referenciarla en otras consultas. Pueden ser locales (son visibles sólo en la sesión actual) o globales (visibles por todas las sesiones). Podemos crear procedimientos que incluyan combinaciones (join). Las tablas temporales se eliminan automáticamente al acabar la sesión o la función o procedimiento almacenado en el cual fueron definidas. create table #NOMBRE( CAMPO DEFINICION. que es parte del nombre.. ). se debe incluir el numeral(#). excepto que se coloca un signo numeral (#) precediendo el nombre. select *from #libros. . de una tabla o de una vista. Podemos crear todos los procedimientos que necesitemos para que realicen todas las operaciones y consultas. Por ejemplo: insert into #libros default values. subconsultas. de un desencadenador. pero la funcionalidad de un procedimiento consiste básicamente en que contengan muchas instrucciones o instrucciones complejas y así evitar tipear repetidamente dichas instrucciones. 131 .exec sp_recompile NOMBREOBJETO. Para crear tablas temporales locales se emplea la misma sintaxis que para crear cualquier tabla. Se pueden eliminar con "drop table".Procedimientos Almacenados (con join) Hasta ahora. 132 .

. excepto timestamp. textptr. datename. excepto "charindex" y "patindex". cursor. Sabemos que una función es un conjunto de sentencias que operan como una unidad lógica. 133 . Las funciones definidas por el usuario no permiten parámetros de salida. Las funciones pueden clasificarse en: . SQL Server provee muchas funciones y además permite que el usuario pueda definir sus propias funciones. debemos tipear: select *from tempdb. Todas las funciones de configuración.deterministicas: siempre retornan el mismo resultado si se las invoca enviando el mismo valor de entrada. create table ##NOMBRE( CAMPO DEFINICION. Una función tiene un nombre. . otra tabla temporal local llamada "#libros" y una tercera tabla temporal global denominada "##libros".Funciones SQL Server ofrece varios tipos de funciones para realizar distintas operaciones. Hemos visto y empleado varias de ellas. Todas las funciones de agregado y string son deterministicas. seguridad y estadísticas del sistema son no deterministicas. Se pueden emplear las funciones del sistema en cualquier lugar en el que se permita una expresión en una sentencia "select". excepto que se coloca un signo numeral doble (##) precediendo el nombre. textvalid. una rutina que retorna un valor..sysobjects. No podemos consultar la tabla "sysobjects" para ver las tablas temporales.no deterministicas: pueden retornar distintos resultados cada vez que se invocan con el mismo valor de entrada.. Las siguientes son algunas de las funciones no deterministicas: getdate. ). . .Para crear tablas temporales globales se emplea la misma sintaxis que para crear cualquier tabla. El (o los) numerales son parte del nombre. rand. Así que puede crearse una tabla permanente llamada "libros". cursor y table. meta data. Los parámetros de entrada pueden ser de cualquier tipo. acepta parámetros de entrada y retorna un valor escalar o una tabla.

podemos verificar su existencia antes de solicitar su eliminación (como con cualquier otro objeto): if object_id('NOMBREPROPIETARIO. la función denominada "f_fechacadena": if object_id('dbo. Eliminamos.NOMBREFUNCION. Como todas las funciones. SQL Server admite 3 tipos de funciones definidas por el usuario clasificadas según el valor retornado: 1) escalares: retornan un valor escalar. 135 . 134 .f_fechacadena') is not null drop function dbo.NOMBREFUNCION') is not null drop function NOMBREPROPIETARIO. La sintaxis básica es: create function NOMBRE (@PARAMETRO TIPO=VALORPORDEFECTO) . para evitarlo.Funciones escalares (crear y llamar) Una función escalar retorna un único valor. se crean con la instrucción "create function". aparece un mensaje indicándolo. 2) de tabla de varias instrucciones (retornan una tabla) y 3) de tabla en línea (retornan una tabla). NO es posible emplear en ellas funciones no determinadas (como getdate()) ni sentencias de modificación o actualización de tablas o vistas.Funciones (drop) Las funciones definidas por el usuario se eliminan con la instrucción "drop function": Sintaxis: drop function NOMBREPPROPIETARIO. Se coloca el nombre del propietario seguido del nombre de la función.NOMBREFUNCION. si existe.f_fechacadena. de control de flujo (if). Las funciones definidas por el usuario se crean con la instrucción "create function" y se eliminan con "drop function". Si la función que se intenta eliminar no existe. Si podemos emplear sentencias de asignación.No todas las sentencias SQL son válidas dentro de una función. de modificación y eliminación de variables locales.

ntext. cursor o timestamp.. Entonces. La cláusula "returns" indica el tipo de dato retornado.end" que contiene las instrucciones que retornan el valor. se define en un bloque "begin.8. image.5). El cuerpo de la función.. El tipo del valor retornado puede ser de cualquier tipo.2).end" dentro del cual se encuentran las instrucciones de procesamiento y el valor retornado luego de "return". se debe especificar el propietario y el nombre de la función: select dbo. excepto text. Cuando llamamos a funciones que tienen definidos parámetros de entrada DEBEMOS suministrar SIEMPRE un valor para él.. Luego del nombre se colocan (opcionalmente) los parámetros de entrada con su tipo. En el ejemplo anterior se declara una variable local a la función (desaparece al salir de la función) que calcula el resultado que se retornará.2) as begin declare @resultado decimal(6.f_promedio(5.returns TIPO begin INSTRUCCIONES return VALOR end. se deben especificar los parámetros de entrada con sus tipos de datos (entre paréntesis).5. luego de "create function" y el nombre de la función..2) set @resultado=(@valor1+@valor2)/2 return @resultado end. SQL Server muestra un mensaje de error indicando que necesita argumentos. Si llamamos a la función anterior sin enviarle los valores para los parámetros: select dbo.f_promedio(). @valor2 decimal(4. Creamos una simple función denominada "f_promedio" que recibe 2 valores y retorna el promedio: create function f_promedio (@valor1 decimal(4. luego de "as" comienza el bloque "begin. el tipo de dato que retorna luego de "returns". .2) ) returns decimal (6. Al hacer referencia a una función escalar.

Luego de los parámetros de entrada se indica el tipo de dato que retorna luego de "returns".end" dentro del cual se encuentran las instrucciones de procesamiento y el valor retornado luego de "return".. se debe especificar el propietario y el nombre de la función: select nombre.. Recuerde que al invocar una función escalar. El parámetro de entrada tiene definido un valor por defecto. No olvide que cuando invocamos funciones que tienen definidos parámetros de entrada DEBEMOS suministrar SIEMPRE un valor para él.f_nombreMes(fechaingreso) as 'mes de ingreso' from empleados.Creamos una función a la cual le enviamos una fecha y nos retorna el nombre del mes en español: create function f_nombreMes (@fecha datetime='2007/01/01') returns varchar(10) as begin declare @nombre varchar(10) set @nombre= case datename(month. dbo. . Las funciones que retornan un valor escalar pueden emplearse en cualquier consulta donde se coloca un campo. luego de "as" comienza el bloque "begin. especificamos los parámetros de entrada con sus tipos de datos (entre paréntesis).@fecha) when 'January' then 'Enero' when 'February' then 'Febrero' when 'March' then 'Marzo' when 'April' then 'Abril' when 'May' then 'Mayo' when 'June' then 'Junio' when 'July' then 'Julio' when 'August' then 'Agosto' when 'September' then 'Setiembre' when 'October' then 'Octubre' when 'November' then 'Noviembre' when 'December' then 'Diciembre' end--case return @nombre end. Analicemos: luego de "create function" y el nombre de la función.

la diferencia es que la tabla retornada por la función puede ser referenciada en el "from" de una consulta. La instrucción "create function" debe ser la primera sentencia de un lote. si llamamos a la función anterior sin enviarle un valor: select dbo. pero en las vistas solamente podemos emplear "select". pero al invocar la función. Las funciones que retornan una tabla pueden emplearse en lugar de un "from" de una consulta. procedimientos. Este tipo de función es similar a un procedimiento almacenado. mientras que en funciones definidas por el usuario podemos incluir sentencias como "if". llamadas a funciones. pero el resultado de un procedimiento almacenado no. CAMPO3 TIPO ) as begin insert @NOMBRETABLARETORNO select CAMPOS from TABLA where campo OPERADOR @PARAMETRO RETURN . que retornan un valor escalar.f_nombreMes(default). Ahora veremos las funciones con varias instrucciones que retornan una tabla.f_nombreMes(). etc. para que tome el valor por defecto DEBEMOS especificar "default". 136 . CAMPO2 TIPO. Por ejemplo.Podemos colocar un valor por defecto al parámetro. SQL Server muestra un mensaje de error indicando que necesita argumento. Sintaxis: create function NOMBREFUNCION (@PARAMETRO TIPO) returns @NOMBRETABLARETORNO table-.nombre de la tabla --formato de la tabla (CAMPO1 TIPO.Funciones de tabla de varias instrucciones Hemos visto el primer tipo de funciones definidas por el usuario. También es similar a una vista. Para que tome el valor por defecto debemos enviar "default" como argumento: select dbo.

2) ) as begin insert @ofertas select codigo.precio from libros where precio < @minimo return end. Las funciones que retornan una tabla pueden llamarse sin especificar propietario: select *from f_ofertas(30). se crea con "create function" seguida del nombre de la función. El siguiente ejemplo crea una función denominada "f_ofertas" que recibe un parámetro. luego (opcionalmente) los parámetros de entrada con su tipo de dato. no puede ser un argumento. título.nombre de la tabla --formato de la tabla (codigo int. . Dijimos que este tipo de función puede ser referenciada en el "from" de una consulta. La función retorna una tabla con el codigo. "return" indica que las filas insertadas en la variable son retornadas. el tipo de datos a retornar (que es "table") y el formato de la misma (campos y tipos).. el cual contiene las instrucciones que insertan filas en la variable (tabla que será retornada) definida en "returns". precio decimal(6. end".titulo. select *from dbo. autor varchar(30).2)) returns @ofertas table-.autor. la siguiente consulta realiza un join entre la tabla "libros" y la tabla retornada por la función "f_ofertas": select *from libros as l join dbo.f_ofertas(30).. titulo varchar(40).codigo. autor y precio de todos los libros cuyo precio sea inferior al parámetro: create function f_ofertas (@minimo decimal(6.codigo=o. La cláusula "returns" define un nombre de variable local para la tabla que retornará.end Como cualquier otra función.f_ofertas(25) as o on l. El cuerpo de la función se define también en un bloque "begin.

NOMBREFUNCION NUEVADEFINICION.Se puede llamar a la función como si fuese una tabla o vista listando algunos campos: select titulo.precio from dbo. Las funciones definidas por el usuario pueden modificarse con la instrucción "alter function". Sintaxis para modificar funciones escalares: alter funtion PROPIETARIO. 138 . Sintaxis general: alter function PROPIETARIO.NOMBREFUNCION (@PARAMETRO TIPO=VALORPORDEFECTO) returns TIPO as begin CUERPO return EXPRESIONESCALAR end Sintaxis para modificar una función de varias instrucciones que retorna una tabla: alter function NOMBREFUNCION (@PARAMETRO TIPO=VALORPORDEFECTO) returns @VARIABLE table (DEFINICION DE LA TABLA A RETORNAR) as begin CUERPO DE LA FUNCION return end Sintaxis para modificar una función con valores de tabla en línea alter function NOMBREFUNCION (@PARAMETRO TIPO) .f_ofertas(40). las funciones definidas por el usuario si.Funciones (modificar) Las funciones de SQL Server no pueden ser modificadas.

Funciones (modificar) Las funciones de SQL Server no pueden ser modificadas.titulo.NOMBREFUNCION NUEVADEFINICION.editorial from libros where autor like '%'+@autor+'%' ). las funciones definidas por el usuario si.editorial from libros where autor like '%'+@autor+'%' ).NOMBREFUNCION . Sintaxis para modificar funciones escalares: alter funtion PROPIETARIO. 138 . Sintaxis general: alter function PROPIETARIO. La modificamos agregando otro campo en el "select": alter table f_libros (@autor varchar(30)='Borges') returns table as return ( select codigo. Creamos una función que retorna una tabla en línea: create function f_libros (@autor varchar(30)='Borges') returns table as return ( select titulo.returns TABLE as return (SENTENCIAS SELECT) Veamos un ejemplo. Las funciones definidas por el usuario pueden modificarse con la instrucción "alter function".

(@PARAMETRO TIPO=VALORPORDEFECTO) returns TIPO as begin CUERPO return EXPRESIONESCALAR end Sintaxis para modificar una función de varias instrucciones que retorna una tabla: alter function NOMBREFUNCION (@PARAMETRO TIPO=VALORPORDEFECTO) returns @VARIABLE table (DEFINICION DE LA TABLA A RETORNAR) as begin CUERPO DE LA FUNCION return end Sintaxis para modificar una función con valores de tabla en línea alter function NOMBREFUNCION (@PARAMETRO TIPO) returns TABLE as return (SENTENCIAS SELECT) Veamos un ejemplo. La modificamos agregando otro campo en el "select": alter table f_libros (@autor varchar(30)='Borges') returns table . Creamos una función que retorna una tabla en línea: create function f_libros (@autor varchar(30)='Borges') returns table as return ( select titulo.editorial from libros where autor like '%'+@autor+'%' ).

Para ello debemos agregar al crearlas la opción "with encryption" antes de "as". CAMPO3 TIPO ) with encryption as begin insert @NOMBRETABLARETORNO select CAMPOS from TABLA where campo OPERADOR @PARAMETRO RETURN . En funciones escalares: create function NOMBREFUNCION (@PARAMETRO TIPO) returns TIPO with encryption as begin CUERPO return EXPRESION end En funciones de tabla de varias sentencias se coloca luego del formato de la tabla a retornar: create function NOMBREFUNCION (@PARAMETRO TIPO) returns @NOMBRETABLARETORNO table-. CAMPO2 TIPO.editorial from libros where autor like '%'+@autor+'%' ).nombre de la tabla --formato de la tabla (CAMPO1 TIPO. para evitar que sean leídas con "sp_helptext".Funciones (encriptado) Las funciones definidas por el usuario pueden encriptarse.titulo.as return ( select codigo. 139 .

obtenemos el propietario. los campos de la tabla retornada. 140 ."sp_help": sin parámetros nos muestra todos los objetos de la base de datos seleccionada."sp_helptext": seguido del nombre de una función definida por el usuario nos muestra el texto que define la función. excepto si ha sido encriptado. SQL Server mostrará un mensaje indicando que tal función está encriptada. así que para obtener información de ellos pueden usarse los siguientes procedimientos almacenados del sistema y las siguientes tablas: .end En funciones con valores de tabla en línea: create function NOMBREFUNCION (@PARAMETRO TIPO=VALORPORDEFECTO) returns table with encryption as return (SELECT). Si le enviamos como argumento el nombre de una función definida por el usuario. incluidas las funciones definidas por el usuario. Si ejecutamos el procedimiento almacenado del sistema "sp_helptext" seguido del nombre de la función creada anteriormente. si es una función de tabla. el tipo de función y la fecha de creación. "table function" si es una función de tabla de varias sentencias y "inline function" si es una función de tabla en línea. . .editorial from libros where autor like '%'+@autor+'%' )."sp_stored_procedures": muestra todos los procedimientos almacenados y funciones definidas por el usuario.Funciones (información) Las funciones son objetos. En la columna "Object_type" aparece "scalar function" si es una función escalar. Veamos un ejemplo: create function f_libros (@autor varchar(30)='Borges') returns table with encryption as return ( select titulo. .

Si es una función definida por el usuario escalar.. muestra "TF" y si es una función de tabla en linea muestra "IF". si es una función de tabla de varias sentencias. actualización y eliminación). Se crean para conservar la integridad referencial y la coherencia entre los datos entre distintas tablas. actualizar o eliminar) datos de una tabla en la que se definió un disparador para alguna de estas acciones (inserción. Podemos ejecutar el procedimiento seguido del nombre de una tabla: sp_depends libros. aparecen las tablas (y demás objetos) de las cuales depende el procedimiento. etc."sp_depends": seguido del nombre de un objeto.crdate as fecha from sysobjects where xtype in ('FN'. Un trigger se asocia a un evento (inserción. Si se intenta modificar (agregar. el disparador se ejecuta (se dispara) en forma automática. es decir. campos. . muestra "FN".Disparadores (triggers) Un "trigger" (disparador o desencadenador) es un tipo de procedimiento almacenado que se ejecuta cuando se intenta modificar los datos de una tabla (o vista). Por ejemplo.xtype as tipo. La columna "xtype" indica el tipo de objeto. La diferencia con los procedimientos almacenados del sistema es que los triggers: .'IF'). 141 . tipo y fecha de creación de todas las funciones definidas por el usuario. las tablas (y campos) referenciadas en la misma. nos devuelve 2 resultados: 1) nombre.La tabla del sistema "sysobjects": muestra nombre y varios datos de todos los objetos de la base de datos actual. tipo. No aparecen objetos que dependan de la función porque no existe ningún objeto que la referencie. aparecen las funciones (y demás objetos) que dependen de ella (que la referencian). podemos tipear: select name. ejecutamos "sp_depends" seguido del nombre de una función definida por el usuario: sp_depends pa_libroslistado. Se definen para una tabla (o vista) específica. Si queremos ver el nombre.'TF'. actualización o borrado) sobre una tabla. de los objetos de los cuales depende el objeto enviado (referenciados por el objeto) y 2) nombre y tipo de los objetos que dependen del objeto nombrado (que lo referencian). No aparecen objetos de los cuales depende porque la tabla no los tiene.

se especifican las condiciones y acciones del disparador. Debe colocarse al menos UNA acción. es decir. a diferencia de las restricciones "check".insert. Puede ser "insert". "update" o "delete". Las restricciones se comprueban ANTES de la ejecución de una instrucción "insert". ."create trigger" junto al nombre del disparador. el desencadenador no llega a ejecutarse. . Por lo tanto. puede crearse un trigger de inserción en la tabla "ventas" que compruebe el campo "stock" de un artículo en la tabla "articulos". Por ejemplo. si se coloca más de una.. deben separarse con comas. "update" o "delete" en la tabla en la que fueron definidos. el disparador controlaría que.luego de "as" viene el cuerpo del trigger. Los disparadores se ejecutan DESPUES de la ejecución de una instrucción "insert". Sintaxis básica: create triggre NOMBREDISPARADOR on NOMBRETABLA for EVENTO."create trigger" debe ser la primera sentencia de un bloque y sólo se puede aplicar a una tabla. . no para obtener resultados de consultas. update o delete as SENTENCIAS Analizamos la sintaxis: ."on" seguido del nombre de la tabla o vista para la cual se establece el trigger.no reciben y retornan parámetros. pueden hacer referencia a campos de otras tablas. Los triggers se crean con la instrucción "create trigger".son apropiados para mantener la integridad de los datos. las condiciones que determinan cuando un intento de inserción. el tipo de modificación) sobre la tabla o vista que activará el trigger. Esta instrucción especifica la tabla en la que se define el disparador. la inserción del nuevo registro en "ventas" no se realice. si se infringe alguna restricción. al intentar modificar los datos de una tabla para la que se ha definido un disparador.no pueden ser invocados directamente. los eventos para los que se ejecuta y las instrucciones que contiene. actualización o borrado provoca las acciones que el trigger realizará. cuando el valor de "stock" sea menor a la cantidad que se intenta vender. . .luego de "for". Consideraciones generales: . . "update" o "delete". Los disparadores. el disparador se ejecuta automáticamente. las restricciones se comprueban primero. se indica la acción (evento.

restore database. Luego de "for" se coloca el evento (en este caso "insert"). para cada tipo de modificación (inserción. las condiciones que determinan cuando un intento de inserción provoca las acciones que el trigger realizará. se puede crear un "insert trigger" para una tabla que ya tiene otro "insert trigger". Cada vez que se realiza un "insert" sobre "ventas". drop database. Por ejemplo. es decir. El disparador controla que la cantidad que se intenta vender sea menor o igual al stock del libro y actualiza el campo "stock" de "libros".Disparador de inserción (insert trigger) Podemos crear un disparador para que se ejecute siempre que una instrucción "insert" ingrese datos en una tabla. disk resize. Luego de "as" se especifican las condiciones y acciones. load database.Se pueden crear varios triggers para cada evento. restando al valor anterior la cantidad vendida: create trigger DIS_ventas_insertar on ventas for insert as declare @stock int . lo que indica que las inserciones sobre la tabla activarán el trigger. alter database. restore log. actualización o borrado) para una misma tabla. "on" seguido del nombre de la tabla para la cual se establece el trigger.. 142 .Las siguientes instrucciones no están permitidas en un desencadenador: create database. .un disparador se crea solamente en la base de datos actual pero puede hacer referencia a objetos de otra base de datos. Sintaxis básica: create triggre NOMBREDISPARADOR on NOMBRETABLA for insert as SENTENCIAS Analizamos la sintaxis: "create trigger" junto al nombre del disparador. disk init. . reconfigure. load log. Creamos un trigger sobre la tabla "ventas" para el evento se inserción. es decir. el disparador se ejecuta. A continuación veremos la creación de un disparador para el suceso de inserción: "insert triger".

La instrucción "writetext" no activa un disparador. la cantidad ingresada en el nuevo registro de "ventas".codigo where libros. . tiene una estructura similar a la tabla en que se define el disparador. 143 . los registros se agregan a la tabla del disparador y a una tabla denominada "inserted". La tabla "inserted" guarda los valores nuevos de los registros. creamos el disparador ("create trigger") dándole un nombre ("DI_ventas_insertar") sobre ("on") una tabla específica ("ventas") para ("for") el suceso de inserción ("insert"). 16.codigolibro=libros. es decir.codigolibro if (@stock>=(select cantidad from inserted)) update libros set stock=stock-inserted. valor que recuperamos de la tabla "inserted". la tabla en que se intenta la acción. lo que solicitamos es que se le reste al "stock" de "libros".codigo where codigo=inserted. Dentro del trigger se puede acceder a esta tabla virtual "inserted" que contiene todos los registros insertados. borra todas las modificaciones que se produjeron en la última transacción restableciendo todo al estado anterior.select @stock= stock from libros join inserted on inserted.cantidad from libros join inserted on inserted. "raiserror" muestra un mensaje de error personalizado.Disparador de borrado (delete trigger) Podemos crear un disparador para que se ejecute siempre que una instrucción "delete" elimine datos en una tabla.codigolibro=libros. controlar que haya stock y disminuir el stock de "libros"). Para identificar fácilmente los disparadores de otros objetos se recomienda usar un prefijo y darles el nombre de la tabla para la cual se crean junto al tipo de acción.codigolibro else begin raiserror ('Hay menos libros en stock de los solicitados para la venta'. las acciones que el trigger realizará cuando se ingrese un registro en "ventas" (en este caso. 1) rollback transaction end Entonces.codigo=inserted. "rollback transaction" es la sentencia que deshace la transacción. es lo que hicimos en el disparador creado anteriormente. es decir. La tabla "inserted" es una tabla virtual que contiene una copia de los registros insertados. Luego se "as" colocamos las sentencias. Cuando se activa un disparador "insert".

Luego de "as" se especifican las condiciones que determinan cuando un intento de eliminación causa las acciones que el trigger realizará. tiene una estructura similar a la tabla en que se define el disparador. los registros eliminados en la tabla del disparador se agregan a una tabla llamada "deleted". Cuando se activa un disparador "delete". si el comprador devuelve los libros comprados): create trigger DIS_ventas_borrar on ventas for delete as update libros set stock= libros.codigo.Sintaxis básica: create triggre NOMBREDISPARADOR on NOMBRETABLA for delete as SENTENCIAS Analizamos la sintaxis: "create trigger" junto al nombre del disparador. "on" seguido del nombre de la tabla para la cual se establece el trigger. para que cada vez que se elimine un registro de "ventas". La tabla "deleted" es una tabla virtual que conserva una copia de los registros eliminados. controlando la cantidad de registros que se están eliminando.codigolibro=libros. el disparador retorna un mensaje de error y deshace la transacción: create trigger DIS_libros_borrar . Entonces. la tabla en que se intenta la acción. El siguiente disparador se crea para controlar que no se elimine más de un registro de la tabla "libros". si se está eliminando más de un registro. Luego de "for" se coloca el evento (en este caso "delete"). El disparador se activa cada vez que se elimina un registro o varios.cantidad from libros join deleted on deleted. Luego de "as" colocamos las sentencias. se actualice el campo "stock" de la tabla "libros" (por ejemplo. las acciones que el trigger realizará cuando se elimine un registro en "ventas" (en este caso.stock+deleted. creamos el disparador ("create trigger") dándole un nombre ("DI_ventas_borrar") sobre ("on") una tabla específica ("ventas") para ("for") el evento de borrado ("delete"). es decir. lo que indica que las eliminaciones sobre la tabla activarán el trigger. Dentro del trigger se puede acceder a esta tabla virtual "deleted". El disparador del siguiente ejemplo se crea para la tabla "ventas". aumentar el stock de "libros").

Si se ejecuta el siguiente "delete". Luego de "for" se coloca el evento (en este caso "update"). es decir. La sentencia "truncate table" no puede incluirse en un disparador de borrado (delete trigger). que afecta a un solo registro. se activa el disparador y permite la transacción: delete from libros where codigo=5. El siguiente disparador de actualización se crea para evitar que se modifiquen los datos de la tabla "libros": create trigger DIS_libros_actualizar on libros .16. se activa el disparador y evita la transacción. lo que indica que las actualizaciones sobre la tabla activarán el trigger. Luego de "as" se especifican las condiciones y acciones. Si se ejecuta un "delete" sobre "libros" que afecte a varios registros.on libros for delete as if (select count(*) from deleted) > 1 begin raiserror('No puede borrar más de un libro'. "on" seguido del nombre de la tabla para la cual se establece el trigger. 144 . Sintaxis básica: create triggre NOMBREDISPARADOR on NOMBRETABLA for update as SENTENCIAS Analizamos la sintaxis: "create trigger" junto al nombre del disparador.Disparador de actualización (update trigger) Podemos crear un disparador para que se ejecute siempre que una instrucción "update" actualice los datos de una tabla.1) rollback transaction end. las condiciones que determinan cuando un intento de modificación provoca las acciones que el trigger realizará.

pero permite la transacción.titulo+'-'+ d. 1) rollback transaction end.editorial) as 'registro actualizado' from deleted as d . así. Creamos un disparador que evite que se actualice el campo "precio" de la tabla "libros": create trigger DIS_libros_actualizar_precio on libros for update as if update(precio) begin raiserror('El precio de un libro no puede modificarse. creamos el disparador ("create trigger") dándole un nombre ("DI_libros_actualizar") sobre una tabla específica ("libros") para ("for") el suceso de actualización ("update"). los registros originales (antes de ser actualizados) se mueven a la tabla virtual "deleted" y los registros actualizados (con los nuevos valores) se copian a la tabla virtual "inserted".for update as raiserror('Los datos de la tabla "libros" no pueden modificarse'. Dentro del trigger se puede acceder a estas tablas. (d.autor+'-'+i. 10. En el cuerpo de un trigger se puede emplear la función "update(campo)" que recibe un campo y retorna verdadero si el evento involucra actualizaciones (o inserciones) en ese campo. en caso contrario retorna "false". realizará las acciones apropiadas (mostrar un mensaje y deshacer la actualización).autor+'-'+d.titulo+'-'+ i. las acciones que el trigger realizará cuando se intente actualizar uno o varios registros en "libros" (en este caso. Empleamos "if update()" para que el trigger controle la actualización del campo "precio". Cuando se ejecuta una instrucción "update" en una tabla que tiene definido un disparador.editorial) as 'registro anterior'. cuando el disparador detecte una actualización en tal campo.codigo. 1) rollback transaction Entonces. en caso que se actualice otro campo. (i. Luego de "as" colocamos las sentencias. impedir las modificaciones). el disparador se activa.'. 10. Creamos un disparador de actualización que muestra el valor anterior y nuevo valor de los registros actualizados: create trigger DIS_libros_actualizar2 on libros for update as if (update(titulo) or update(autor) or update(editorial)) and not (update(precio) or update(stock)) begin select d.

join inserted as i on d.documento) begin raiserror('El socio debe matriculas. si intentamos modificarlo. SQL Server muestra un mensaje de error y el trigger no llega a dispararse. esto es porque tal campo. en tal caso. Dijimos que un disparador puede definirse para más de una acción. no puede modificarse porque está definido "identity". El trigger se define para ambos eventos en la misma sentencia de creación. 145 .codigo=i. create trigger dis_inscriptos_insert_delete on inscriptos for insert. autor y editorial) y no en los campos prohibidos (precio y stock)).'. no puede inscribirse en otro curso'.delete as if exists (select *from inserted join morosos on morosos. mostrará los antiguos y nuevos valores consultando las tablas "deleted" e "inserted". 1) rollback transaction end . Creamos un trigger para evitar que se inscriban socios que deben matrículas y no permitir que se eliminen las inscripciones de socios deudores.documento) begin raiserror('El socio es moroso. update y delete).documento=inserted. en caso que se actualice un campo no permitido. 16. el disparador muestra un mensaje y deshace la transacción. La actualización no se realizó. Empleamos "if update" para que el trigger controle si la actualización se realiza en ciertos campos permitidos (titulo.codigo end else begin raiserror('El precio y stock no pueden modificarse. 10. deben separarse con comas. no puede borrarse su inscripcion'.documento=deleted. 1) rollback transaction end. 1) rollback transaction end else if exists (select *from deleted join morosos on morosos.Disparadores (varios eventos) Hemos aprendido a crear disparadores para diferentes eventos (insert. 16. Note que el disparador no controla los intentos de actualización sobre el campo "codigo". si se modifican los campos permitidos y ninguno de los no permitidos.

"sp_depends": retorna 2 resultados: 1) el nombre.else if (select matricula from inserted)='n' insert into morosos select documento from inserted. 148 ."sp_helptext": seguido del nombre de un disparador nos muestra el texto que define el trigger. campos.inscriptos user table yes numerocurso . se deshace la transacción. etc. El trigger controla: . incluidos los triggers. así que para obtener información de ellos pueden usarse los siguientes procedimientos almacenados del sistema y las siguientes tablas: . Si le enviamos como argumento el nombre de un disparador.condicionales user table yes fecha dbo.si se intenta eliminar una inscripción de un socio que está en "morosos". se deshace la transacción. excepto si ha sido encriptado. dicho socio se ingresa a la tabla "morosos". En la columna "Object_type" aparece "trigger" si es un disparador.si se ingresa una nueva inscripción y no se paga la matrícula. . el tipo de objeto y la fecha de creación. ejecutamos "sp_depends" seguido del nombre de un disparador: sp_depends dis_inscriptos_insertar.Disparador (información) Los triggers (disparadores) son objetos. .si se intenta ingresar una inscripción de un socio moroso. Por ejemplo. obtenemos el propietario. . Aparece una tabla similar a la siguiente: name type updated column ----------------------------------------------------------------dbo. tipo. . de los objetos de los cuales depende el objeto enviado (referenciados por el objeto) y 2) nombre y tipo de los objetos que dependen del objeto nombrado (que lo referencian).condicionales user table yes codigocurso dbo."sp_help": sin parámetros nos muestra todos los objetos de la base de datos seleccionada.

solamente se consulta). aparecen los objetos que dependen de ella (que la referencian).condicionales dbo. las 2 últimas columnas indican el momento de disparo (un valor 1 se interpreta como verdadero y un 0 como falso). También podemos ejecutar el mismo procedimiento seguido del nombre de una tabla: sp_depends inscriptos. . En este ejemplo: 1 solo objeto.xtype as tipo. No aparecen objetos que dependen del trigger porque no existe ningún objeto que lo referencie.inscriptos dbo. su nombre y tipo (trigger).crdate as fecha from sysobjects where xtype = 'TR'.inscriptos user table yes fecha user table yes documento user table no numero user table no cantidadmaxima user table yes documento En la columna "name" nos muestra las tablas (y demás objetos si hubiese) de las cuales depende el trigger. el tipo de objeto en la columna "type" (en este caso. las tablas referenciadas en el mismo. No aparecen objetos de los cuales depende porque la tabla no los tiene. La columna "xtype" indica el tipo de objeto. Si es un trigger muestra "TR".dbo. En el ejemplo.cursos dbo. la columna "column" muestra el nombre del campo que se referencia.cursos dbo. la columna "update" indica si el objeto es actualizado o no (note que la tabla "cursos" no se actualiza. es decir. Si queremos ver el nombre. podemos tipear: select name. podemos ejecutar el procedimiento del sistema "sp_helptrigger" seguido del nombre de la tabla o vista. el disparador "dis_inscriptos_insertar" está definido para el evento de inserción (valor 1 en "isinsert") y es "instead of" (valor 1 en "isinsteadof"). .Para conocer los disparadores que hay en una tabla específica y sus acciones respectivas. tipo y fecha de creación de todos los disparadores. Por ejemplo: sp_helptrigger inscriptos.La tabla del sistema "sysobjects": muestra nombre y varios datos de todos los objetos de la base de datos actual. Nos muestra la siguiente información: trigger_name trigger_owner isupdate isdelete isinsert isinsteadof -----------------------------------------------------------------------------------------------------------dis_inscriptos_insertar dbo 0 0 isafter 1 0 1 El nombre del trigger. su propietario. todas tablas). en las 3 columnas siguientes indica para qué evento se ha definido (un valor 1 indica que está definido para tal evento). .

1) rollback transaction end. Si se deshabilita un disparador.16. "update" o "delete" en la tabla. Sintaxis para deshabilitar o habilitar un disparador: alter table NOMBRETABLA ENABLE | DISABLE trigger NOMBREDISPARADOR. el disparador se ejecutará cada vez que se actualice la tabla. Por ejemplo. no se activa. .149 . 150 . o todos los disparadores que tenga definidos.Disparador (modificar) Los triggers pueden modificarse y eliminarse. Al modificar la definición de un disparador se reemplaza la definición existente del disparador por la nueva definición. éste sigue existiendo. si creó un disparador para "insert" y luego se modifica el evento por "update". La sintaxis general es la siguiente: alter trigger NOMBREDISPARADOR NUEVADEFINICION.disparador (deshabilitar y habilitar) Se puede deshabilitar o habilitar un disparador específico de una tabla o vista. Asumiendo que hemos creado un disparador llamado "dis_empleados_borrar" que no permitía eliminar más de 1 registro de la tabla empleados. Se puede cambiar el evento del disparador. alteramos el disparador. para que cambia la cantidad de eliminaciones permitidas de 1 a 3: alter trigger dis_empleados_borrar on empleados for delete as if (select count(*) from deleted)>3--antes era 1 begin raiserror('No puede borrar mas de 3 empleados'. pero al ejecutar una instrucción "insert".

insert. El siguiente ejemplo deshabilitamos dos triggers definidos sobre la tabla empleados: alter table empleados disable trigger dis_empleados_actualizar. especificando el momento de ejecución (after o instead of). La siguiente sentencia habilita todos los triggers de la tabla "empleados": alter table empleados enable trigger all. Podemos encriptar los triggers para evitar que sean leídos con "sp_helptext". 151 . Se pueden deshabilitar (o habilitar) varios disparadores en una sola sentencia. eliminación o actualización).El siguiente ejemplo deshabilita un trigger: alter table empleados disable trigger dis_empleados_borrar. separando sus nombres con comas.Disparador (with encryption) Hasta el momento hemos aprendido que un trigger se crea sobre una tabla (o vista). Sintaxis para habilitar (o deshabilitar) todos los disparadores de una tabla específica: alter table NOMBRETABLA ENABLE | DISABLE TRIGGER all. Para ello debemos agregar al crearlos la opción "with encryption" luego del nombre de la tabla o vista: create triggre NOMBREDISPARADOR on NOMBRETABLAoVISTA with encryption MOMENTODEDISPARO--after o instead of ACCION-. delete as SENTENCIAS El siguiente disparador se crea encriptado: create trigger DIS_empleados_insertar on empleados with encryption . update. dis_empleados_insertar. para un evento (inserción.

after insert as if (select seccion from inserted)='Gerencia' begin raiserror('No puede ingresar empleados en la sección "Gerencia". Entonces. SQL Server mostrará un mensaje indicando que tal disparador ha sido encriptado.codigo=libros. Se permite actualizar el stock de varios libros a la vez. "update" o "delete" que invoque a un disparador puede afectar a varios registros.codigo=libros. pero ningún "stock" debe tener un valor negativo. un trigger rechaza o acepta cada transacción de modificación como una totalidad.codigo join inserted on inserted. si algún registro no la cumple. 152 . 1) rollback transaction end. Podemos optar por: 1) procesar todos los registros: todos los registros afectados deberán cumplir los criterios del disparador para que se produzca la acción.codigo where inserted. .stock<0. Tenemos la tabla "libros". no debe cambiar. Veamos un ejemplo. la acción no se produce para tal registro pero si para los demás que si la cumplen. Si ejecutamos el procedimiento almacenado del sistema "sp_helptext" seguido del nombre del trigger creado anteriormente. Creamos un disparador de actualización sobre la tabla "libros".'. 16. En tales casos.stock from libros join deleted on deleted. los demás si: create trigger dis_libros_actualizar on libros after update as if exists (select *from inserted where stock<0) begin update libros set stock=deleted.Disparador (condicionales) Una instrucción "insert". o 2) permitir acciones condicionales: puede definir un disparador que controle si cada registro afectado cumple con la condición. si algún "stock" queda con un valor negativo. end.

Lo que hacemos es. si es así. . en el cuerpo del trigger. Tampoco podemos evitar que se actualicen todos los registros porque se actualizan antes que las acciones del trigger se ejecuten. averiguar si alguno de los registros actualizados tiene stock negativo.No podemos revertir la transacción con "rollback transaction" porque en ese caso TODOS los registros modificados volverían a los valores anteriores. y lo que necesitamos es que solamente aquellos que quedaron con valor negativo vuelvan a su valor original. volvemos a actualizarlo al valor anterior a la transacción.

Sign up to vote on this title
UsefulNot useful