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:

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

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

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

Podemos comparar valores numéricos. Por ejemplo. No son los únicos. 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. Los operadores relacionales vinculan un campo con un valor para que SQL Server compare cada registro (el campo especificado) con el valor dado. por ejemplo: select *from libros where autor='Borges'.Hemos aprendido a especificar condiciones de igualdad para seleccionar registros de una tabla. 8 . Utilizamos el operador relacional de igualdad. 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. existen otros que veremos mas adelante. precio from libros where precio>20. para ello usamos la condición: select * from libros where autor<>'Borges'. Los operadores relacionales comparan valores del mismo tipo.Borrar registros (delete) .

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Con esta función aparece una nueva columna en la salida.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. 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". pero no es compatible con "all". count(*) as cantidad from visitantes group by ciudad with rollup. Con "cube" se puede emplear "where" y "having".seccion (sexo y estadocivil seteados a "null") y .estadocivil (sexo y seccion seteados a "null"). 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. aparece la siguiente salida: ciudad ------------------------cantidad . 41 . Es decir.. "cube" genera filas de resumen de subgrupos para todas las combinaciones posibles de los valores de los campos por los que agrupamos. una por cada "grouping". 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. 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".

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

ciudad. la cláusula "compute by" puede incluir los siguientes subconjuntos de campos: . "Compute by" genera cortes de control y subtotales.. 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". 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). El campo que se coloque en la cláusula "compute" debe estar incluida en la lista de campos del "select"..montocompra from visitantes compute avg(edad). En una misma instrucción se pueden colocar varias cláusulas "compute": select edad. 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.ciudad. Si la cláusula "order by" tiene los siguientes campos: . order by a. select nombre. Produce la misma salida que las siguientes 2 sentencias: select *from visitantes.ciudad.provincia from visitantes order by provincia compute count(provincia) by provincia.b. select avg(montocompra) from visitantes.ciudad compute count(provincia) by provincia.sum(montocompra). Se generan filas de detalle y varios valores de resumen cuando cambian los valores del campo.provincia from visitantes order by provincia.compute FUNCION(CAMPO)...c. 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.ciudad.

es decir. Por ejemplo.ciudad compute avg(edad).. 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). by a. ... queremos conocer todos los autores de los cuales tenemos libros..count(provincia) by provincia.b...c.. También podemos tipear: select autor from libros group by autor.... 43 . compute . Aparecen repetidos..Registros duplicados (distinct) Con la cláusula "distinct" se especifica que los registros con ciertos datos duplicados sean obviadas en el resultado.b. Para obtener la lista de autores sin repetición usamos: select distinct autor from libros.. text e image no se pueden incluir en una cláusula "compute" o "compute by". compute . no queremos incluir "null" en la lista. by a.ciudad. 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. podemos utilizar la sentencia siguiente: select distinct autor from libros where autor is not null.. o ... Los tipos de datos ntext.. compute .. si utilizamos esta sentencia: select autor from libros. sum(montocompra) compute avg(montocompra).. by a. Note que en los tres casos anteriores aparece "null" como un valor para "autor"· Si sólo queremos la lista de autores conocidos.

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

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

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

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

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

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

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

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

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

Un campo con una restricción "primary key" puede tener una restricción "check". cuando demos el nombre a las restricciones "primary key" seguiremos el formato "PK_NOMBRETABLA_NOMBRECAMPO". primary key(codigo) ). Por convención. automáticamente SQL Server redefinía el campo como "not null". Sabemos que cuando agregamos una restricción a una tabla que contiene información. . la restricción no se aplica y aparece un mensaje de error. si intentamos ingresar un registro con un valor para el campo "codigo" que ya existe o el valor "null". si intentamos definir la restricción "primary key" para "libros" y hay registros con códigos repetidos o con un valor "null".). seguido del nombre de la tabla y una serie de letras y números aleatorios. Dicha restricción. los campos que son clave primaria DEBEN haber sido definidos "not null" (o ser implícitamente "not null" si se definen identity). pero al agregar una restricción "primary key". Si ejecutamos el procedimiento almacenado "sp_helpconstraint" junto al nombre de la tabla.. Con esta restricción. que asegura la unicidad de cada registro de una tabla. a la cual no le dábamos un nombre. podemos ver las restricciones "primary key" (y todos los tipos de restricciones) de dicha tabla. aparece un mensaje de error. si actualizamos. 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. SQL Server permite definir solamente una restricción "primary key" por tabla. Por ejemplo.editorial varchar(20). SQL Server controla los datos existentes para confirmar que cumplen las exigencias de la restricción. 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.. Cuando establecíamos una clave primaria al definir la tabla. SQL Server creaba automáticamente una restricción "primary key" para dicha tabla. si no los cumple. Igualmente. recibía un nombre dado por SQL Server que comienza con "PK" (por primary key). la restricción no se establece. Cada vez que establecíamos la clave primaria para la tabla.

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

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

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

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

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

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

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

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

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

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

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

SQL Server no lo permite. también se puede especificar que sea "unique". el índice será no agrupado (nonclustered). Si se intenta crear un índice unique para un campo que tiene valores duplicados. "TIPODEINDICE" indica si es agrupado (clustered) o no agrupado (nonclustered).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". es decir. .create TIPODEINDICE index NOMBREINDICE on TABLA(CAMPO). no haya valores repetidos. el índice será agrupado (clustered) a menos que ya exista un índice agrupado para dicha tabla.tema que veremos posteriormente). Si no especificamos crea uno No agrupado. son índices compuestos. por ejemplo "I" y luego el nombre de la tabla y/o campo. 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). si no se especifica. Independientemente de si es agrupado o no. Al crear una restricción "primary key". Al crear una restricción "unique". Los campos de un índice compuesto tienen que ser de la misma tabla (excepto cuando se crea en una vista . 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). Creamos un índice compuesto para el campo "autor" y "editorial": create index I_libros_autoreditorial on libros(autor. 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). Un índice puede tener más de un campo como clave. podemos agregar un prefijo al nombre del índice. Para identificar los índices fácilmente. 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. si no se especifica.

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

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

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

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

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

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

codigo. es decir.codigo=codigoeditorial where codigoeditorial is null. En el siguiente ejemplo solicitamos el título y nombre de la editorial de los libros empleando un "right join": select titulo.nombre from editoriales as e left join libros as l on e. que NO encuentran coincidencia en la tabla de la derecha: select titulo. la diferencia está en el orden de las tablas: select titulo. El resultado mostrará el título del libro y el nombre de la editorial. pero con el valor "null" en el campo "nombre". es decir.En el siguiente ejemplo solicitamos el título y el nombre la editorial. el registro muestra los campos correspondientes a la tabla de la derecha seteados a "null".codigo=codigoeditorial where codigoeditorial is not null.nombre from libros as l left join editoriales as e on codigoeditorial = e. la sentencia es similar a la anterior.nombre from editoriales as e left join libros as l on e.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.nombre from libros as l . 68 . 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. cuyo valor de código está presente en "libros": select titulo. 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. También podemos mostrar las editoriales que NO están presentes en "libros". los títulos cuyo código de editorial no está presente en "editoriales" aparecen en el resultado.

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

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". retorna 30 filas. La sintaxis básica es ésta: select CAMPOS from TABLA1 cross join TABLA2. es decir. 2) combinaciones externas (left. 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. 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. 69 . Si un registro de una tabla izquierda no encuentra coincidencia en la tabla derecha.Combinaciones cruzadas (cross join) Vimos que hay tres tipos de combinaciones: 1) combinaciones internas (join). los campos de esta última aparecen conteniendo "null". 70 . La salida del "full join" precedente muestra todos los registros de ambas tablas. Las combinaciones cruzadas (cross join) muestran todas las combinaciones de todos los registros de las tablas combinadas. Una combinación externa completa ("full outer join" o "full join") retorna todos los registros de ambas tablas. y si la tabla de la derecha no encuentra correspondencia en la tabla izquierda. el registro muestra los campos correspondientes a la tabla de la derecha seteados a "null". si hay 5 registros en una tabla y 6 en la otra.codigo. right y full join) y 3) combinaciones cruzadas. las columnas correspondientes a campos de la tabla derecha aparecen seteadas a "null".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. Veamos un ejemplo: select titulo.nombre from editoriales as e full join libros as l on codigoeditorial = e. .where codigoeditorial is null. Para este tipo de join no se incluye una condición de enlace.

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

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

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

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

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). longitud o atributos de una clave foránea. Las claves foráneas y las claves primarias deben ser del mismo tipo para poder enlazarse. se emplea para enlazar la tabla "libros" con "editoriales" y es clave primaria en "editoriales" con el nombre "codigo". para establecer un "join" con otra tabla en la cual es clave primaria. se define una referencia a un campo con una restricción "primary key" o "unique" de la misma tabla o de otra. 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. debemos modificar la otra para que los valores se correspondan.NOMBRETABLA1 referencia el nombre de la tabla a la cual le aplicamos la restricción. la analizaremos ahora. Por ejemplo. es decir. 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. . 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. La integridad referencial asegura que se mantengan las referencias entre las claves primarias y las externas. 76 . vimos que existen distintos tipos de restricciones: 1) de los campos: default y check 2) de la tabla: primary key y unique.el campo "codigoeditorial" de "libros" es una clave foránea. tal código exista en la tabla "editoriales". una clave foránea es un campo (o varios) empleados para enlazar datos de 2 tablas. Analicémosla: . debemos tener cuidado con las claves foráneas. controla que si se agrega un código de editorial en la tabla "libros". Entonces. Por ejemplo. ésta puede quedar inhabilitada para hacer los enlaces. Cuando alteramos una tabla. que no se pueda eliminar o modificar un código de "editoriales" si existen libros con dicho código. Si modificamos el tipo. Si modificamos una.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). 3) referencial: foreign key.

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

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

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

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

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

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

constraint UQ_libros_tituloautor unique (titulo.Hasta el momento hemos agregado restricciones a tablas existentes con "alter table" (manera aconsejada). . constraint PK_libros_codigo primary key clustered (codigo). constraint CK_precio_positivo check (precio>=0) ).codigoautor). constraint FK_libros_autores foreign key (codigoautor) references autores(codigo) on update cascade. En el ejemplo anterior creamos: . 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"). codigoautor int not null.una restricción "primary key" con índice agrupado para el campo "codigo" (a nivel de tabla). codigoeditorial tinyint not null. . .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. Podemos aplicar restricciones a nivel de campo (restricción de campo) o a nivel de tabla (restricción de tabla). precio decimal(5.2) constraint DF_precio default (0). 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).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. también pueden establecerse al momento de crear una tabla (en la instrucción "create table").una restricción "check" para el campo "precio" que no admita valores negativos. . .

Se usa cuando los datos que se quieren obtener pertenecen a distintas tablas y no se puede acceder a ellos con una sola consulta. Los encabezados del resultado de una unión son los que se especifican en el primer "select".Agregar y eliminar campos ( alter table . 83 . 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". Puede dividir una consulta compleja en varias consultas "select" y luego emplear el operador "union" para combinarlas. Es necesario que las tablas referenciadas tengan tipos de datos similares. 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. Puede emplear la cláusula "order by". domicilio from profesores.Si definimos una restricción "foreign key" al crear una tabla. Para obtener los datos necesarios de ambas tablas en una sola consulta necesitamos realizar una unión: select nombre.drop) "alter table" permite modificar la estructura de una tabla. 82 . modificar y eliminar campos de una tabla. 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". la misma cantidad de campos y el mismo orden de campos en la lista de selección de cada consulta.add . domicilio from alumnos union select nombre.Unión El operador "union" combina el resultado de dos o más instrucciones "select" en un único resultado. la tabla referenciada debe existir. No se incluyen las filas duplicadas en el resultado. Podemos utilizarla para agregar. a menos que coloque la opción "all". el segundo. El primer "select" devuelve el nombre y domicilio de todos los alumnos.

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

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

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

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

92 .si el "where" de la consulta exterior incluye un campo.una subconsulta puede estar anidada dentro del "where" o "having" de una consulta externa o dentro de otra subconsulta. . Podemos conseguirlo en una sola sentencia combinando dos consultas: .Subconsultas como expresión Una subconsulta puede reemplazar una expresión.. .una vista creada con una subconsulta no puede actualizarse.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". . . calcular la diferencia con el valor del libro que solicitamos. select CAMPO OPERADOR (SUBCONSULTA) from TABLA. anteriormente debíamos averiguar en una consulta el precio del libro más costoso y luego.no se pueden emplear subconsultas que recuperen campos de tipos text o image."order by" puede emplearse solamente si se especifica "top" también. Si queremos saber el precio de un determinado libro y la diferencia con el precio del libro más costoso. los campos no serán incluidos en la salida (en la lista de selección de la consulta externa)."distinct" no puede usarse con subconsultas que incluyan "group by".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"). . . 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). . Dicha subconsulta debe devolver un valor escalar (o una lista de valores de un campo). . este debe ser compatible con el campo en la lista de selección de la subconsulta.no pueden emplearse las cláusulas "compute" y "compute by".si una tabla se nombra solamente en un subconsulta y no en la consulta externa. . en otra consulta.

Note que el campo del "where" de la consulta exterior es compatible con el valor retornado por la expresión de la subconsulta. 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"). Queremos saber el título. Para actualizar un registro empleando subconsulta la sintaxis básica es la siguiente: update TABLA set CAMPO=NUEVOVALOR where CAMPO= (SUBCONSULTA). precio from libros where precio= (select max(precio) from libros).autor.Subconsultas con in Vimos que una subconsulta puede reemplazar una expresión. Se pueden emplear en "select".precio. autor y precio del libro más costoso: select titulo. 93 .select titulo. "insert". el precio de un libro y la diferencia entre el precio del libro y el máximo valor de precio. "update" y "delete". En el ejemplo anterior se muestra el título. 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". las subconsultas que retornan una lista de valores reemplazan a una expresión en una cláusula "where" que contiene la palabra clave "in". Dicha subconsulta debe devolver un valor escalar o una lista de valores de un campo. Para eliminar registros empleando subconsulta empleamos la siguiente sintaxis básica: delete from TABLA where CAMPO=(SUBCONSULTA). . precio-(select max(precio) from libros) as diferencia from libros where titulo='Uno'.

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

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

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

*. 95 .numerofactura) as cantidad. A este tipo de subconsulta se la denomina consulta correlacionada. la fecha.Exists y No Exists Los operadores "exists" y "not exists" se emplean para determinar si hay o no datos en una lista de valores.preciounitario*cantidad) from Detalles as d where f. 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). 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. 96 . 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 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).numerofactura) as total from facturas as f. el primer "select" (externo) devuelve todos los datos de cada factura. si existe. específicamente. El campo de la tabla dentro de la subconsulta (f. En este caso. Estos operadores retornan "true" (si las subconsultas retornan registros) o "false" (si las subconsultas no retornan registros). Se necesita una lista de todas las facturas que incluya el número. la cantidad de artículos comprados y el total: select f. .numero=d. La consulta interna se evalúa tantas veces como registros tiene la consulta externa. El proceso se repite para el registro de la consulta externa. se realiza la subconsulta para cada registro de la consulta externa. La consulta interna toma ese valor y determina si existe en "detalles".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.numeroitem) from Detalles as d where f.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".numero=d. el cliente. (select sum(d. (select count(d. el precio (unitario) y la cantidad. la consulta externa pasa otro "numero" a la consulta interna y SQL Server repite la evaluación. la consulta externa pasa un valor de "numero" a la consulta interna. la consulta interna devuelve la suma.numero) se compara con el campo de la tabla externa.

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=

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

nota) from alumnos. se crea una nueva tabla y se inserta en ella el resultado de una consulta a otra tabla. se puede insertar registros en una tabla con la salida devuelta por una consulta a otra tabla. La cantidad de columnas devueltas en la consulta debe ser la misma que la cantidad de campos a cargar en el "insert". contendrá solamente un campo llamado "nombre". Tenemos la tabla "libros" de una librería y queremos crear una tabla llamada "editoriales" que contenga los nombres de las editoriales. Entonces. 101 . La tabla libros contiene varios registros. tipo de dato y valores almacenados que los campos listados de la tabla consultada. que no existe. La tabla "editoriales". 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. Los campos de la nueva tabla tienen el mismo nombre. Se pueden insertar valores en una tabla con el resultado de una consulta que incluya cualquier tipo de "join". Es decir.nota) select (documento. si se quiere dar otro nombre a los campos de la nueva tabla se deben especificar alias.insert into aprobados (documento.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.Crear tabla a partir de otra (select . . La tabla "editoriales" se ha creado con el campo "nombre" seleccionado del campo "editorial" de "libros". 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).

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

Una vista es como una tabla virtual que almacena una consulta. se puede dar un nombre a cualquier consulta y almacenarla como una vista. pudiendo modificar tales datos. así se protegen las tablas base de cambios en su estructura.Vistas Una vista es una alternativa para mostrar datos de varias tablas. La sintaxis básica parcial para crear una vista es la siguiente: create view NOMBREVISTA as SENTENCIASSELECT from TABLA. una combinació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. un resumen estadístico de una tabla. 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. Las tablas consultadas en una vista se llaman tablas base. Entonces. un subconjunto de otra vista. combinación de vistas y tablas. El usuario opera con los datos de una vista como si se tratara de una tabla. una unión de varias tablas.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. 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. El contenido de una vista se muestra con un "select": .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. una vista almacena una consulta como un objeto para utilizarse posteriormente.) al finalizar una instrucción. 103 . En general.Recuerde que si coloca "go" no debe incluir el "punto y coma" (. Una vista se define usando un "select". en lugar de concederle permisos para acceder a ciertos campos. Podemos crear vistas con: un subconjunto de registros y campos de una tabla. Las vistas permiten: .

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

Existen algunas restricciones para el uso de "create view".create view vista_empleados_ingreso (fecha. excepto si ha sido encriptado. Si no los colocamos y empleamos la sintaxis vista anteriormente. 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. a saber: . .Vistas (información) Las vistas son objetos.fechaingreso). incluidas las vistas. SQL Server verifica que existan las tablas a las que se hacen referencia en ella. 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.count(*) from empleados group by datepart(year.cantidad) as select datepart(year. propietario.fechaingreso) La diferencia es que se colocan entre paréntesis los encabezados de las columnas que aparecerán en la vista. . Las vistas se crean en la base de datos activa. 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. "sp_helptext" seguido del nombre de una vista nos muestra el texto que la define.no se pueden asociar reglas ni valores por defecto a las vistas. En la columna "Object_type" aparece "view" si es una vista. obtenemos 2 resultados: . Ejecutando "sp_depends" seguido del nombre de un objeto.no puede incluir las cláusulas "compute" ni "compute by" ni la palabra clave "into". Al crear una vista.no se pueden crear vistas temporales ni crear vistas sobre tablas temporales. obtenemos la fecha de creación.no puede combinarse con otras instrucciones en un mismo lote. Los nombres que se colocan entre paréntesis deben ser tantos como los campos o expresiones que se definen en la vista. . los campos y demás información. 104 . Si le enviamos como argumento el nombre de una vista. Se pueden construir vistas sobre otras vistas.

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

Vistas (eliminar) Para quitar una vista se emplea "drop view": drop view NOMBREVISTA."with encryption" indica a SQL Server que codifique las sentencias que definen la vista. hay que eliminarla explícitamente. 106 . creamos la siguiente vista: create view vista_empleados . s.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.nombre) as nombre. Por ejemplo. se recomienda ejecutar el procedimiento almacenado de sistema "sp_depends" para averiguar si hay objetos que hagan referencia a él. 107 . aparece un mensaje indicando tal situación y el texto no se muestra. 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. Si se elimina una tabla a la que hace referencia una vista.sexo. Antes de eliminar un objeto. Eliminamos la vista denominada "vista_empleados": drop view vista_empleados. la vista no se elimina. Solo el propietario puede eliminar una vista.nombre as seccion. Creamos una vista con su definición oculta: create view vista_empleados with encryption as select (apellido+' '+e.

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

cantidadhijos. Si crea una vista con "select *" y luego agrega campos a la estructura de las tablas involucradas. si no encuentra ninguna coincidencia. Finalmente se coloca "end" para indicar que el "case" ha finalizado. 110 . else RESULTADO3 end Por cada valor hay un "when" y un "then". esto es porque los campos se seleccionan al ejecutar "create view".nombre) as nombre. .sexo. debe alterar la vista.nombre as seccion. desaparece. puede ser nulo). debe colocarla nuevamente. . si encuentra un valor coincidente en algún "where" ejecuta el "then" correspondiente a ese "where".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. se ejecuta el "else". s.nota (valor entero entre 0 y 10.. 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.Lenguaje de control de flujo (case) La función "case" compara 2 o más valores y devuelve un resultado. en caso de no hacerlo.nombre (30 caracteres). La sintaxis es la siguiente: case VALORACOMPARAR when VALOR1 then RESULTADO1 when VALOR2 then RESULTADO2 . si no hay parte "else" retorna "null". Un profesor guarda las notas de sus alumnos de un curso en una tabla llamada "alumnos" que consta de los siguientes campos: .

. 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. La sintaxis es la siguiente: case when VALORACOMPARAR OPERADOR VALOR1 then RESULTADO1 when VALORACOMPARAR OPERADOR VALOR2 then RESULTADO2 . Podemos realizar comparaciones en cada "where". 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. nota. condicion= case when nota<4 then 'libre' when nota >=4 and nota<7 then 'regular' when nota>=7 then 'promocionado' ..Queremos mostrar los nombres. 2 ó 3: 'libre'.0. por ello los valores devueltos son iguales para algunos casos.7.nota. . 8. en caso que el valor no encuentre coincidencia con ninguno valor "when".4. 5 ó 6: 'regular'. está entre 4 y 7 o supera el 7: select nombre. 9 ó 10: 'promocionado'. Esta es la sentencia: select nombre. Note que como omitimos la parte "else".. Note que cada "where" compara un valor puntual. 1. retorna "null". 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: .

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

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

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. 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. la sintaxis es: select @nombre = autor from libros where titulo='Uno' Podemos ver el contenido de una variable con: select @nombre. La utilidad de las variables consiste en que almacenan valores para utilizarlos en otras consultas.declare @variable varchar(10). Por ejemplo. 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. Una variable puede tener comodines: declare @patron varchar(30) set @patron='B%' select autor from libros where autor like @patron. Disponemos punto y coma solo al final de la última instrucción del lote. Una variable a la cual no se le ha asignado un valor contiene "null". select @variable. Si le asignamos un valor resultado de una consulta.

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

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

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

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 e image (escribir) La función "writetext" sobreescribe (reemplaza) el texto de un campo "text". tal puntero debe ser válido. 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.'. no se crea un puntero válido y al intentar leer dicho campo ocurre un error. Luego de "writetext" se coloca el nombre de la tabla y el campo (text.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. "DATO" es el texto que almacena. 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. "ntext" o "image" o no se ingresan datos. "ntext" o "image".CAMPO PUNTEROATEXTO DATO. puede ser una variable o un literal.sinopsis'. "ntext" o "image" o no se ingresan datos. no se crea un puntero válido y al intentar escribir dicho campo ocurre un error. porque la función "writetext" requiere un puntero válido. porque la función "readtext" requiere un puntero válido. 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 . No puede emplearse en vistas. Sintaxis: writetext TABLA. @puntero)=1) readtext libros. 116 .Tipo de dato text . ntext o image) a actualizar. "ntext" o "image". "PUNTEROATEXTO" es el valor que almacena el puntero a texto del dato de tipo "text".sinopsis @puntero 9 50 else select 'puntero invalido'.

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

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

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

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

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

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

El valor por defecto puede ser "null" o una constante. un procedimiento definido con parámetros no puede ejecutarse sin valores para ellos. opcionalmente. La sintaxis anterior ejecuta el procedimiento pasando valores a los parámetros por posición. se puede especificar un valor por defecto. editorial.precio from libros where autor= @autor. 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'. 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. . 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. 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'. @autor='Richard Bach'. el nombre de un autor y el de una editorial: create procedure pa_libros_autor_editorial @autor varchar(30). Creamos un procedimiento que recibe 2 parámetros. 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'. precio from libros where autor= @autor and editorial=@editorial. Los valores de un parámetro pueden pasarse al procedimiento mediante el nombre del parámetro o por su posición.'Planeta'. también puede incluir comodines si el procedimiento emplea "like". @editorial varchar(20) as select titulo. Cuando pasamos valores con el nombre del parámetro. el orden en que se colocan puede alterarse. Si no se coloca valor por defecto.

precio from libros where autor like @autor and editorial like @editorial.No podríamos ejecutar el procedimiento anterior sin valores para los parámetros. autor. Es decir. se asume que es el primero.editorial.precio from libros where autor= @autor and editorial=@editorial. . @editorial varchar(30) = '%' as select titulo. La sentencia siguiente ejecuta el procedimiento almacenado "pa_libros_autor_editorial3" enviando un valor por posición. asume que es el primero. Si queremos especificar solamente el segundo parámetro. Si queremos ejecutar un procedimiento que permita omitir los valores para los parámetros debemos. 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) = '%'. @editorial varchar(20)='Planeta' as select titulo. definir valores por defecto para cada parámetro: create procedure pa_libros_autor_editorial2 @autor varchar(30)='Richard Bach'. al crear el procedimiento. La sentencia siguiente ejecuta el procedimiento almacenado "pa_libros_autor_editorial3" enviando un valor para el segundo parámetro.editorial. debemos emplear la sintaxis de paso de valores a parámetros por nombre: exec pa_libros_autor_editorial2 @editorial='Paidos'. exec pa_libros_autor_editorial3 'P%'. Podemos ejecutar el procedimiento anterior sin enviarle valores. 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). usará los predeterminados. no se puede interrumpir la secuencia.autor. SQL Server asume que los valores se dan en el orden que fueron definidos. para el primer parámetro toma el valor por defecto: exec pa_libros_autor_editorial3 @editorial='P%'.

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

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

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

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

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

Esta opción es opcional.precio from libros where autor = @autor. debe incluirla al alterarlo. por necesidad de los usuarios o por cambios en la estructura de las tablas que referencia. Un procedimiento almacenado existente puede modificarse con "alter procedure".editorial. Si ejecutamos el procedimiento almacenado del sistema "sp_helptext" para ver su contenido. 127 . Modificamos el procedimiento almacenado "pa_libros_autor" para que muestre. 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. además del título. Sintaxis: alter procedure NOMBREPROCEDIMIENTO @PARAMETRO TIPO = VALORPREDETERMINADO as SENTENCIAS. 128 . 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.Procedimientos almacenados (modificar) Los procedimientos almacenados pueden modificarse. no aparece.Procedimientos almacenados (insertar) . Si quiere modificar un procedimiento que se creó con la opción "with encryption" y quiere conservarla.

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

@num.set @resultado=1 set @num=@numero while (@num>1) begin exec pa_multiplicar @resultado. SQL Server ofrece tres métodos para recompilar explícitamente un procedimiento almacenado: 1) Se puede indicar. Se realiza la primera vez que se ejecuta un procedimiento almacenado o si el procedimiento almacenado se debe volver a compilar (recompilación). Este procedimiento vuelve a compilar el procedimiento almacenado (o desencadenador) que se especifica. La sintaxis es: . 3) Podemos ejecutar el procedimiento almacenado del sistema "sp_recompile". 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. el segundo (B) tiene acceso a todos los objetos que cree el primero (A). 130 . 2) Podemos especificar "with recompile" al momento de ejecutarlo: exec NOMBREPROCEDIMIENTO with recompile. 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.@resultado). En este caso la sintaxis es la siguiente: create procedure NOMBREPROCEDIMIENTO PARAMETROS with recompile as SENTENCIAS. 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. Cuando un procedimiento (A) llama a otro (B).@numero))+'!='+convert(char. 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. @resultado output set @num=@num-1 end select rtrim(convert(char. al crear el procedimiento.

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

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

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

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

f_nombreMes(fechaingreso) as 'mes de ingreso' from empleados. . especificamos los parámetros de entrada con sus tipos de datos (entre paréntesis). Recuerde que al invocar una función escalar. dbo.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.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. Analicemos: luego de "create function" y el nombre de la función. Las funciones que retornan un valor escalar pueden emplearse en cualquier consulta donde se coloca un campo. luego de "as" comienza el bloque "begin... Luego de los parámetros de entrada se indica el tipo de dato que retorna luego de "returns".@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. 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.

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

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

Las funciones definidas por el usuario pueden modificarse con la instrucción "alter function". Sintaxis para modificar funciones escalares: alter funtion PROPIETARIO. las funciones definidas por el usuario si.precio from dbo.NOMBREFUNCION NUEVADEFINICION. 138 .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) .Se puede llamar a la función como si fuese una tabla o vista listando algunos campos: select titulo.f_ofertas(40).Funciones (modificar) Las funciones de SQL Server no pueden ser modificadas. Sintaxis general: alter function PROPIETARIO.

Sintaxis para modificar funciones escalares: alter funtion PROPIETARIO. 138 .NOMBREFUNCION .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 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. Sintaxis general: alter function PROPIETARIO.editorial from libros where autor like '%'+@autor+'%' ).NOMBREFUNCION NUEVADEFINICION.editorial from libros where autor like '%'+@autor+'%' ).Funciones (modificar) Las funciones de SQL Server no pueden ser modificadas. las funciones definidas por el usuario si. Las funciones definidas por el usuario pueden modificarse con la instrucción "alter function".titulo.

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+'%' ). La modificamos agregando otro campo en el "select": alter table f_libros (@autor varchar(30)='Borges') returns table .(@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.

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-.editorial from libros where autor like '%'+@autor+'%' ). CAMPO3 TIPO ) with encryption as begin insert @NOMBRETABLARETORNO select CAMPOS from TABLA where campo OPERADOR @PARAMETRO RETURN .as return ( select codigo.titulo.Funciones (encriptado) Las funciones definidas por el usuario pueden encriptarse. CAMPO2 TIPO. Para ello debemos agregar al crearlas la opción "with encryption" antes de "as".nombre de la tabla --formato de la tabla (CAMPO1 TIPO. 139 . para evitar que sean leídas con "sp_helptext".

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

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

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

Creamos un trigger sobre la tabla "ventas" para el evento se inserción. 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. restando al valor anterior la cantidad vendida: create trigger DIS_ventas_insertar on ventas for insert as declare @stock int . es decir. Por ejemplo. alter database. Luego de "for" se coloca el evento (en este caso "insert"). Luego de "as" se especifican las condiciones y acciones.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.Se pueden crear varios triggers para cada evento. disk resize. para cada tipo de modificación (inserción. load log. "on" seguido del nombre de la tabla para la cual se establece el trigger. es decir. . 142 .un disparador se crea solamente en la base de datos actual pero puede hacer referencia a objetos de otra base de datos. Cada vez que se realiza un "insert" sobre "ventas". 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". . actualización o borrado) para una misma tabla..Las siguientes instrucciones no están permitidas en un desencadenador: create database. se puede crear un "insert trigger" para una tabla que ya tiene otro "insert trigger". el disparador se ejecuta. A continuación veremos la creación de un disparador para el suceso de inserción: "insert triger". restore log. drop database. restore database. las condiciones que determinan cuando un intento de inserción provoca las acciones que el trigger realizará. lo que indica que las inserciones sobre la tabla activarán el trigger. load database.

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

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

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

impedir las modificaciones).codigo. 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". pero permite la transacción. en caso que se actualice otro campo. 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. Cuando se ejecuta una instrucción "update" en una tabla que tiene definido un disparador. 1) rollback transaction end.autor+'-'+i.titulo+'-'+ i. cuando el disparador detecte una actualización en tal campo. realizará las acciones apropiadas (mostrar un mensaje y deshacer la actualización). 1) rollback transaction Entonces. 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").titulo+'-'+ d. (i.editorial) as 'registro actualizado' from deleted as d . Dentro del trigger se puede acceder a estas tablas. 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. 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.autor+'-'+d. en caso contrario retorna "false". (d. así. el disparador se activa. Empleamos "if update()" para que el trigger controle la actualización del campo "precio". Luego de "as" colocamos las sentencias. 10. las acciones que el trigger realizará cuando se intente actualizar uno o varios registros en "libros" (en este caso.for update as raiserror('Los datos de la tabla "libros" no pueden modificarse'.editorial) as 'registro anterior'.'. 10.

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

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

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

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

El siguiente ejemplo deshabilitamos dos triggers definidos sobre la tabla empleados: alter table empleados disable trigger dis_empleados_actualizar.insert.Disparador (with encryption) Hasta el momento hemos aprendido que un trigger se crea sobre una tabla (o vista). Se pueden deshabilitar (o habilitar) varios disparadores en una sola sentencia. 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-. 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". separando sus nombres con comas. delete as SENTENCIAS El siguiente disparador se crea encriptado: create trigger DIS_empleados_insertar on empleados with encryption .El siguiente ejemplo deshabilita un trigger: alter table empleados disable trigger dis_empleados_borrar. Sintaxis para habilitar (o deshabilitar) todos los disparadores de una tabla específica: alter table NOMBRETABLA ENABLE | DISABLE TRIGGER all. eliminación o actualización). dis_empleados_insertar. para un evento (inserción. 151 . update.

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

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

Sign up to vote on this title
UsefulNot useful