Documente Academic
Documente Profesional
Documente Cultură
63 - Regenerar ndices...........................................................................................................82
64 - Eliminar ndices.............................................................................................................83
65 - Trabajar con varias tablas..............................................................................................84
66 - Combinacin interna (inner join)...................................................................................85
67 - Combinacin externa izquierda (left join).....................................................................87
68 - Combinacin externa derecha (right join).....................................................................89
69 - Combinacin externa completa (full join).....................................................................90
70 - Combinaciones cruzadas (cross join)............................................................................91
71 - Autocombinacin...........................................................................................................92
72 - Combinaciones y funciones de agrupamiento...............................................................93
73 - Combinacin de ms de dos tablas................................................................................94
74 - Combinaciones con update y delete..............................................................................95
75 - Clave fornea.................................................................................................................96
76 - Restricciones (foreign key)............................................................................................97
77 - Restricciones foreign key en la misma tabla.................................................................99
78 - Restricciones foreign key (acciones)...........................................................................100
79 - Restricciones foreign key deshabilitar y eliminar (with check - nocheck)..................101
80 - Restricciones foreign key (informacin).....................................................................103
81 - Restricciones al crear la tabla......................................................................................104
82 - Unin...........................................................................................................................106
83 - Agregar y eliminar campos ( alter table - add - drop)..................................................107
84 - Alterar campos (alter table - alter)...............................................................................108
85 - Agregar campos y restricciones (alter table)...............................................................109
86 - Campos calculados.......................................................................................................110
87 - Tipo de dato definido por el usuario (crear - informacion)..........................................111
88 - Tipo de dato definido por el usuario (asociacin de reglas)........................................112
89 - Tipo de dato definido por el usuario (valores predeterminados).................................113
90 - Tipo de dato definido por el usuario (eliminar)...........................................................114
91 - Subconsultas................................................................................................................114
92 - Subconsultas como expresin......................................................................................115
93 - Subconsultas con in.....................................................................................................117
94 - Subconsultas any - some - all.......................................................................................118
95 - Subconsultas correlacionadas......................................................................................120
96 - Exists y No Exists........................................................................................................121
97 - Subconsulta simil autocombinacin............................................................................122
98 - Subconsulta en lugar de una tabla...............................................................................123
99 - Subconsulta (update - delete).......................................................................................125
100 - Subconsulta (insert)...................................................................................................126
101 - Crear tabla a partir de otra (select - into)...................................................................126
102 - go...............................................................................................................................128
103 - Vistas..........................................................................................................................128
104 - Vistas (informacin)..................................................................................................131
105 - vistas (encriptar)........................................................................................................133
106 - Vistas (eliminar).........................................................................................................134
107 - Vistas (with check option).........................................................................................135
108 - Vistas (modificar datos de una tabla a travs de vistas)............................................135
109 - Vistas modificar (alter view)......................................................................................137
110 - Lenguaje de control de flujo (case)............................................................................138
111 - Lenguaje de control de flujo (if)................................................................................140
112 - Variables de usuario...................................................................................................141
113 - Tipos de datos text, ntext y image..............................................................................143
114 - Tipo de dato text - ntext e image (punteros)..............................................................144
115 - Tipo de dato text - ntext e image (leer)......................................................................145
116 - Tipo de dato text - ntext e image (escribir)................................................................146
117 - Tipo de dato text - ntext e image (actualizar)............................................................148
118 - Tipo de dato text - ntext e image (funciones)............................................................150
119 - Procedimientos almacenados.....................................................................................151
120 - Procedimientos almacenados (crear - ejecutar).........................................................152
121 - Procedimientos almacenados (eliminar)....................................................................154
122 - Procedimientos almacenados (parmetros de entrada)..............................................155
123 - Procedimientos almacenados (parmetros de salida)................................................158
124 - Procedimientos almacenados (return)........................................................................160
El parmetro @table_owner='dbo' indica que solo muestre las tablas de usuarios y no las
que crea el SQL Server para administracin interna.
Finalizamos cada comando con un punto y coma.
Al crear una tabla debemos resolver qu campos (columnas) tendr y que tipo de datos
almacenarn cada uno de ellos, es decir, su estructura.
La sintaxis bsica 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 parntesis 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:
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 alfabtico y no puede contener espacios. La
longitud mxima 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;
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
situacin y la sentencia no se ejecuta. Para evitar este mensaje podemos agregar a la
instruccin lo siguiente:
if object_id('usuarios') is not null
drop table usuarios;
Usamos "insert into", luego el nombre de la tabla, detallamos los nombres de los campos
entre parntesis y separados por comas y luego de la clusula "values" colocamos los
valores para cada campo, tambin entre parntesis y separados por comas.
Para agregar un registro a la tabla tipeamos:
insert into usuarios (nombre, clave) values ('Mariano','payaso');
Note que los datos ingresados, como corresponden a cadenas de caracteres se colocan entre
comillas simples.
Para ver los registros de una tabla usamos "select":
select * from usuarios;
En el ejemplo anterior se nombra primero el campo "clave" y luego el campo "nombre" por
eso, los valores tambin se colocan en ese orden.
Si ingresamos los datos en un orden distinto al orden en que se nombraron los campos, no
aparece un mensaje de error y los datos se guardan de modo incorrecto.
En el siguiente ejemplo se colocan los valores en distinto orden en que se nombran los
campos, 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,clave) values ('Boca','Luis');
varchar: se usa para almacenar cadenas de caracteres. Una cadena es una secuencia
de caracteres. Se coloca entre comillas (simples); ejemplo: 'Hola', 'Juan Perez'. El
tipo "varchar" define una cadena de longitud variable en la cual determinamos el
mximo de caracteres entre parntesis. Puede guardar hasta 8000 caracteres. Por
ejemplo, para almacenar cadenas de hasta 30 caracteres, definimos un campo de
tipo varchar(30), es decir, entre parntesis, junto al nombre del campo colocamos la
longitud.
Si asignamos una cadena de caracteres de mayor longitud que la definida, la cadena
no se carga, aparece un mensaje indicando tal situacin y la sentencia no se ejecuta.
Por ejemplo, si definimos un campo de tipo varchar(10) e intentamos asignarle la
cadena 'Buenas tardes', aparece un mensaje de error y la sentencia no se ejecuta.
integer: se usa para guardar valores numricos enteros, de -2000000000 a
2000000000 aprox. Definimos campos de este tipo cuando queremos representar,
por ejemplo, cantidades.
float: se usa para almacenar valores numricos con decimales. Se utiliza como
separador el punto (.). Definimos campos de este tipo para precios, por ejemplo.
Antes de crear una tabla debemos pensar en sus campos y optar por el tipo de dato
adecuado para cada uno de ellos.
Por ejemplo, si en un campo almacenaremos nmeros enteros, el tipo "float" sera una mala
eleccin; si vamos a guardar precios, el tipo "float" es ms adecuado, no as "integer" que
no tiene decimales. Otro ejemplo, si en un campo vamos a guardar un nmero telefnico o
un nmero de documento, usamos "varchar", no "integer" porque si bien son dgitos, con
ellos no realizamos operaciones matemticas.
La lista de campos luego del "select" selecciona los datos correspondientes a los campos
nombrados. En el ejemplo anterior seleccionamos los campos "titulo" y "autor" de la tabla
"libros", mostrando todos los registros. Los datos aparecen ordenados segn la lista de
seleccin, en dicha lista los nombres de los campos se separan con comas.
where CONDICION;
Para las condiciones se utilizan operadores relacionales (tema que trataremos ms adelante
en detalle). El signo igual(=) es un operador relacional.
Para la siguiente seleccin de registros especificamos una condicin que solicita los
usuarios cuya clave es igual a "River":
select nombre,clave
from usuarios
where clave='River';
7 - Operadores relacionales
Los operadores son smbolos que permiten realizar operaciones matemticas, concatenar
cadenas, hacer comparaciones.
SQL Server tiene 4 tipos de operadores:
1.
2.
3.
4.
relacionales (o de comparacin)
aritmticos
de concatenacin
lgicos.
=
<>
>
<
>=
<=
igual
distinto
mayor
menor
mayor o igual
menor o igual
Podemos seleccionar los registros cuyo autor sea diferente de "Borges", para ello usamos la
condicin:
select * from libros
where autor<>'Borges';
Podemos comparar valores numricos. Por ejemplo, queremos mostrar los ttulos y precios
de los libros cuyo precio sea mayor a 20 pesos:
select titulo, precio
from libros
where precio>20;
Queremos seleccionar los libros cuyo precio sea menor o igual a 30:
select *from libros
where precio<=30;
Los operadores relacionales comparan valores del mismo tipo. Se emplean para comprobar
si un campo cumple con una condicin.
No son los nicos, existen otros que veremos mas adelante.
Si solicitamos el borrado de un registro que no existe, es decir, ningn registro cumple con
la condicin especificada, ningn registro ser eliminado.
Tenga en cuenta que si no colocamos una condicin, se eliminan todos los registros de la
tabla nombrada.
Utilizamos "update" junto al nombre de la tabla y "set" junto con el campo a modificar y su
nuevo valor.
El cambio afectar a todos los registros.
Podemos modificar algunos registros, para ello debemos establecer condiciones de
seleccin con "where".
Por ejemplo, queremos cambiar el valor correspondiente a la clave de nuestro usuario
llamado "Federicolopez", queremos como nueva clave "Boca", necesitamos una condicin
"where" que afecte solamente a este registro:
update usuarios set clave='Boca'
where nombre='Federicolopez';
Si Microsoft SQL Server no encuentra registros que cumplan con la condicin del "where",
no se modifica ninguno.
Las condiciones no son obligatorias, pero si omitimos la clusula "where", la actualizacin
afectar a todos los registros.
Tambin podemos actualizar varios campos en una sola instruccin:
update usuarios set nombre='Marceloduarte', clave='Marce'
where nombre='Marcelo';
Para ello colocamos "update", el nombre de la tabla, "set" junto al nombre del campo y el
nuevo valor y separado por coma, el otro nombre del campo con su nuevo valor.
10 - Comentarios
Para aclarar algunas instrucciones, en ocasiones, necesitamos agregar comentarios.
Es posible ingresar comentarios en la lnea de comandos, es decir, un texto que no se
ejecuta; para ello se emplean dos guiones (--) al comienzo de la lnea:
select * from libros --mostramos los registros de libros;
en la lnea anterior, todo lo que est luego de los guiones (hacia la derecha) no se ejecuta.
Para agregar varias lneas de comentarios, se coloca una barra seguida de un asterisco (/*)
al comienzo del bloque de comentario y al finalizarlo, un asterisco seguido de una barra
(*/).
select titulo, autor
/*mostramos ttulos y
nombres de los autores*/
from libros;
);
Para especificar que un campo no admita valores nulos, debemos colocar "not null" luego
de la definicin del campo.
En el ejemplo anterior, los campos "editorial" y "precio" si admiten valores nulos.
Cuando colocamos "null" estamos diciendo que admite valores nulos (caso del campo
"editorial"); por defecto, es decir, si no lo aclaramos, los campos permiten valores nulos
(caso del campo "precio").
Si ingresamos los datos de un libro, para el cual an no hemos definido el precio podemos
colocar "null" para mostrar que no tiene precio:
insert into libros (titulo,autor,editorial,precio)
values('El aleph','Borges','Emece',null);
Note que el valor "null" no es una cadena de caracteres, no se coloca entre comillas.
Entonces, si un campo acepta valores nulos, podemos ingresar "null" cuando no conocemos
el valor.
Tambin podemos colocar "null" en el campo "editorial" si desconocemos el nombre de la
editorial a la cual pertenece el libro que vamos a ingresar:
insert into libros (titulo,autor,editorial,precio)
values('Alicia en el pais','Lewis Carroll',null,25);
Si intentamos ingresar el valor "null" en campos que no admiten valores nulos (como
"titulo" o "autor"), SQL Server no lo permite, muestra un mensaje y la insercin no se
realiza; por ejemplo:
insert into libros (titulo,autor,editorial,precio)
values(null,'Borges','Siglo XXI',25);
Para ver cules campos admiten valores nulos y cules no, podemos emplear el
procedimiento almacenado "sp_columns" junto al nombre de la tabla. Nos muestra mucha
informacin, en la columna "IS_NULLABLE" vemos que muestra "NO" en los campos que
no permiten valores nulos y "YES" en los campos que si los permiten.
Para recuperar los registros que contengan el valor "null" en algn campo, no podemos
utilizar los operadores relacionales vistos anteriormente: = (igual) y <> (distinto); debemos
utilizar los operadores "is null" (es igual a null) y "is not null" (no es null):
select * from libros
where precio is null;
Con la primera sentencia veremos los libros cuyo precio es igual a "null" (desconocido);
con la segunda, los libros cuyo precio es 0.
Igualmente para campos de tipo cadena, las siguientes sentencias "select" no retornan los
mismos registros:
select * from libros where editorial is null;
select * from libros where editorial='';
Con la primera sentencia veremos los libros cuya editorial es igual a "null", con la segunda,
los libros cuya editorial guarda una cadena vaca.
Entonces, para que un campo no permita valores nulos debemos especificarlo luego de
definir el campo, agregando "not null". Por defecto, los campos permiten valores nulos,
pero podemos especificarlo igualmente agregando "null".
12 - Clave primaria
Una clave primaria es un campo (o varios) que identifica un solo registro (fila) en una tabla.
Para un valor del campo clave existe solamente un registro.
Veamos un ejemplo, si tenemos una tabla con datos de personas, el nmero de documento
puede establecerse como clave primaria, es un valor que no se repite; puede haber personas
con igual apellido y nombre, incluso el mismo domicilio (padre e hijo por ejemplo), pero su
documento ser siempre distinto.
Si tenemos la tabla "usuarios", el nombre de cada usuario puede establecerse como clave
primaria, es un valor que no se repite; puede haber usuarios con igual clave, pero su nombre
de usuario ser siempre diferente.
Podemos establecer que un campo sea clave primaria al momento de crear la tabla o luego
que ha sido creada. Vamos a aprender a establecerla al crear la tabla. Hay 2 maneras de
hacerlo, por ahora veremos la sintaxis ms sencilla.
Tenemos nuestra tabla "usuarios" definida con 2 campos ("nombre" y "clave").
La sintaxis bsica y general es la siguiente:
create table NOMBRETABLA(
CAMPO TIPO,
...
primary key (NOMBRECAMPO)
);
En el siguiente ejemplo definimos una clave primaria, para nuestra tabla "usuarios" para
asegurarnos que cada usuario tendr un nombre diferente y nico:
create table usuarios(
nombre varchar(20),
clave varchar(10),
primary key(nombre)
);
Lo que hacemos agregar luego de la definicin de cada campo, "primary key" y entre
parntesis, el nombre del campo que ser clave primaria.
Una tabla slo puede tener una clave primaria. Cualquier campo (de cualquier tipo) puede
ser clave primaria, debe cumplir como requisito, que sus valores no se repitan ni sean nulos.
Por ello, al definir un campo como clave primaria, automticamente SQL Server lo
convierte a "not null".
Luego de haber establecido un campo como clave primaria, al ingresar los registros, SQL
Server controla que los valores para el campo establecido como clave primaria no estn
repetidos en la tabla; si estuviesen repetidos, muestra un mensaje y la insercin no se
realiza. Es decir, si en nuestra tabla "usuarios" ya existe un usuario con nombre "juanperez"
e intentamos ingresar un nuevo usuario con nombre "juanperez", aparece un mensaje y la
instruccin "insert" no se ejecuta.
Igualmente, si realizamos una actualizacin, SQL Server controla que los valores para el
campo establecido como clave primaria no estn repetidos en la tabla, si lo estuviese,
aparece un mensaje indicando que se viola la clave primaria y la actualizacin no se realiza.
Cuando un campo tiene el atributo "identity" no se puede ingresar valor para l, porque se
inserta automticamente tomando el ltimo valor como referencia, o 1 si es el primero.
Para ingresar registros omitimos el campo definido como "identity", por ejemplo:
insert into libros (titulo,autor,editorial,precio)
values('El aleph','Borges','Emece',23);
El atributo "identity" no implica unicidad, es decir, permite repeticin de valores; por ello
hay que tener cuidado al explicitar un valor porque se puede ingresar un valor repetido.
Para desactivar la opcin "identity_insert" tipeamos:
set identity_insert libros off;
15 - Truncate table
Aprendimos que para borrar todos los registro de una tabla se usa "delete" sin condicin
"where".
Tambin podemos eliminar todos los registros de una tabla con "truncate table".
Por ejemplo, queremos vaciar la tabla "libros", usamos:
truncate table libros;
La sentencia "truncate table" vaca la tabla (elimina todos los registros) y conserva la
estructura de la tabla.
La diferencia con "drop table" es que esta sentencia borra la tabla, "truncate table" la vaca.
La diferencia con "delete" es la velocidad, es ms rpido "truncate table" que "delete" (se
nota cuando la cantidad de registros es muy grande) ya que ste borra los registros uno a
uno.
Otra diferencia es la siguiente: cuando la tabla tiene un campo "identity", si borramos todos
los registros con "delete" y luego ingresamos un registro, al cargarse el valor en el campo
de identidad, contina con la secuencia teniendo en cuenta el valor mayor que se haba
guardado; si usamos "truncate table" para borrar todos los registros, al ingresar otra vez un
registro, la secuencia del campo de identidad vuelve a iniciarse en 1.
Por ejemplo, tenemos la tabla "libros" con el campo "codigo" definido "identity", y el valor
ms alto de ese campo es "2", si borramos todos los registros con "delete" y luego
ingresamos un registro, ste guardar el valor de cdigo "3"; si en cambio, vaciamos la
tabla con "truncate table", al ingresar un nuevo registro el valor del cdigo se iniciar en 1
nuevamente.
0 a 8K
0 a 8K
0 a 2GB
muestra un mensaje indicando que est fuera de rango. Si intentamos ingresar el valor
'12y.25', SQL Server no puede realizar la conversin y muestra un mensaje de error.
Es importante elegir el tipo de dato adecuado segn el caso, el ms preciso. Por ejemplo, si
un campo numrico almacenar valores positivos menores a 255, el tipo "int" no es el ms
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
2 a 17
float
real
4 u 8
4 u 8
money
smallmoney
8
4
Podemos ingresar una fecha, sin hora, en tal caso la hora se guarda como "00:00:00". Por
ejemplo, si ingresamos '25-12-01' (ao de 2 dgitos), lo mostrar as: '2001-12-25
00:00:00.000'.
Podemos ingresar una hora sin fecha, en tal caso, coloca la fecha "1900-01-01". Por
ejemplo, si ingresamos '10:15', mostrar '1900-01-01 10:15.000'.
Podemos emplear los operadores relacionales vistos para comparar fechas.
Tipo
Bytes de almacenamiento
_______________________________________
datetime
8
smalldatetime 4
Tambin es posible ingresar valores para algunos campos. Ingresamos valores solamente
para los campos "titulo" y "autor":
insert into libros (titulo, autor)
values ('El aleph','Borges');
SQL Server almacenar el valor "null" en el campo "editorial", para el cual no hemos
explicitado un valor.
Al ingresar registros debemos tener en cuenta:
- la lista de campos debe coincidir en cantidad y tipo de valores con la lista de valores luego
de "values". Si se listan ms (o menos) campos que los valores ingresados, aparece un
mensaje de error y la sentencia no se ejecuta.
- si ingresamos valores para todos los campos podemos obviar la lista de campos.
- podemos omitir valores para los campos que NO hayan sido declarados "not null", es
decir, que permitan valores nulos (se guardar "null"); si omitimos el valor para un campo
"not null", la sentencia no se ejecuta.
- se DEBE omitir el valor para el campo"identity". Salvo que identity_insert este en on.
- se pueden omitir valores para campos declarados "not null" siempre que tengan definido
un valor por defecto con la clusula "default" (tema que veremos a continuacin).
Si al ingresar un nuevo registro omitimos los valores para el campo "autor" y "cantidad",
Sql Server insertar los valores por defecto; el siguiente valor de la secuencia en "codigo",
en "autor" colocar "Desconocido" y en cantidad "0".
Entonces, si al definir el campo explicitamos un valor mediante la clusula "default", se
ser el valor por defecto.
Ahora, al visualizar la estructura de la tabla con "sp_columns" podemos entender lo que
informa la columna "COLUMN_DEF", muestra el valor por defecto del campo.
Tambin se puede utilizar "default" para dar el valor por defecto a los campos en sentencias
"insert", por ejemplo:
insert into libros (titulo,autor,precio,cantidad)
values ('El gato con botas',default,default,100);
Si todos los campos de una tabla tienen valores predeterminados (ya sea por ser "identity",
permitir valores nulos o tener un valor por defecto), se puede ingresar un registro de la
siguiente manera:
insert into libros default values;
La sentencia anterior almacenar un registro con los valores predetermiandos para cada uno
de sus campos.
Si queremos saber el monto total en dinero de un ttulo podemos multiplicar el precio por la
cantidad por cada ttulo, pero tambin podemos hacer que SQL Server realice el clculo y
lo incluya en una columna extra en la salida:
select titulo, precio,cantidad,
precio*cantidad
from libros;
Si queremos saber el precio de cada libro con un 10% de descuento podemos incluir en la
sentencia los siguientes clculos:
select titulo,precio,
precio-(precio*0.1)
from libros;
Note que concatenamos adems unos guiones para separar los campos.
23 - Alias
Una manera de hacer ms comprensible el resultado de una consulta consiste en cambiar
los encabezados de las columnas.
Por ejemplo, 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 informacin
de dicha tabla aparezca como encabezado del campo "nombre" el texto "nombre y
apellido", para ello colocamos un alias de la siguiente manera:
select nombre as NombreYApellido,
domicilio,telefono
from agenda;
Para reemplazar el nombre de un campo por otro, se coloca la palabra clave "as" seguido
del texto del encabezado.
Si el alias consta de una sola cadena las comillas no son necesarias, pero si contiene ms de
una palabra, es necesario colocarla entre comillas simples:
select nombre as 'Nombre y apellido',
domicilio,telefono
from agenda;
24 - Funciones
Una funcin es un conjunto de sentencias que operan como una unidad lgica.
Una funcin tiene un nombre, retorna un parmetro de salida y opcionalmente acepta
parmetros de entrada. Las funciones de SQL Server no pueden ser modificadas, las
funciones definidas por el usuario si.
SQL Server ofrece varios tipos de funciones para realizar distintas operaciones. Se pueden
clasificar de la siguiente manera:
1) de agregado: realizan operaciones que combinan varios valores y retornan un nico
valor. Son "count", "sum", "min" y "max".
2) escalares: toman un solo valor y retornan un nico valor. Pueden agruparse de la
siguiente manera:
- de configuracin: retornan informacin referida a la configuracin.
Ejemplo:
select @@version;
retorna "tardes".
- str(numero,longitud,cantidaddecimales): convierte nmeros a caracteres; el primer
parmetro indica el valor numrico a convertir, el segundo la longitud del resultado (debe
ser mayor o igual a la parte entera del nmero ms el signo si lo tuviese) y el tercero, la
cantidad de decimales. El segundo y tercer argumento son opcionales y deben ser positivos.
String significa cadena en ingls.
Ejemplo: se convierte el valor numrico "123.456" a cadena, especificando 7 de longitud y
3 decimales:
select str(123.456,7,3);
select str(-123.456,7,3);
retorna '-123.46';
Si no se colocan el segundo y tercer argumeno, la longitud predeterminada es 10 y la
cantidad de decimales 0 y se redondea a entero. Ejemplo: se convierte el valor numrico
"123.456" a cadena:
select str(123.456);
retorna '123';
select str(123.456,3);
retorna '123';
Si el segundo parmetro es menor a la parte entera del nmero, devuelve asteriscos (*).
Ejemplo: select str(123.456,2,3);
retorna "**".
- stuff(cadena1,inicio,cantidad,cadena2): inserta la cadena enviada como cuarto argumento,
en la posicin indicada en el segundo argumento, reemplazando la cantidad de caracteres
indicada por el tercer argumento en la cadena que es primer parmetro. Stuff significa
rellenar en ingls. Ejemplo:
select stuff('abcde',3,2,'opqrs');
devuelve 4.
- char(x): retorna un caracter en cdigo ASCII del entero enviado como argumento.
Ejemplo:
select char(65);
retorna "A".
- left(cadena,longitud): retorna la cantidad (longitud) de caracteres de la cadena
comenzando desde la izquierda, primer caracter. Ejemplo:
select left('buenos dias',8);
Hola
');
Hola
');
retorna "www.sqlserverya.com'.
- reverse(cadena): devuelve la cadena invirtiendo el order de los caracteres. Ejemplo:
select reverse('Hola');
retorna "aloH".
- patindex(patron,cadena): devuelve la posicin de comienzo (de la primera ocurrencia) del
patrn especificado en la cadena enviada como segundo argumento. Si no la encuentra
retorna 0. Ejemplos:
select patindex('%Luis%', 'Jorge Luis Borges');
retorna 7.
select patindex('%or%', 'Jorge Luis Borges');
retorna 2.
select patindex('%ar%', 'Jorge Luis Borges');
retorna 0.
- charindex(subcadena,cadena,inicio): devuelve la posicin donde comienza la subcadena
en la cadena, comenzando la bsqueda desde la posicin indicada por "inicio". Si el tercer
argumento no se coloca, la bsqueda se inicia desde 0. Si no la encuentra, retorna 0.
Ejemplos:
select charindex('or','Jorge Luis Borges',5);
retorna 13.
select charindex('or','Jorge Luis Borges');
retorna 2.
select charindex('or','Jorge Luis Borges',14);
retorna 0.
select charindex('or', 'Jorge Luis Borges');
retorna 0.
- replicate(cadena,cantidad): repite una cadena la cantidad de veces especificada. Ejemplo:
retorna "HolaHolaHola";
- space(cantidad): retorna una cadena de espacios de longitud indicada por "cantidad", que
debe ser un valor positivo. Ejemplo:
select 'Hola'+space(1)+'que tal';
26 - Funciones matemticas
Las funciones matemticas realizan operaciones con expresiones numricas y retornan un
resultado, operan con tipos de datos numricos.
Microsoft SQL Server tiene algunas funciones para trabajar con nmeros. Aqu
presentamos algunas.
-abs(x): retorna el valor absoluto del argumento "x". Ejemplo:
select abs(-20);
retorna 20.
-ceiling(x): redondea hacia arriba el argumento "x". Ejemplo:
select ceiling(12.34);
retorna 13.
-floor(x): redondea hacia abajo el argumento "x". Ejemplo:
select floor(12.34);
retorna 12.
- %: %: devuelve el resto de una divisin. Ejemplos:
select 10%3;
retorna 1.
select 10%2;
retorna 0.
-power(x,y): retorna el valor de "x" elevado a la "y" potencia. Ejemplo:
select power(2,3);
retorna 8.
-round(numero,longitud): retorna un nmero redondeado a la longitud especificada.
"longitud" debe ser tinyint, smallint o int. Si "longitud" es positivo, el nmero de decimales
es redondeado segn "longitud"; si es negativo, el nmero es redondeado desde la parte
entera segn el valor de "longitud". Ejemplos:
select round(123.456,1);
retorna "120.000", es decir, redondea desde el primer valor entero (hacia la izquierda).
select round(123.456,-2);
retorna "100.000", es decir, redondea desde el segundo valor entero (hacia la izquierda).
-sign(x): si el argumento es un valor positivo devuelve 1;-1 si es negativo y si es 0, 0.
-square(x): retorna el cuadrado del argumento. Ejemplo:
select square(3); retorna 9.
retorna el da actual;
select datepart(hour,getdate());
month (mes), day (dia), week (semana), hour (hora), minute (minuto), second (segundo) y
millisecond (milisegundo). Ejemplos:
select dateadd(day,3,'1980/11/02');
retorna 13 (meses).
- day(fecha): retorna el da de la fecha especificada. Ejemplo:
select day(getdate());
Por ejemplo, recuperamos los registros de la tabla "libros" ordenados por el ttulo:
select *from libros
order by titulo;
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;
Tambin 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 seleccin.
Se permite ordenar por valores calculados o expresiones.
La clusula "order by" no puede emplearse para campos text, ntext e image.
Los registros recuperados en una sentencia que une 2 condiciones con el operador "and",
cumplen con las 2 condiciones.
Queremos ver los libros cuyo autor sea "Borges" y/o cuya editorial sea "Planeta":
select *from libros
where autor='Borges' or
editorial='Planeta';
En la sentencia anterior usamos el operador "or"; indicamos que recupere los libros en los
cuales el valor del campo "autor" sea "Borges" y/o el valor del campo "editorial" sea
"Planeta", es decir, seleccionar los registros que cumplan con la primera condicin, con la
segunda condicin o con ambas condiciones.
Los registros recuperados con una sentencia que une 2 condiciones con el operador "or",
cumplen 1 de las condiciones o ambas.
Queremos recuperar los libros que NO cumplan la condicin dada, por ejemplo, aquellos
cuya editorial NO sea "Planeta":
select *from libros
where not editorial='Planeta';
Si bien los parntesis no son obligatorios en todos los casos, se recomienda utilizarlos para
evitar confusiones.
El orden de prioridad de los operadores lgicos es el siguiente: "not" se aplica antes que
"and" y "and" antes que "or", si no se especifica un orden de evaluacin mediante el uso de
parntesis.
El orden en el que se evalan los operadores con igual nivel de precedencia es indefinido,
por ello se recomienda usar los parntesis.
Entonces, para establecer ms de una condicin en un "where" es necesario emplear
operadores lgicos. "and" significa "y", indica que se cumplan ambas condiciones; "or"
significa "y/o", indica que se cumpla una u otra condicin (o ambas); "not" significa "no",
indica que no se cumpla la condicin especificada.
Para obtener los registros que no contiene "null", se puede emplear "is not null", esto
mostrar los registros con valores conocidos.
Siempre que sea posible, emplee condiciones de bsqueda positivas ("is null"), evite las
negativas ("is not null") porque con ellas se evalan todos los registros y esto hace ms
lenta la recuperacin de los datos.
Averiguamos si el valor de un campo dado (precio) est entre los valores mnimo y mximo
especificados (20 y 40 respectivamente).
"between" significa "entre". Trabaja con intervalo de valores.
Este operador se puede emplear con tipos de datos numricos y money (en tales casos
incluyen los valores mnimo y mximo) y tipos de datos fecha y hora (incluye slo el valor
mnimo).
No tiene en cuenta los valores "null".
Si agregamos el operador "not" antes de "between" el resultado se invierte, es decir, se
recuperan los registros que estn fuera del intervalo especificado. Por ejemplo,
recuperamos los libros cuyo precio NO se encuentre entre 20 y 35, es decir, los menores a
15 y mayores a 25:
select *from libros
where precio not between 20 and 35;
Siempre que sea posible, emplee condiciones de bsqueda positivas ("between"), evite las
negativas ("not between") porque hace ms lenta la recuperacin de los datos.
Entonces, se puede usar el operador "between" para reducir las condiciones "where".
Para recuperar los libros cuyo autor no sea 'Paenza' ni 'Borges' usbamos:
select *from libros
where autor<>'Borges' and
autor<>'Paenza';
Empleando "in" averiguamos si el valor del campo est incluido en la lista de valores
especificada; con "not" antecediendo la condicin, invertimos el resultado, es decir,
recuperamos los valores que no se encuentran (coindicen) con la lista de valores.
Los valores "null" no se consideran.
Recuerde: siempre que sea posible, emplee condiciones de bsqueda positivas ("in"), evite
las negativas ("not in") porque con ellas se evaln todos los registros y esto hace ms lenta
la recuperacin de los datos.
El operador igual ("=") nos permite comparar cadenas de caracteres, pero al realizar la
comparacin, busca coincidencias de cadenas completas, realiza una bsqueda exacta.
Imaginemos que tenemos registrados estos 2 libros:
"El Aleph", "Borges";
"Antologia poetica", "J.L. Borges";
slo aparecer el primer registro, ya que la cadena "Borges" no es igual a la cadena "J.L.
Borges".
Esto sucede porque el operador "=" (igual), tambin el operador "<>" (distinto) comparan
cadenas de caracteres completas. Para comparar porciones de cadenas utilizamos los
operadores "like" y "not like".
Entonces, podemos comparar trozos de cadenas de caracteres para realizar consultas. Para
recuperar todos los registros cuyo autor contenga la cadena "Borges" debemos tipear:
select *from libros
where autor like "%Borges%";
Note que el smbolo "%" ya no est al comienzo, con esto indicamos que el ttulo debe
tener como primera letra la "M" y luego, cualquier cantidad de caracteres.
Para seleccionar todos los libros que NO comiencen con "M":
select *from libros
where titulo not like 'M%';
As como "%" reemplaza cualquier cantidad de caracteres, el guin bajo "_" reemplaza un
caracter, es otro caracter comodn. Por ejemplo, queremos ver los libros de "Lewis Carroll"
pero no recordamos si se escribe "Carroll" o "Carrolt", entonces tipeamos esta condicin:
select *from libros
where autor like "%Carrol_";
Ejemplos:
...
...
...
...
like
like
like
like
"like" se emplea con tipos de datos char, nchar, varchar, nvarchar o datetime. Si empleamos
"like" con tipos de datos que no son caracteres, SQL Server convierte (si es posible) el tipo
de dato a caracter. Por ejemplo, queremos buscar todos los libros cuyo precio se encuentre
entre 10.00 y 19.99:
select titulo,precio from libros
where precio like '1_.%';
Para bsquedas de caracteres comodines como literales, debe incluirlo dentro de corchetes,
por ejemplo, si busca:
Imaginemos que nuestra tabla "libros" contiene muchos registros. Para averiguar la
cantidad sin necesidad de contarlos manualmente usamos la funcin "count()":
select count(*)
from libros;
La funcin "count()" cuenta la cantidad de registros de una tabla, incluyendo los que tienen
valor nulo.
Tambin podemos utilizar esta funcin junto con la clusula "where" para una consulta ms
especfica. Queremos saber la cantidad de libros de la editorial "Planeta":
select count(*)
from libros
where editorial='Planeta';
Para contar los registros que tienen precio (sin tener en cuenta los que tienen valor nulo),
usamos la funcin "count()" y en los parntesis colocamos el nombre del campo que
necesitamos contar:
select count(precio)
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. No es lo mismo. "count(*)" cuenta registros, si en lugar de un
asterisco colocamos como argumento el nombre de un campo, se contabilizan los registros
cuyo valor en ese campo NO es nulo.
Note que incluye todos los libros aunque tengan valor nulo en algn campo.
Contamos los libros de editorial "Planeta":
select count_big(*)
from libros
where editorial='Planeta';
Contamos los registros que tienen precio (sin tener en cuenta los que tienen valor nulo):
select count_big(precio)
from libros;
Las relaciones entre las funciones de agrupamiento y los tipos de datos es la siguiente:
- count: se puede emplear con cualquier tipo de dato.
- min y max: con cualquier tipo de dato.
- sum y avg: slo en campos de tipo numrico.
La funcin "sum()" retorna la suma de los valores que contiene el campo especificado. Si
queremos saber la cantidad total de libros que tenemos disponibles para la venta, debemos
sumar todos los valores del campo "cantidad":
select sum(cantidad)
from libros;
Para averiguar el valor mximo o mnimo de un campo usamos las funciones "max()" y
"min()" respectivamente.
Queremos saber cul es el mayor precio de todos los libros:
select max(precio)
from libros;
Entonces, dentro del parntesis de la funcin colocamos el nombre del campo del cul
queremos el mximo valor.
La funcin "avg()" retorna el valor promedio de los valores del campo especificado.
Queremos saber el promedio del precio de los libros referentes a "PHP":
select avg(precio)
from libros
where titulo like '%PHP%';
Tambin se puede agrupar por ms de un campo, en tal caso, luego del "group by" se listan
los campos, separados por comas. Todos los campos que se especifican en la clusula
"group by" deben estar en la lista de seleccin.
select CAMPO1, CAMPO2, FUNCIONDEAGREGADO
from NOMBRETABLA
group by CAMPO1,CAMPO2;
Para obtener la cantidad libros con precio no nulo, de cada editorial utilizamos la funcin
"count()" envindole como argumento el campo "precio", agregamos "group by" y el
campo por el que deseamos que se realice el agrupamiento (editorial):
select editorial, count(precio)
from libros
group by editorial;
Como resultado aparecen los nombres de las editoriales y la cantidad de registros de cada
una, sin contar los que tienen precio nulo.
Recuerde la diferencia de los valores que retorna la funcin "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, en el segundo, los registros en los cuales el
campo especificado es no nulo.
Para conocer el total en dinero de los libros agrupados por editorial:
select editorial, sum(precio)
from libros
group by editorial;
Para saber el mximo y mnimo valor de los libros agrupados por editorial:
select editorial,
max(precio) as mayor,
min(precio) as menor
from libros
group by editorial;
Para calcular el promedio del valor de los libros agrupados por editorial:
select editorial, avg(precio)
from libros
group by editorial;
Note que las editoriales que no tienen libros que cumplan la condicin, no aparecen en la
salida. Para que aparezcan todos los valores de editorial, incluso los que devuelven cero o
"null" en la columna de agregado, debemos emplear la palabra clave "all" al lado de "group
by":
select editorial, count(*)
from libros
where precio<30
group by all editorial;
Entonces, usamos "group by" para organizar registros en grupos y obtener un resumen de
dichos grupos. SQL Server produce una columna de valores por cada grupo, devolviendo
filas por cada grupo especificado.
Si queremos saber la cantidad de libros agrupados por editorial pero considerando slo
algunos grupos, por ejemplo, los que devuelvan un valor mayor a 2, usamos la siguiente
instruccin:
select editorial, count(*) from libros
group by editorial
having count(*)>2;
En algunos casos es posible confundir las clusulas "where" y "having". Queremos contar
los registros agrupados por editorial sin tener en cuenta a la editorial "Planeta".
Analicemos las siguientes sentencias:
select editorial, count(*) from libros
where editorial<>'Planeta'
group by editorial;
select editorial, count(*) from libros
group by editorial
having editorial<>'Planeta';
Ambas devuelven el mismo resultado, pero son diferentes. La primera, selecciona todos los
registros rechazando los de editorial "Planeta" y luego los agrupa para contarlos. La
segunda, selecciona todos los registros, los agrupa para contarlos y finalmente rechaza fila
con la cuenta correspondiente a la editorial "Planeta".
No debemos confundir la clusula "where" con la clusula "having"; la primera establece
condiciones para la seleccin de registros de un "select"; la segunda establece condiciones
para la seleccin de registros de una salida "group by".
Veamos otros ejemplos combinando "where" y "having". Queremos la cantidad de libros,
sin considerar los que tienen precio nulo, agrupados por editorial, sin considerar la editorial
"Planeta":
select editorial, count(*) from libros
where precio is not null
group by editorial
having editorial<>'Planeta';
Aqu, selecciona los registros rechazando los que no cumplan con la condicin dada en
"where", luego los agrupa por "editorial" y finalmente rechaza los grupos que no cumplan
con la condicin dada en el "having".
Se emplea la clusula "having" con funciones de agrupamiento, esto no puede hacerlo la
clusula "where". Por ejemplo queremos el promedio de los precios agrupados por
editorial, de aquellas editoriales que tienen ms de 2 libros:
select editorial, avg(precio) from libros
group by editorial
having count(*) > 2;
En una clusula "having" puede haber hasta 128 condiciones. Cuando utilice varias
condiciones, tiene que combinarlas con operadores lgicos (and, or, not).
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, max(precio) as 'mayor'
from libros
group by editorial
having min(precio)<100 and
min(precio)>30
order by editorial;
Entonces, usamos la clasula "having" para restringir las filas que devuelve una salida
"group by". Va siempre despus de la clusula "group by" y antes de la clusula "order by"
si la hubiere.
Esta consulta muestra el total de visitantes agrupados por ciudad; pero si queremos adems
la cantidad total de visitantes, debemos realizar otra consulta:
select count(*) as total
from visitantes;
Para obtener ambos resultados en una sola consulta podemos usar "with rollup" que nos
devolver ambas salidas en una sola consulta:
select ciudad,count(*) as cantidad
from visitantes
group by ciudad with rollup;
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.
La clusula "group by" permite agregar el modificador "with rollup", el cual agrega
registros extras al resultado de una consulta, que muestran operaciones de resumen.
Si agrupamos por 2 campos, "ciudad" y "sexo":
select ciudad,sexo,count(*) as cantidad
from visitantes
group by ciudad,sexo
with rollup;
La salida muestra los totales por ciudad y sexo y produce tantas filas extras como valores
existen del primer campo por el que se agrupa ("ciudad" en este caso), mostrando los
totales para cada valor, con la columna correspondiente al segundo campo por el que se
agrupa ("sexo" en este ejemplo) conteniendo "null", y 1 fila extra mostrando el total de
todos los visitantes (con las columnas correspondientes a ambos campos conteniendo
"null"). Es decir, por cada agrupacin, aparece una fila extra con el/ los campos que no se
consideran, seteados a "null".
Con "rollup" se puede agrupar hasta por 10 campos.
Es posible incluir varias funciones de agrupamiento, por ejemplo, queremos la cantidad de
visitantes y la suma de sus compras agrupados por ciudad y sexo:
select ciudad,sexo,
count(*) as cantidad,
sum(montocompra) as total
from visitantes
group by ciudad,sexo
with rollup;
Entonces, "rollup" es un modificador para "group by" que agrega filas extras mostrando
resultados de resumen de los subgrupos. 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".
Con "rollup" se puede emplear "where" y "having", pero no es compatible con "all".
SQL Server genera varias filas extras con informacin de resumen para los siguientes
subgrupos:
- sexo y estadocivil (seccion seteado a "null"),
- sexo (estadocivil y seccion seteados a "null") y
- total (todos los campos seteados a "null").
Si se emplea "cube":
select sexo,estadocivil,seccion,
count(*) from empleados
group by sexo,estadocivil,seccion
with cube;
seteado a "null"),
seteado a "null"),
seteados a "null") y
seteados a "null"),
Es decir, "cube" genera filas de resumen de subgrupos para todas las combinaciones
posibles de los valores de los campos por los que agrupamos.
Se pueden colocar hasta 10 campos en el "group by".
Con "cube" se puede emplear "where" y "having", pero no es compatible con "all".
41 - Funcin grouping
La funcin "grouping" se emplea con los operadores "rollup" y "cube" para distinguir los
valores de detalle y de resumen en el resultado. Es decir, 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".
Con esta funcin aparece una nueva columna en la salida, una por cada "grouping"; 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.
Slo se puede emplear la funcin "grouping" en los campos que aparecen en la clusula
"group by".
Si tenemos una tabla "visitantes" con los siguientes registros almacenados:
Nombre
sexo
ciudad
------------------------------Susana Molina f
Cordoba
Marcela Mercado f
Cordoba
Roberto Perez f
null
Alberto Garcia m
Cordoba
Teresa Garcia f
Alta Gracia
y contamos la cantidad agrupando por ciudad (note que hay un valor nulo en dicho campo)
empleando "rollup":
select ciudad,
count(*) as cantidad
from visitantes
group by ciudad
with rollup;
La ltima fila contiene en la columna generada por "grouping" el valor 1, indicando que es
la fila de resumen generada por "rollup"; la primera fila, contiene en dicha columna el valor
0, que indica que el valor "null" es un valor del campo "ciudad".
Entonces, si emplea los operadores "rollup" y "cube" y los campos por los cuales agrupa
admiten valores nulos, utilice la funcin "grouping" para distinguir los valores de detalle y
de resumen en el resultado.
El campo que se coloque en la clusula "compute" debe estar incluida en la lista de campos
del "select".
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);
"Compute by" genera cortes de control y subtotales. Se generan filas de detalle y varios
valores de resumen cuando cambian los valores del campo.
Con "compute by" se DEBE usar tambin la clusula "order by" y los campos que se
incluyan luego de "by" deben estar en el "order by". Listando varios campos luego del "by"
corta un grupo en subgrupos y aplica la funcin de agregado en cada nivel de
agrupamiento:
select nombre,ciudad,provincia
from visitantes
order by provincia
compute count(provincia)
by provincia;
select nombre,ciudad,provincia
from visitantes
order by provincia,ciudad
compute count(provincia)
by provincia,ciudad;
Los campos que aparecen luego de la clusula "compute by" DEBEN ser idnticos a un
subconjunto de los campos que aparecen despus de "order by" y estar en el mismo orden.
Si la clusula "order by" tiene los siguientes campos:
... order by a,b,c...
En una misma instruccin se pueden colocar varias clusulas "compute" combinadas con
varias clusulas "compute by":
select *from visitantes
order by provincia,ciudad
compute avg(edad), sum(montocompra)
compute avg(montocompra),count(provincia)
by provincia,ciudad;
Note que en los tres casos anteriores aparece "null" como un valor para "autor" Si slo
queremos la lista de autores conocidos, es decir, no queremos incluir "null" en la lista,
podemos utilizar la sentencia siguiente:
select distinct autor from libros
where autor is not null;
Para contar los distintos autores, sin considerar el valor "null" usamos:
select count(distinct autor)
from libros;
Note que si contamos los autores sin "distinct", no incluir los valores "null" pero si los
repetidos:
select count(autor)
from libros;
Tambin puede utilizarse con "group by" para contar los diferentes autores por editorial:
select editorial, count(distinct autor)
from libros
group by editorial;
La clusula "distinct" afecta a todos los campos presentados. Para mostrar los ttulos y
editoriales de los libros sin repetir ttulos ni editoriales, usamos:
select distinct titulo,editorial
from libros
order by titulo;
Note que los registros no estn duplicados, aparecen ttulos iguales pero con editorial
diferente, cada registro es diferente.
La palabra clave "distinct" no est permitida con las clusulas "compute" y "compute by".
Entonces, "distinct" elimina registros duplicados.
44 - Clusula top
La palabra clave "top" se emplea para obtener slo una cantidad limitada de registros, los
primeros n registros de una consulta.
Con la siguiente consulta obtenemos todos los datos de los primeros 2 libros de la tabla:
select top 2 *from libros;
Es decir, luego del "select" se coloca "top" seguido de un nmero entero positivo y luego se
contina con la consulta.
Se puede combinar con "order by":
select top 3 titulo,autor
from libros
order by autor;
En la consulta anterior solicitamos los ttulos y autores de los 3 primeros libros, ordenados
por autor.
Cuando se combina con "order by" es posible emplear tambin la clusula "with ties". Esta
clusula permite incluir en la seleccion, todos los registros que tengan el mismo valor del
campo por el que se ordena, que el ltimo registro retornado si el ltimo registro retornado
(es decir, el nmero n) tiene un valor repetido en el registro n+1. Es decir, si el valor del
campo por el cual se ordena del ltimo registro retornado (el nmero n) est repetido en los
siguientes registros (es decir, el n+1 tiene el mismo valor que n, y el n+2, etc.), lo incluye
en la seleccin.
Veamos un ejemplo:
select top 3 with ties
*from libros
order by autor;
Esta consulta solicita el retorno de los primeros 3 registros; en caso que el registro nmero
4 (y los posteriores), tengan el mismo valor en "autor" que el ltimo registro retornado
(nmero 3), tambin aparecern en la seleccin.
Si colocamos un valor para "top" que supera la cantidad de registros de la tabla, SQL
Server muestra todos los registros.
Necesitamos definir una clave primaria para una tabla con los datos descriptos arriba. No
podemos usar solamente la patente porque un mismo auto puede ingresar ms de una vez
en el da a la playa; tampoco podemos usar la hora de entrada porque varios autos pueden
ingresar a una misma hora.
Tampoco sirven los otros campos.
Como ningn campo, por si slo cumple con la condicin para ser clave, es decir, debe
identificar un solo registro, el valor no puede repetirse, debemos usar 2 campos.
Definimos una clave compuesta cuando ningn campo por si solo cumple con la condicin
para ser clave.
En este ejemplo, un auto puede ingresar varias veces en un da a la playa, pero siempre ser
a distinta hora.
Usamos 2 campos como clave, la patente junto con la hora de llegada, as identificamos
unvocamente cada registro.
Nombramos los campos que formarn parte de la clave separados por comas.
Al ingresar los registros, SQL Server controla que los valores para los campos establecidos
como clave primaria no estn repetidos en la tabla; si estuviesen repetidos, muestra un
mensaje y la insercin no se realiza. Lo mismo sucede si realizamos una actualizacin.
Entonces, si un solo campo no identifica unvocamente un registro podemos definir una
clave primaria compuesta, es decir formada por ms de un campo.
Cuando se agrega una restriccin a una tabla, SQL Server comprueba los datos existentes.
Hay varios tipos de restricciones.
47 - Restriccin default
La restriccin "default" especifica un valor por defecto para un campo cuando no se inserta
explcitamente en un comando "insert".
Anteriormente, para establecer un valor por defecto para un campo emplebamos la
clusula "default" al crear la tabla, por ejemplo:
create table libros(
...
autor varchar(30) default 'Desconocido',
...
);
Cada vez que establecamos un valor por defecto para un campo de una tabla, SQL Server
creaba automticamente una restriccin "default" para ese campo de esa tabla.
Dicha restriccin, a la cual no le dbamos un nombre, reciba un nombre dado por SQL
Server que consiste "DF" (por default), seguido del nombre de la tabla, el nombre del
campo y letras y nmeros aleatorios.
Podemos agregar una restriccin "default" a una tabla existente con la sintaxis bsica
siguiente:
alter table NOMBRETABLA
add constraint NOMBRECONSTRAINT
default VALORPORDEFECTO
for CAMPO;
Entonces, la restriccin "default" especifica un valor por defecto para un campo cuando no
se inserta explcitamente en un "insert", se puede establecer uno por campo y no se puede
emplear junto con la propiedad "identity".
48 - Restriccin check
La restriccin "check" especifica los valores que acepta un campo, evitando que se ingresen
valores inapropiados.
La sintaxis bsica es la siguiente:
alter table NOMBRETABLA
add constraint NOMBRECONSTRAINT
check CONDICION;
Trabajamos con la tabla "libros" de una librera que tiene los siguientes campos: codigo,
titulo, autor, editorial, preciomin (que indica el precio para los minoristas) y preciomay
(que indica el precio para los mayoristas).
Los campos correspondientes a los precios (minorista y mayorista) se definen de tipo
decimal(5,2), es decir, aceptan valores entre -999.99 y 999.99. Podemos controlar que no se
ingresen valores negativos para dichos campos agregando una restriccin "check":
alter table libros
add constraint CK_libros_precio_positivo
check (preciomin>=0 and preciomay>=0);
Este tipo de restriccin verifica los datos cada vez que se ejecuta una sentencia "insert" o
"update", es decir, acta en inserciones y actualizaciones.
Si la tabla contiene registros que no cumplen con la restriccin que se va a establecer, la
restriccin no se puede establecer, hasta que todos los registros cumplan con dicha
restriccin.
La condicin puede hacer referencia a otros campos de la misma tabla. Por ejemplo,
podemos controlar que el precio mayorista no sea mayor al precio minorista:
alter table libros
add constraint CK_libros_preciominmay
check (preciomay<=preciomin);
Por convencin, cuando demos el nombre a las restricciones "check" seguiremos la misma
estructura: comenzamos con "CK", seguido del nombre de la tabla, del campo y alguna
palabra con la cual podamos identificar fcilmente de qu se trata la restriccin, por si
tenemos varias restricciones "check" para el mismo campo.
Un campo puede tener varias restricciones restricciones "check" y una restriccin "check"
puede incluir varios campos.
Las condiciones para restricciones "check" tambin pueden pueden incluir un patrn o una
lista de valores. Por ejemplo establecer que cierto campo conste de 4 caracteres, 2 letras y 2
dgitos:
...
check (CAMPO like '[A-Z][A-Z][0-9][0-9]');
O establecer que cierto campo asuma slo los valores que se listan:
...
check (CAMPO in ('lunes','miercoles','viernes'));
Sabemos que si agregamos una restriccin a una tabla que contiene datos, SQL Server los
controla para asegurarse que cumplen con la condicin de la restriccin, si algn registro no
la cumple, la restriccin no se establecece.
Es posible deshabilitar esta comprobacin en caso de restricciones "check".
Podemos hacerlo cuando agregamos la restriccin "check" a una tabla para que SQL Server
acepte los valores ya almacenados que infringen la restriccin. Para ello debemos incluir la
opcin "with nocheck" en la instruccin "alter table":
alter table libros
with nocheck
add constraint CK_libros_precio
check (precio>=0);
Si se emplea "check constraint all" no se coloca nombre de restricciones, habilita todas las
restricciones que tiene la tabla nombrada.
Para habilitar o deshabilitar restricciones la comprobacin de datos en inserciones o
actualizaciones, la sintaxis bsica es:
alter table NOMBRETABLA
OPCIONdeRESTRICCION constraint NOMBRERESTRICCION;
Para saber si una restriccin est habilitada o no, podemos ejecutar el procedimiento
almacenado "sp_helpconstraint" y fijarnos lo que informa la columna "status_enabled".
Entonces, las clusulas "check" y "nocheck" permiten habilitar o deshabilitar restricciones
"check" (tambin las restricciones "foreign key" que veremos ms adelante), a las dems se
las debe eliminar ("default" y las que veremos posteriormente).
Cada vez que establecamos la clave primaria para la tabla, SQL Server creaba
automticamente una restriccin "primary key" para dicha tabla. Dicha restriccin, a la cual
no le dbamos un nombre, reciba un nombre dado por SQL Server que comienza con "PK"
(por primary key), seguido del nombre de la tabla y una serie de letras y nmeros
aleatorios.
Podemos agregar una restriccin "primary key" a una tabla existente con la sintaxis bsica
siguiente:
alter table NOMBRETABLA
add constraint NOMBRECONSTRAINT
primary key (CAMPO,...);
En el siguiente ejemplo definimos una restriccin "primary key" para nuestra tabla "libros"
para asegurarnos que cada libro tendr un cdigo diferente y nico:
alter table libros
add constraint PK_libros_codigo
primary key(codigo);
Con esta restriccin, si intentamos ingresar un registro con un valor para el campo "codigo"
que ya existe o el valor "null", aparece un mensaje de error, porque no se permiten valores
duplicados ni nulos. Igualmente, si actualizamos.
Por convencin, cuando demos el nombre a las restricciones "primary key" seguiremos el
formato "PK_NOMBRETABLA_NOMBRECAMPO".
Sabemos que cuando agregamos una restriccin a una tabla que contiene informacin, SQL
Server controla los datos existentes para confirmar que cumplen las exigencias de la
restriccin, si no los cumple, la restriccin no se aplica y aparece un mensaje de error. Por
ejemplo, si intentamos definir la restriccin "primary key" para "libros" y hay registros con
cdigos repetidos o con un valor "null", la restriccin no se establece.
Cuando establecamos una clave primaria al definir la tabla, automticamente SQL Server
redefina el campo como "not null"; pero al agregar una restriccin "primary key", los
campos que son clave primaria DEBEN haber sido definidos "not null" (o ser
implcitamente "not null" si se definen identity).
SQL Server permite definir solamente una restriccin "primary key" por tabla, que asegura
la unicidad de cada registro de una tabla.
Si ejecutamos el procedimiento almacenado "sp_helpconstraint" junto al nombre de la
tabla, podemos ver las restricciones "primary key" (y todos los tipos de restricciones) de
dicha tabla.
Un campo con una restriccin "primary key" puede tener una restriccin "check".
Un campo "primary key" tambin acepta una restriccin "default" (excepto si es identity),
pero no tiene sentido ya que el valor por defecto solamente podr ingresarse una vez; si
intenta ingresarse cuando otro registro ya lo tiene almacenado, aparecer un mensaje de
error indicando que se intenta duplicar la clave.
51 - Restriccin unique
Hemos visto que las restricciones aplicadas a tablas aseguran valores nicos para cada
registro.
Anteriormente aprendimos la restriccin "primary key", otra restriccin para las tablas es
"unique".
Ejemplo:
alter table alumnos
add constraint UQ_alumnos_documento
unique (documento);
Pueden eliminarse varias restricciones con una sola instruccin separndolas por comas.
Cuando eliminamos una tabla, todas las restricciones que fueron establecidas en ella, se
eliminan tambin.
Entonces, luego de "create rule" se coloca el nombre de la regla, luego la palabra clave "as"
seguido de una variable (a la cual la precede el signo arroba) y finalmente la condicin.
Por convencin, nombraremos las reglas comenzando con "RG", el nombre del campo al
que se asocia y alguna palabra que haga referencia a la condicin.
La variable puede tener cualquier nombre, pero debe estar precedido por el signo arroba
(@), dicha variable ser reemplazada por el valor del campo cuando se asocie.
La condicin se refiere a los valores permitidos para inserciones y actualizaciones y puede
contener cualquier expresin vlida para una clusula "where"; no puede hacer referencia a
los campos de una tabla.
Creamos una regla para restringir los valores que se pueden ingresar en un campo "sueldo"
de una tabla llamada "empleados", estableciendo un intervalo de valores:
create rule RG_sueldo_intervalo
as @sueldo between 100 and 1000
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, aparece un mensaje de error
indicando que hay conflicto con la regla y la insercin (o actualizacin) no se realiza.
SQL Server NO controla los datos existentes para confirmar que cumplen con la regla
como lo hace al aplicar restricciones; si no los cumple, la regla se asocia igualmente; pero
al ejecutar una instruccin "insert" o "update" muestra un mensaje de error, es decir, acta
en inserciones y actualizaciones.
La regla debe ser compatible con el tipo de datos del campo al cual se asocia; si esto no
sucede, SQL Server no lo informa al crear la regla ni al asociarla, pero al ejecutar una
instruccin "insert" o "update" muestra un mensaje de error.
No se puede crear una regla para campos de tipo text, image, o timestamp.
Si asocia una nueva regla a un campo que ya tiene asociada otra regla, la nueva regla
reeemplaza la asociacin anterior; pero la primera regla no desaparece, solamente se
deshace la asociacin.
La sentencia "create rule" no puede combinarse con otras sentencias en un lote.
La funcin que cumple una regla es bsicamente la misma que una restriccin "check", las
siguientes caractersticas explican algunas diferencias entre ellas:
- podemos definir varias restricciones "check" sobre un campo, un campo solamente puede
tener una regla asociada a l;
- una restriccin "check" se almacena con la tabla, cuando sta se elimina, las restricciones
tambin se borran. Las reglas son objetos diferentes e independientes de las tablas, si
eliminamos una tabla, las asociaciones desaparecen, pero las reglas siguen existiendo en la
base de datos;
- una restriccin "check" puede incluir varios campos; una regla puede asociarse a distintos
campos (incluso de distintas tablas);
- una restriccin "check" puede hacer referencia a otros campos de la misma tabla, una
regla no.
Un campo puede tener reglas asociadas a l y restricciones "check". Si hay conflicto entre
ellas, SQL Server no lo informa al crearlas y/o asociarlas, pero al intentar ingresar un valor
que alguna de ellas no permita, aparece un mensaje de error.
Con "sp_helpconstraint" podemos ver las reglas asociadas a los campos de una tabla.
Con "sp_help" podemos ver todos los objetos de la base de datos activa, incluyendo las
reglas, en tal caso en la columna "Object_type" aparece "rule".
Si eliminamos una tabla, las asociaciones de reglas de sus campos desaparecen, pero las
reglas siguen existiendo.
Tambin se puede consultar la tabla del sistema "sysobjects", que nos muestra el nombre y
varios datos de todos los objetos de la base de datos actual. La columna "xtype" indica el
tipo de objeto, en caso de ser una regla aparece el valor "R":
select *from sysobjects;
Si queremos ver todas las reglas creadas por nosotros, podemos tipear:
select *from sysobjects
where xtype='R' and-- tipo regla
name like 'RG%';--bsqueda con comodn
En el siguiente creamos un valor predeterminado que inserta ceros con el formato vlido
para un nmero de telfono:
create default VP_telefono
as '(0000)0-000000';
Con "sp_helpconstraint" podemos ver los valores predeterminados asociados a los campos
de una tabla.
Con "sp_help" podemos ver todos los objetos de la base de datos activa, incluyendo los
valores predeterminados, en tal caso en la columna "Object_type" aparece "default".
Tambin se puede consultar la tabla del sistema "sysobjects", que nos muestra el nombre y
varios datos de todos los objetos de la base de datos actual. La columna "xtype" indica el
tipo de objeto, en caso de ser un valor predeterminado aparece el valor "D":
select *from sysobjects;
Si queremos ver todos los valores predeterminados creados por nosotros, podemos tipear:
select *from sysobjects
where xtype='D' and-- tipo valor predeterminado
name like 'VP%';--bsqueda con comodn
60 - Indices
SQL Server accede a los datos de dos maneras:
1. recorriendo las tablas; comenzando el principio y extrayendo los registros que
cumplen las condiciones de la consulta.
2. empleando ndices; recorriendo la estructura de rbol del ndice para localizar los
registros y extrayendo los que cumplen las condiciones de la consulta.
Los ndices se emplean para facilitar la obtencin de informacin de una tabla. El indice de
una tabla desempea la misma funcin que el ndice de un libro: permite encontrar datos
rpidamente; en el caso de las tablas, localiza registros.
Una tabla se indexa por un campo (o varios).
Un ndice posibilita el acceso directo y rpido haciendo ms eficiente las bsquedas. Sin
ndice, SQL Server debe recorrer secuencialmente toda la tabla para encontrar un registro.
El objetivo de un indice es acelerar la recuperacin de informacin. La indexacin es una
tcnica que optimiza el acceso a los datos, mejora el rendimiento acelerando las consultas y
otras operaciones. Es til cuando la tabla contiene miles de registros, cuando se realizan
operaciones de ordenamiento y agrupamiento y cuando se combinan varias tablas (tema que
veremos ms adelante).
La desventaja es que consume espacio en el disco en disco y genera costo de
mantenimiento (tiempo y recursos).
Los ndices ms adecuados son aquellos creados con campos que contienen valores nicos.
, mat_ , es.codcar,nomcar,np.nom_nivel_profesional ,np.cod_nivel_profesional from
( select cc.codcar , mat_ from carreras cc left join ( select codcar, sum(.mat_) as mat_ from
( select rut, codcar, estado, cod_tipo_alum, count(rut) as mat_ from ( select rut,
codcar_actual as codcar, codcar as codcar_atingua, especialidad, estado, anoestado ,
modoingreso, anoingreso, cod_tipo_alum from Vista_matricula_ group by rut,
codcar_actual, codcar, especialidad, estado, anoestado , modoingreso, anoingreso,
cod_tipo_alum ) as mat_ where (estado=1 or estado=3 or estado=6) group by rut, codcar,
estado, cod_tipo_alum ) as group by .codcar ) as on .codcar=cc.codcar ) es inner join
carreras car on es.codcar=car.codcar inner join ( select
dca.codcar,dca.cod_nivel_profesional from descripcion_carrera dca where
dca.cod_nivel_global=1 group by dca.codcar,dca.cod_nivel_profesional ) dca on
dca.codcar=es.codcar inner join nivel_profesional np on
np.cod_nivel_profesional=dca.cod_nivel_profesional inner join ( select
fde.codcar,fde.coddep,fde.codfac from fac_dep fde where coddep<>'DEPMAT' group by
codcar,coddep,fde.codfac ) fde on fde.codcar=es.codcar left join ( select ct.cod_carrera as
codcar, ct.cod_centro, cu.nom_centro from ( select cod_carrera, cod_centro from
sid_carrera_total group by cod_carrera, cod_centro ) as ct inner join
sid_centro_universitario cu on ct.cod_centro=cu.cod_centro ) ce on es.codcar=ce.codcar
left join facultades fac on fac.codfac=fde.codfac left join deptos dep on
dep.coddep=fde.coddep where (dca.cod_nivel_profesional=1 or
dca.cod_nivel_profesional=2 or dca.cod_nivel_profesional=3) and ( mat_ is not null) group
by fac.codfac, dep.coddep, fac.nomfac,dep.nomdep, ce.cod_centro, ce.nom_centro , mat_,
es.codcar,car.nomcar,np.nom_nivel_profesional ,np.cod_nivel_profesional order by
fac.codfac, dep.coddep, ce.cod_centro, es.codcar
Es importante identificar el o los campos por los que sera til crear un ndice, aquellos
campos por los cuales se realizan bsqueda con frecuencia: claves primarias, claves
externas o campos que combinan tablas.
No se recomienda crear ndices por campos que no se usan con frecuencia en consultas o no
contienen valores nicos.
SQL Server permite crear dos tipos de ndices: 1) agrupados y 2) no agrupados.
Es recomendable crear los ndices agrupados antes que los no agrupados, porque los
primeros modifican el orden fsico de los registros, ordenndolos secuencialmente.
La diferencia bsica entre ndices agrupados y no agrupados es que los registros de un
ndice agrupado estn ordenados y almacenados de forma secuencial en funcin de su
clave.
SQL Server crea automaticamente ndices cuando se crea una restriccin "primary key" o
"unique" en una tabla.
Es posible crear ndices en las vistas.
Resumiendo, los ndices facilitan la recuperacin de datos, permitiendo el acceso directo y
acelerando las bsquedas, consultas y otras operaciones que optimizan el rendimiento
general.
62 - Creacin de ndices
Para crear ndices empleamos la instruccin "create index".
La sintaxis bsica es la siguiente:
create TIPODEINDICE index NOMBREINDICE
on TABLA(CAMPO);
Para identificar los ndices fcilmente, podemos agregar un prefijo al nombre del ndice,
por ejemplo "I" y luego el nombre de la tabla y/o campo.
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 ms de un campo como clave, son ndices compuestos. Los campos
de un ndice compuesto tienen que ser de la misma tabla (excepto cuando se crea en una
vista - tema que veremos posteriormente).
Creamos un ndice compuesto para el campo "autor" y "editorial":
create index I_libros_autoreditorial
on libros(autor,editorial);
SQL Server crea automticamente ndices cuando se establece una restriccin "primary
key" o "unique" en una tabla. Al crear una restriccin "primary key", si no se especifica, el
ndice ser agrupado (clustered) a menos que ya exista un ndice agrupado para dicha tabla.
Al crear una restriccin "unique", si no se especifica, el ndice ser no agrupado (nonclustered).
Muestra el nombre del ndice, si es agrupado (o no), primary (o unique) y el campo por el
cual se indexa.
Todos los ndices de la base de datos activa se almacenan en la tabla del sistema
"sysindexes", podemos consultar dicha tabla tipeando:
select name from sysindexes;
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_%';
63 - Regenerar ndices
Vimos que para crear ndices empleamos la instruccin "create index".
Empleando la opcin "drop_existing" junto con "create index" permite regenerar un ndice,
con ello evitamos eliminarlo y volver a crearlo. La sintaxis es la siguiente:
create TIPODEINDICE index NOMBREINDICE
on TABLA(CAMPO)
with drop_existing;
Tambin podemos modificar alguna de las caractersticas de un ndice con esta opcin, a
saber:
- tipo: cambindolo de no agrupado a agrupado (siempre que no exista uno agrupado para
la misma tabla). No se puede convertir un ndice agrupado en No agrupado.
- campo: se puede cambiar el campo por el cual se indexa, agregar campos, eliminar algn
campo de un ndice compuesto.
- nico: se puede modificar un ndice para que los valores sean nicos o dejen de serlo.
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);
Esta opcin no puede emplearse con ndices creados a partir de una restriccin "primary
key" o "unique".
64 - Eliminar ndices
Los ndices creados con "create index" se eliminan con "drop index"; la siguiente es la
sintaxis bsica:
drop index NOMBRETABLA.NOMBREINDICE;
Los ndices que SQL Server crea automticamente al establecer una restriccin "primary
key" o "unique" no pueden eliminarse con "drop index", se eliminan automticamente
cuando quitamos la restriccin.
Podemos averiguar si existe un ndice para eliminarlo, consultando la tabla del sistema
"sysindexes":
if exists (select name from sysindexes
where name = 'NOMBREINDICE')
drop index NOMBRETABLA.NOMBREINDICE;
De esta manera, evitamos almacenar tantas veces los nombres de las editoriales en la tabla
"libros" y guardamos el nombre en la tabla "editoriales"; para indicar la editorial de cada
libro agregamos un campo que hace referencia al cdigo de la editorial en la tabla "libros" y
en "editoriales".
Al recuperar los datos de los libros con la siguiente instruccin:
select* from libros;
Ejemplo:
select *from libros
join editoriales
on codigoeditorial=editoriales.codigo;
En algunos casos (como en este ejemplo) el uso de alias es para fines de simplificacin y
hace ms legible la consulta si es larga y compleja, pero en algunas consultas es
absolutamente necesario.
El resultado mostrar el ttulo y nombre de la editorial; las editoriales de las cuales no hay
libros, es decir, cuyo cdigo de editorial no est presente en "libros" aparece en el resultado,
pero con el valor "null" en el campo "titulo".
Es importante la posicin en que se colocan las tablas en un "left join", la tabla de la
izquierda es la que se usa para localizar registros en la tabla de la derecha.
Entonces, un "left join" se usa para hacer coincidir registros en una tabla (izquierda) con
otra tabla (derecha); si un valor de la tabla de la izquierda no encuentra coincidencia en la
tabla de la derecha, se genera una fila extra (una por cada valor no encontrado) con todos
los campos correspondientes a la tabla derecha seteados a "null". La sintaxis bsica es la
siguiente:
select CAMPOS
from TABLAIZQUIERDA
left join TABLADERECHA
on CONDICION;
El resultado mostrar el ttulo del libro y el nombre de la editorial; los ttulos cuyo cdigo
de editorial no est presente en "editoriales" aparecen en el resultado, pero con el valor
"null" en el campo "nombre".
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,
es decir, cuyo valor de cdigo est presente en "libros":
select titulo,nombre
from editoriales as e
left join libros as l
on e.codigo=codigoeditorial
where codigoeditorial is not null;
Tambin podemos mostrar las editoriales que NO estn presentes en "libros", es decir, que
NO encuentran coincidencia en la tabla de la derecha:
select titulo,nombre
from editoriales as e
left join libros as l
on e.codigo=codigoeditorial
where codigoeditorial is null;
El resultado mostrar el ttulo y nombre de la editorial; las editoriales de las cuales no hay
libros, es decir, cuyo cdigo de editorial no est presente en "libros" aparece en el resultado,
pero con el valor "null" en el campo "titulo".
Es FUNDAMENTAL tener en cuenta la posicin en que se colocan las tablas en los "outer
join". En un "left join" la primera tabla (izquierda) es la que busca coincidencias en la
segunda tabla (derecha); en el "right join" la segunda tabla (derecha) es la que busca
coincidencias en la primera tabla (izquierda).
En la siguiente consulta empleamos un "left join" para conseguir el mismo resultado que el
"right join" anterior":
select titulo,nombre
from editoriales as e
left join libros as l
on codigoeditorial = e.codigo;
Note que la tabla que busca coincidencias ("editoriales") est en primer lugar porque es un
"left join"; en el "right join" precedente, estaba en segundo lugar.
Un "right join" hace coincidir registros en una tabla (derecha) con otra tabla (izquierda); si
un valor de la tabla de la derecha no encuentra coincidencia en la tabla izquierda, se genera
una fila extra (una por cada valor no encontrado) con todos los campos correspondientes a
la tabla izquierda seteados a "null". La sintaxis bsica es la siguiente:
select CAMPOS
from TABLAIZQUIERDA
right join TABLADERECHA
on CONDICION;
Un "right join" tambin puede tener clusula "where" que restringa el resultado de la
consulta considerando solamente los registros que encuentran coincidencia en la tabla
izquierda:
select titulo,nombre
from libros as l
right join editoriales as e
on e.codigo=codigoeditorial
where codigoeditorial is not null;
Mostramos las editoriales que NO estn presentes en "libros", es decir, que NO encuentran
coincidencia en la tabla de la derecha empleando un "right join":
select titulo,nombre
from libros as l
rightjoin editoriales as e
on e.codigo=codigoeditorial
where codigoeditorial is null;
La salida del "full join" precedente muestra todos los registros de ambas tablas, incluyendo
los libros cuyo cdigo de editorial no existe en la tabla "editoriales" y las editoriales de las
cuales no hay correspondencia en "libros".
La salida muestra cada plato combinado con cada uno de los postres.
Como cualquier tipo de "join", puede emplearse una clusula "where" que condicione la
salida.
71 - Autocombinacin
Dijimos que es posible combinar una tabla consigo misma.
Un pequeo restaurante tiene almacenadas sus comidas en una tabla llamada "comidas" que
consta de los siguientes campos:
- nombre varchar(20),
- precio decimal (4,2) y
- rubro char(6)-- que indica con 'plato' si es un plato principal y
'postre' si es postre.
Podemos obtener la combinacin de platos empleando un "cross join" con una sola tabla:
select c1.nombre as 'plato principal',
c2.nombre as postre,
c1.precio+c2.precio as total
from comidas as c1
cross join comidas as c2;
En la consulta anterior se emple un "where" que especifica que se combine "plato" con
"postre".
En una autocombinacin se combina una tabla con una copia de si misma. Para ello
debemos utilizar 2 alias para la tabla. Para evitar que aparezcan filas duplicadas, debemos
emplear un "where".
Tambin se puede realizar una autocombinacin con "join":
select c1.nombre as 'plato principal',
c2.nombre as postre,
c1.precio+c2.precio as total
from comidas as c1
join comidas as c2
on c1.codigo<>c2.codigo
where c1.rubro='plato' and
c2.rubro='postre';
Note que las editoriales que no tienen libros no aparecen en la salida porque empleamos un
"join".
Empleamos otra funcin de agrupamiento con "left join". Para conocer el mayor precio de
los libros de cada editorial usamos la funcin "max()", hacemos un "left join" y agrupamos
por nombre de la editorial:
select nombre as editorial,
max(precio) as 'mayor precio'
from editoriales as e
left join libros as l
on codigoeditorial=e.codigo
group by nombre;
En la sentencia anterior, mostrar, para la editorial de la cual no haya libros, el valor "null"
en la columna calculada.
tabla "editoriales" enlazndolas por los campos correspondientes. Utilizamos alias para una
sentencia ms sencilla y comprensible.
Note que especificamos a qu tabla pertenecen los campos cuyo nombre se repiten en las
tablas, esto es necesario para evitar confusiones y ambiguedades al momento de referenciar
un campo.
Note que no aparecen los libros cuyo cdigo de autor no se encuentra en "autores" y cuya
editorial no existe en "editoriales", esto es porque realizamos una combinacin interna.
Podemos combinar varios tipos de join en una misma sentencia:
select titulo,a.nombre,e.nombre
from autores as a
right join libros as l
on codigoautor=a.codigo
left join editoriales as e on codigoeditorial=e.codigo;
En la consulta anterior solicitamos el ttulo, autor y editorial de todos los libros que
encuentren o no coincidencia con "autores" ("right join") y a ese resultado lo combinamos
con "editoriales", encuentren o no coincidencia.
Es posible realizar varias combinaciones para obtener informacin de varias tablas. Las
tablas deben tener claves externas relacionadas con las tablas a combinar.
En consultas en las cuales empleamos varios "join" es importante tener en cuenta el orden
de las tablas y los tipos de "join"; recuerde que la tabla resultado del primer join es la que
se combina con el segundo join, no la segunda tabla nombrada. En el ejemplo anterior, el
"left join" no se realiza entre las tablas "libros" y "editoriales" sino entre el resultado del
"right join" y la tabla "editoriales".
75 - Clave fornea
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 fornea, externa o ajena.
En el ejemplo de la librera en que utilizamos las tablas "libros" y "editoriales" con estos
campos:
libros: codigo (clave primaria), titulo, autor, codigoeditorial, precio
y
el campo "codigoeditorial" de "libros" es una clave fornea, se emplea para enlazar la tabla
"libros" con "editoriales" y es clave primaria en "editoriales" con el nombre "codigo".
Las claves forneas y las claves primarias deben ser del mismo tipo para poder enlazarse. Si
modificamos una, debemos modificar la otra para que los valores se correspondan.
Cuando alteramos una tabla, debemos tener cuidado con las claves forneas. Si
modificamos el tipo, longitud o atributos de una clave fornea, sta puede quedar
inhabilitada para hacer los enlaces.
Entonces, una clave fornea es un campo (o varios) empleados para enlazar datos de 2
tablas, para establecer un "join" con otra tabla en la cual es clave primaria.
Con la restriccin "foreign key" se define un campo (o varios) cuyos valores coinciden con
la clave primaria de la misma tabla o de otra, es decir, se define una referencia a un campo
con una restriccin "primary key" o "unique" de la misma tabla o de otra.
La integridad referencial asegura que se mantengan las referencias entre las claves
primarias y las externas. Por ejemplo, controla que si se agrega un cdigo de editorial en la
tabla "libros", tal cdigo exista en la tabla "editoriales".
Tambin controla que no pueda eliminarse un registro de una tabla ni modificar la clave
primaria si una clave externa hace referencia al registro. Por ejemplo, que no se pueda
eliminar o modificar un cdigo de "editoriales" si existen libros con dicho cdigo.
La siguiente es la sintaxis parcial general para agregar una restriccin "foreign key":
alter table NOMBRETABLA1
add constraint NOMBRERESTRICCION
foreign key (CAMPOCLAVEFORANEA)
references NOMBRETABLA2 (CAMPOCLAVEPRIMARIA);
Analicmosla:
- NOMBRETABLA1 referencia el nombre de la tabla a la cual le aplicamos la restriccin,
- NOMBRERESTRICCION es el nombre que le damos a la misma,
- luego de "foreign key", entre parntesis se coloca el campo de la tabla a la que le
aplicamos la restriccin que ser establecida como clave fornea,
- luego de "references" indicamos el nombre de la tabla referenciada y el campo que es
clave primaria en la misma, a la cual hace referencia la clave fornea. La tabla referenciada
debe tener definida una restriccin "primary key" o "unique"; si no la tiene, aparece un
mensaje de error.
Para agregar una restriccin "foreign key" al campo "codigoeditorial" de "libros", tipeamos:
alter table libros
add constraint FK_libros_codigoeditorial
foreign key (codigoeditorial)
references editoriales(codigo);
En el ejemplo implementamos una restriccin "foreign key" para asegurarnos que el cdigo
de la editorial de la de la tabla "libros" ("codigoeditorial") est asociada con un cdigo
vlido en la tabla "editoriales" ("codigo").
Cuando agregamos cualquier restriccin a una tabla que contiene informacin, SQL Server
controla los datos existentes para confirmar que cumplen con la restriccin, si no los
cumple, la restriccin no se aplica y aparece un mensaje de error. Por ejemplo, si
intentamos agregar una restriccin "foreign key" a la tabla "libros" y existe un libro con un
valor de cdigo para editorial que no existe en la tabla "editoriales", la restriccin no se
agrega.
Acta en inserciones. Si intentamos ingresar un registro (un libro) con un valor de clave
fornea (codigoeditorial) que no existe en la tabla referenciada (editoriales), SQL server
muestra un mensaje de error. Si al ingresar un registro (un libro), no colocamos el valor
para el campo clave fornea (codigoeditorial), almacenar "null", porque esta restriccin
permite valores nulos (a menos que se haya especificado lo contrario al definir el campo).
Acta en eliminaciones y actualizaciones. Si intentamos eliminar un registro o modificar un
valor de clave primaria de una tabla si una clave fornea hace referencia a dicho registro,
SQL Server no lo permite (excepto si se permite la accin en cascada, tema que veremos
posteriormente). Por ejemplo, si intentamos eliminar una editorial a la que se hace
referencia en "libros", aparece un mensaje de error.
Esta restriccin (a diferencia de "primary key" y "unique") no crea ndice automaticamente.
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 clusula "references".
Esta restriccin se puede definir dentro de la misma tabla (lo veremos ms adelante) o entre
distintas tablas.
Una tabla puede tener varias restricciones "foreign key".
No se puede eliminar una tabla referenciada en una restriccin "foreign key", aparece un
mensaje de error.
Una restriccion "foreign key" no puede modificarse, debe eliminarse y volverse a crear.
Para ver informacin acerca de esta restriccin podemos ejecutar el procedimiento
almacenado "sp_helpconstraint" junto al nombre de la tabla. Nos muestra el tipo, nombre,
la opcin para eliminaciones y actualizaciones, el estado (temas que veremos ms
adelante), el nombre del campo y la tabla y campo que referencia.
Tambin informa si la tabla es referenciada por una clave fornea.
En caso que un afiliado no haya sido incorporado a la mutual por otro afiliado, el campo
"afiliadotitular" almacenar "null".
Establecemos una restriccin "foreign key" para asegurarnos que el nmero 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);
on update OPCION;
Para habilitar una restriccin deshabilitada se ejecuta la misma instruccin pero con la
clusula "check" o "check all":
alter table libros
check constraint FK_libros_codigoeditorial;
Si se emplea "check constraint all" no se coloca nombre de restricciones, habilita todas las
restricciones que tiene la tabla nombrada ("check" y "foreign key").
Para saber si una restriccin est habilitada o no, podemos ejecutar el procedimiento
almacenado "sp_helpconstraint" y entenderemos lo que informa la columna
"status_enabled".
Entonces, las clusulas "check" y "nocheck" permiten habilitar o deshabilitar restricciones
"foreign key" (y "check"). Pueden emplearse para evitar la comprobacin de datos
existentes al crear la restriccin o para deshabilitar la comprobacin de datos al ingresar,
actualizar y eliminar algn registro que infrinja la restriccin.
Podemos eliminar una restriccin "foreign key" con "alter table". La sintaxis bsica es la
misma que para cualquier otra restriccin:
alter table TABLA
drop constraint NOMBRERESTRICCION;
No se puede eliminar una tabla si una restriccin "foreign key" hace referencia a ella.
Cuando eliminamos una tabla que tiene una restriccin "foreign key", la restriccin tambin
se elimina.
82 - Unin
El operador "union" combina el resultado de dos o ms instrucciones "select" en un nico
resultado.
Se usa cuando los datos que se quieren obtener pertenecen a distintas tablas y no se puede
acceder a ellos con una sola consulta.
Es necesario que las tablas referenciadas tengan tipos de datos similares, la misma cantidad
de campos y el mismo orden de campos en la lista de seleccin de cada consulta. No se
incluyen las filas duplicadas en el resultado, a menos que coloque la opcin "all".
Se deben especificar los nombres de los campos en la primera instruccin "select".
Para agregar un nuevo campo a una tabla empleamos la siguiente sintaxis bsica:
alter table NOMBRETABLA
add NOMBRENUEVOCAMPO DEFINICION;
En el ejemplo anterior, se agreg una restriccin "default" para el nuevo campo, que puede
verificarse ejecutando el procedimiento almacenado "sp_helpconstraint".
Al agregar un campo puede especificarse que sea "identity" (siempre que no exista otro
campo identity).
Para eliminar campos de una tabla la sintaxis bsica es la siguiente:
alter table NOMBRETABLA
drop column NOMBRECAMPO;
No pueden eliminarse los campos que son usados por un ndice o tengan restricciones. No
puede eliminarse un campo si es el nico en la tabla.
Podemos eliminar varios campos en una sola sentencia:
alter table libros
drop column editorial,edicion;
En el siguiente ejemplo alteramos el campo "precio" de la tabla "libros" que fue definido
"decimal(6,2) not null" para que no acepte valores nulos:
alter table libros
alter column precio decimal(6,2) null;
SQL Server tiene algunas excepciones al momento de modificar los campos. No permite
modificar:
- campos de tipo text, image, ntext y timestamp.
- un campo que es usado en un campo calculado.
- campos que son parte de ndices o tienen restricciones, a menos que el cambio no afecte al
ndice o a la restriccin, por ejemplo, se puede ampliar la longitud de un campo de tipo
caracter.
- agregando o quitando el atributo "identity".
- 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"; un campo int
guarda un valor 300 y se pretende modificarlo a tinyint, etc.).
Agregamos a la tabla "libros", el campo "codigo" de tipo int identity not null y una
restriccin "primary key" con ndice no agrupado:
alter table libros
add codigo int identity not null
constraint PK_libros_codigo primary key nonclustered;
86 - Campos calculados
Un campo calculado es un campo que no se almacena fsicamente en la tabla. SQL Server
emplea una frmula que detalla el usuario al definir dicho campo para calcular el valor
segn otros campos de la misma tabla.
Un campo calculado no puede:
- definirse como "not null".
- ser una subconsulta.
- tener restriccin "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 expresin que la define no cambia en cada consulta.
Creamos un campo calculado denominado "sueldototal" que suma al sueldo bsico 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)
);
Los campos de los cuales depende el campo calculado no pueden eliminarse, se debe
eliminar primero el campo calculado.
Creamos un tipo de datos definido por el usuario llamado "tipo_documento" que admite
valores nulos:
exec sp_addtype tipo_documento, 'char(8)', 'null';
El parmetro "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 debern cumplir la regla. Si no se especifica este parmetro, 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 instruccin
"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 asociacin, 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 contina 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 instruccin "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 informacin 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.
El parmetro "futureonly" es opcional, especifica que si existen campos (de cualquier tabla)
con este tipo de dato, no se asocien al valor predeterminado; si creamos una nueva tabla
con este tipo de dato, si estar asociado al valor predeterminado. Si no se especifica este
parmetro, todos los campos de este tipo de dato, existentes o que se creen posteriormente
(de cualquier tabla), quedan asociados al valor predeterminado.
Si asocia un valor predeterminado a un tipo de dato definido por el usuario que tiene otro
valor predeterminado asociado, el ltimo lo reemplaza.
Para quitar la asociacin, empleamos el mismo procedimiento almacenado que aprendimos
cuando quitamos asociaciones a campos:
sp_unbindefault 'TIPODEDATODEFINIDOPORELUSUARIO';
Debe tener en cuenta que NO se puede aplicar una restriccin "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.
Si un campo de un tipo de dato definido por el usuario tiene una restriccin "default" y
luego se asocia un valor predeterminado al tipo de dato, el valor predeterminado no queda
asociado en el campo que tiene la restriccin "default".
Un tipo de dato definido por el usuario puede tener un solo valor predeterminado asociado.
Cuando obtenemos informacin del tipo da dato definido por el usuario ejecutando
"sp_help", en la columna "default_name" se muestra el nombre del valor predeterminado
asociado a dicho tipo de dato; muestra "none" cuando no tiene ningn valor predeterminado
asociado.
No se puede eliminar un tipo de datos definido por el usuario si alguna tabla (u otro objeto)
hace uso de l; por ejemplo, si una tabla tiene un campo definido con tal tipo de dato.
Si eliminamos un tipo de datos definido por el usuario, desaparecen las asociaciones de las
reglas y valores predeterminados, pero tales reglas y valores predeterminados, no se
eliminan, siguen existiendo en la base de datos.
91 - Subconsultas
Una subconsulta (subquery) es una sentencia "select" anidada en otra sentencia "select",
"insert", "update" o "delete" (o en otra subconsulta).
Las subconsultas se emplean cuando una consulta es muy compleja, entonces se la divide
en varios pasos lgicos y se obtiene el resultado con una nica instruccin y cuando la
consulta depende de los resultados de otra consulta.
Generalmente, una subconsulta se puede reemplazar por combinaciones y estas ltimas son
ms eficientes.
Las subconsultas se DEBEN incluir entre parntesis.
Puede haber subconsultas dentro de subconsultas, se admiten hasta 32 niveles de anidacin.
Se pueden emplear subconsultas:
- en lugar de una expresin, siempre que devuelvan un solo valor o una lista de valores.
- que retornen un conjunto de registros de varios campos en lugar de una tabla o para
obtener el mismo resultado que una combinacin (join).
Hay tres tipos bsicos de subconsultas:
1. las que retornan un solo valor escalar que se utiliza con un operador de comparacin
o en lugar de una expresin.
2. las que retornan una lista de valores, se combinan con "in", o los operadores "any",
"some" y "all".
3. los que testean la existencia con "exists".
Reglas a tener en cuenta al emplear subconsultas:
- la lista de seleccin de una subconsulta que va luego de un operador de comparacin
puede incluir slo una expresin o campo (excepto si se emplea "exists" y "in").
- si el "where" de la consulta exterior incluye un campo, este debe ser compatible con el
campo en la lista de seleccin de la subconsulta.
- no se pueden emplear subconsultas que recuperen campos de tipos text o image.
- las subconsultas luego de un operador de comparacin (que no es seguido por "any" o
"all") no pueden incluir clusulas "group by" ni "having".
- "distinct" no puede usarse con subconsultas que incluyan "group by".
- no pueden emplearse las clusulas "compute" y "compute by".
- "order by" puede emplearse solamente si se especifica "top" tambin.
- una vista creada con una subconsulta no puede actualizarse.
- una subconsulta puede estar anidada dentro del "where" o "having" de una consulta
externa o dentro de otra subconsulta.
- si una tabla se nombra solamente en un subconsulta y no en la consulta externa, los
campos no sern incluidos en la salida (en la lista de seleccin de la consulta externa).
Una subconsulta puede reemplazar una expresin. Dicha subconsulta debe devolver un
valor escalar (o una lista de valores de un campo).
Las subconsultas que retornan un solo valor escalar se utiliza con un operador de
comparacin o en lugar de una expresin:
select CAMPOS
from TABLA
where CAMPO OPERADOR (SUBCONSULTA);
select CAMPO OPERADOR (SUBCONSULTA)
from TABLA;
Si queremos saber el precio de un determinado libro y la diferencia con el precio del libro
ms costoso, anteriormente debamos averiguar en una consulta el precio del libro ms
costoso y luego, en otra consulta, calcular la diferencia con el valor del libro que
solicitamos. Podemos conseguirlo en una sola sentencia combinando dos consultas:
select titulo,precio,
precio-(select max(precio) from libros) as diferencia
from libros
where titulo='Uno';
Note que el campo del "where" de la consulta exterior es compatible con el valor retornado
por la expresin de la subconsulta.
Se pueden emplear en "select", "insert", "update" y "delete".
Para actualizar un registro empleando subconsulta la sintaxis bsica es la siguiente:
update TABLA set CAMPO=NUEVOVALOR
where CAMPO= (SUBCONSULTA);
93 - Subconsultas con in
Vimos que una subconsulta puede reemplazar una expresin. Dicha subconsulta debe
devolver un valor escalar o una lista de valores de un campo; las subconsultas que retornan
una lista de valores reemplazan a una expresin en una clusula "where" que contiene la
palabra clave "in".
El resultado de una subconsulta con "in" (o "not in") es una lista. Luego que la subconsulta
retorna resultados, la consulta exterior los usa.
La sintaxis bsica es la siguiente:
...where EXPRESION in (SUBCONSULTA);
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 subconsulta (consulta interna) retorna una lista de valores de un solo campo (codigo)
que la consulta exterior luego emplea al recuperar los datos.
Podemos reemplazar por un "join" la consulta anterior:
select distinct nombre
from editoriales as e
join libros
on codigoeditorial=e.codigo
where autor='Richard Bach';
Una combinacin (join) siempre puede ser expresada como una subconsulta; pero una
subconsulta no siempre puede reemplazarse por una combinacin que retorne el mismo
resultado. Si es posible, es aconsejable emplear combinaciones en lugar de subconsultas,
son ms eficientes.
Se recomienda probar las subconsultas antes de incluirlas en una consulta exterior, as
puede verificar que retorna lo necesario, porque a veces resulta difcil verlo en consultas
anidadas.
Tambin podemos buscar valores No coincidentes con una lista de valores que retorna una
subconsulta; por ejemplo, las editoriales que no han publicado libros de un autor especfico:
select nombre
from editoriales
where codigo not in
(select codigoeditorial
from libros
where autor='Richard Bach');
Queremos saber los ttulos de los libros de "Borges" que pertenecen a editoriales que han
publicado tambin libros de "Richard Bach", es decir, 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.codigo
from editoriales as e
join libros as l
on codigoeditorial=e.codigo
where l.autor='Richard Bach');
La consulta interna (subconsulta) retorna una lista de valores de un solo campo (puede
ejecutar la subconsulta como una consulta para probarla), luego, la consulta externa
compara cada valor de "codigoeditorial" con cada valor de la lista devolviendo los ttulos
de "Borges" que coinciden.
"all" tambin compara un valor escalar con una serie de valores. Chequea si TODOS los
valores de la lista de la consulta externa se encuentran en la lista de valores devuelta por la
consulta interna.
Sintaxis:
VALORESCALAR OPERADORDECOMPARACION all (SUBCONSULTA);
Queremos saber si TODAS las editoriales que publicaron libros de "Borges" coinciden con
TODAS las editoriales que publicaron libros de "Richard Bach":
select titulo
from libros
where autor='Borges' and
codigoeditorial = all
(select e.codigo
from editoriales as e
join libros as l
on codigoeditorial=e.codigo
where l.autor='Richard Bach');
La consulta interna (subconsulta) retorna una lista de valores de un solo campo (puede
ejecutar la subconsulta como una consulta para probarla), luego, la consulta externa
compara cada valor de "codigoeditorial" con cada valor de la lista, si TODOS coinciden,
devuelve los ttulos.
Veamos otro ejemplo con un operador de comparacin 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 > any
(select precio
from libros
where autor='Bach');
El precio de cada libro de "Borges" es comparado con cada valor de la lista de valores
retornada por la subconsulta; si ALGUNO cumple la condicin, es decir, es mayor a
ALGUN precio de "Richard Bach", se lista.
Veamos la diferencia si empleamos "all" en lugar de "any":
select titulo,precio
from libros
where autor='borges' and
precio > all
(select precio
from libros
where autor='bach');
El precio de cada libro de "Borges" es comparado con cada valor de la lista de valores
retornada por la subconsulta; si cumple la condicin, es decir, si es mayor a TODOS los
precios de "Richard Bach" (o al mayor), se lista.
Emplear "= any" es lo mismo que emplear "in".
Emplear "<> all" es lo mismo que emplear "not in".
Recuerde que solamente las subconsultas luego de un operador de comparacin al cual es
seguido por "any" o "all") pueden incluir clusulas "group by".
95 - Subconsultas correlacionadas
Un almacn almacena la informacin de sus ventas en una tabla llamada "facturas" en la
cual guarda el nmero de factura, 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 artculo, el precio (unitario) y la cantidad.
Se necesita una lista de todas las facturas que incluya el nmero, la fecha, el cliente, la
cantidad de artculos comprados y el total:
select f.*,
(select count(d.numeroitem)
from Detalles as d
where f.numero=d.numerofactura) as cantidad,
(select sum(d.preciounitario*cantidad)
from Detalles as d
where f.numero=d.numerofactura) as total
from facturas as f;
El segundo "select" retorna una lista de valores de una sola columna con la cantidad de
items por factura (el nmero de factura lo toma del "select" exterior); el tercer "select"
retorna una lista de valores de una sola columna con el total por factura (el nmero de
factura lo toma del "select" exterior); el primer "select" (externo) devuelve todos los datos
de cada factura.
A este tipo de subconsulta se la denomina consulta correlacionada. La consulta interna se
evala tantas veces como registros tiene la consulta externa, se realiza la subconsulta para
cada registro de la consulta externa. El campo de la tabla dentro de la subconsulta
(f.numero) se compara con el campo de la tabla externa.
96 - Exists y No Exists
Los operadores "exists" y "not exists" se emplean para determinar si hay o no datos en una
lista de valores.
Estos operadores pueden emplearse con subconsultas correlacionadas para restringir el
resultado de una consulta exterior a los registros que cumplen la subconsulta (consulta
interior). Estos operadores retornan "true" (si las subconsultas retornan registros) o "false"
(si las subconsultas no retornan registros).
Cuando se coloca en una subconsulta el operador "exists", SQL Server analiza si hay datos
que coinciden con la subconsulta, no se devuelve ningn registro, es como un test de
existencia; SQL Server termina la recuperacin de registros cuando por lo menos un
registro cumple la condicin "where" de la subconsulta.
La sintaxis bsica es la siguiente:
... where exists (SUBCONSULTA);
and d.articulo='lapiz');
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');
Por cada valor de l1, se evala la subconsulta, si el precio es mayor que el promedio.
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;
Eliminamos todos los libros de las editoriales que tiene publicados libros de "Juan Perez":
delete from libros
where codigoeditorial in
(select e.codigo
from editoriales as e
join libros
on codigoeditorial=e.codigo
where autor='Juan Perez');
La subconsulta es una combinacin que retorna una lista de valores que la consulta externa
emplea al seleccionar los registros para la eliminacin.
Un profesor almacena las notas de sus alumnos en una tabla llamada "alumnos". Tiene otra
tabla llamada "aprobados", con algunos campos iguales a la tabla "alumnos" pero en ella
solamente almacenar los alumnos que han aprobado el ciclo.
Ingresamos registros en la tabla "aprobados" seleccionando registros de la tabla "alumnos":
insert into aprobados (documento,nota)
select (documento,nota)
from alumnos;
Entonces, se puede insertar registros en una tabla con la salida devuelta por una consulta a
otra tabla; 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 cargarn (si se ingresan
todos los campos no es necesario listarlos).
La cantidad de columnas devueltas en la consulta debe ser la misma que la cantidad de
campos a cargar en el "insert".
Se pueden insertar valores en una tabla con el resultado de una consulta que incluya
cualquier tipo de "join".
Es decir, se crea una nueva tabla y se inserta en ella el resultado de una consulta a otra
tabla.
Tenemos la tabla "libros" de una librera y queremos crear una tabla llamada "editoriales"
que contenga los nombres de las editoriales.
La tabla "editoriales", que no existe, contendr solamente un campo llamado "nombre". La
tabla libros contiene varios registros.
Podemos crear la tabla "editoriales" con el campo "nombre" consultando la tabla "libros" y
en el mismo momento insertar la informacin:
select distinct editorial as nombre
into editoriales
from libros;
102 - go
Esto solo se aplica cuando instale el SQL Server en su mquina.
"go" es un signo de finalizacin de un lote de sentencias. No es una sentencia, es un
comando. El lote de sentencias est compuesto por todas las sentencias antes de "go" o
todas las sentencias entre dos "go".
Las sentencias no deben ocupar la misma linea en la que est "go".
Habr notado que no se puede ejecutar un procedimiento almacenado luego de otras
sentencias a menos que se incluya "execute" (o "exec").
Por ejemplo, si tipeamos:
select *from empleados;
sp_helpconstraint empleados;
muestra un mensaje de error porque no puede procesar ambas sentencias como un solo lote.
Para que no ocurra debemos tipear:
select *from empleados;
exec sp_helpconstraint empleados;
Las siguientes sentencias no pueden ejecutarse en el mismo lote: create rule, create
default,create view, create procedure, create trigger. Cada una de ellas necesita ejecutarse
separndolas con "go". Por ejemplo:
create table....
go
create rule...
go
Recuerde que si coloca "go" no debe incluir el "punto y coma" (;) al finalizar una
instruccin.
No est de ms recordar que esto solo se aplica cuando instale el SQL Server en su mquina
y ejecute los comandos desde el Query Analyzer.
103 - Vistas
Una vista es una alternativa para mostrar datos de varias tablas. Una vista es como una
tabla virtual que almacena una consulta. Los datos accesibles a travs de la vista no estn
almacenados en la base de datos como un objeto.
Entonces, una vista almacena una consulta como un objeto para utilizarse posteriormente.
Las tablas consultadas en una vista se llaman tablas base. En general, se puede dar un
nombre a cualquier consulta y almacenarla como una vista.
Una vista suele llamarse tambin tabla virtual porque los resultados que retorna y la manera
de referenciarlas es la misma que para una tabla.
Las vistas permiten:
- ocultar informacin: permitiendo el acceso a algunos datos y manteniendo oculto el resto
de la informacin que no se incluye en la vista. El usuario opera con los datos de una vista
como si se tratara de una tabla, pudiendo modificar tales datos.
- simplificar la administracin de los permisos de usuario: se pueden dar al usuario
permisos para que solamente pueda acceder a los datos a travs de vistas, en lugar de
concederle permisos para acceder a ciertos campos, as se protegen las tablas base de
cambios en su estructura.
- mejorar el rendimiento: se puede evitar tipear instrucciones repetidamente almacenando
en una vista el resultado de una consulta compleja que incluya informacin de varias tablas.
Podemos crear vistas con: un subconjunto de registros y campos de una tabla; una unin de
varias tablas; una combinacin de varias tablas; un resumen estadstico de una tabla; un
subconjunto de otra vista, combinacin de vistas y tablas.
Una vista se define usando un "select".
La sintaxis bsica parcial para crear una vista es la siguiente:
create view NOMBREVISTA as
SENTENCIASSELECT
from TABLA;
Los nombres para vistas deben seguir las mismas reglas que cualquier identificador. Para
distinguir una tabla de una vista podemos fijar una convencin para darle nombres, por
ejemplo, colocar el sufijo vista y luego el nombre de las tablas consultadas en ellas.
Los campos y expresiones de la consulta que define una vista DEBEN tener un nombre. Se
debe colocar nombre de campo cuando es un campo calculado o si hay 2 campos con el
mismo nombre. Note que en el ejemplo, al concatenar los campos "apellido" y "nombre"
colocamos un alias; si no lo hubisemos hecho aparecera un mensaje de error porque dicha
expresin DEBE tener un encabezado, SQL Server no lo coloca por defecto.
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). Note que en la vista
definida en el ejemplo, al campo "s.nombre" le colocamos un alias porque ya haba un
encabezado (el alias de la concatenacin) llamado "nombre" y no pueden repetirse, si
sucediera, aparecera un mensaje de error.
La diferencia es que se colocan entre parntesis los encabezados de las columnas que
aparecern en la vista. Si no los colocamos y empleamos la sintaxis vista anteriormente, se
emplean los nombres de los campos o alias (que en este caso habra que agregar) colocados
en el "select" que define la vista. Los nombres que se colocan entre parntesis deben ser
tantos como los campos o expresiones que se definen en la vista.
Las vistas se crean en la base de datos activa.
Al crear una vista, SQL Server verifica que existan las tablas a las que se hacen referencia
en ella.
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.
Existen algunas restricciones para el uso de "create view", a saber:
- no puede incluir las clusulas "compute" ni "compute by" ni la palabra clave "into";
- no se pueden crear vistas temporales ni crear vistas sobre tablas temporales.
- no se pueden asociar reglas ni valores por defecto a las vistas.
- no puede combinarse con otras instrucciones en un mismo lote.
Se pueden construir vistas sobre otras vistas.
aparecen las tablas (y dems objetos) de las cuales depende la vista, es decir, las tablas
referenciadas en la misma.
Si ejecutamos el procedimiento seguido del nombre de una tabla:
sp_depends empleados;
Nos muestra nombre y varios datos de todos los objetos de la base de datos actual. La
columna "xtype" indica el tipo de objeto, si es una vista, aparece 'V'.
Si queremos ver todas las vistas creadas por nosotros, podemos tipear:
select *from sysobjects
where xtype='V' and-- tipo vista
name like 'vista%';--bsqueda con comodn
Podemos ocultar el texto que define una vista empleando la siguiente sintaxis al crearla:
create view NOMBREVISTA
with encryption
as
SENTENCIASSELECT
from TABLA;
"with encryption" indica a SQL Server que codifique las sentencias que definen la vista.
Creamos una vista con su definicin oculta:
create view vista_empleados
with encryption
as
Si se elimina una tabla a la que hace referencia una vista, la vista no se elimina, hay que
eliminarla explcitamente.
Solo el propietario puede eliminar una vista.
Antes de eliminar un objeto, se recomienda ejecutar el procedimiento almacenado de
sistema "sp_depends" para averiguar si hay objetos que hagan referencia a l.
Eliminamos la vista denominada "vista_empleados":
drop view vista_empleados;
La vista definida anteriormente muestra solamente algunos de los datos de los empleados
de la seccin "Administracion". Adems, solamente se permiten modificaciones a los
empleados de esa seccin.
Podemos actualizar el nombre, apellido y sexo a travs de la vista, pero no el campo
"seccion" porque est restringuido.
Se puede insertar, actualizar o eliminar datos de una tabla a travs de una vista, teniendo en
cuenta lo siguiente, las modificaciones que se realizan a las vistas:
- no pueden afectar a ms de una tabla consultada. Pueden modificarse datos de una vista
que combina varias tablas pero la modificacin solamente debe afectar a una sola tabla.
- no se pueden cambiar los campos resultado de un clculo.
- pueden generar errores si afectan a campos a las que la vista no hace referencia. Por
ejemplo, si se ingresa un registro en una vista que consulta una tabla que tiene campos not
null que no estn incluidos en la vista.
- la opcin "with check option" obliga a todas las instrucciones de modificacin que se
ejecutan en la vista a cumplir ciertos criterios que se especifican al definir la vista.
- para eliminar datos de una vista solamente UNA tabla puede ser listada en el "from" de la
definicion de la misma.
Si crea una vista con "select *" y luego agrega campos a la estructura de las tablas
involucradas, los nuevos campos no aparecern en la vista; esto es porque los campos se
seleccionan al ejecutar "create view"; debe alterar la vista.
Por cada valor hay un "when" y un "then"; si encuentra un valor coincidente en algn
"where" ejecuta el "then" correspondiente a ese "where", si no encuentra ninguna
coincidencia, se ejecuta el "else"; si no hay parte "else" retorna "null". Finalmente se coloca
"end" para indicar que el "case" ha finalizado.
Un profesor guarda las notas de sus alumnos de un curso en una tabla llamada "alumnos"
que consta de los siguientes campos:
- nombre (30 caracteres),
- nota (valor entero entre 0 y 10, puede ser nulo).
Queremos mostrar los nombres, 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:
- 0, 1, 2 3: 'libre';
- 4, 5 6: 'regular';
- 7, 8, 9 10: 'promocionado';
Esta es la sentencia:
select nombre,nota, resultado=
case nota
when 0 then 'libre'
when 1 then 'libre'
when 2 then 'libre'
when 3 then 'libre'
when 4 then 'regular'
when 5 then 'regular'
when 6 then 'regular'
when 7 then 'promocionado'
when 8 then 'promocionado'
when 9 then 'promocionado'
when 10 then 'promocionado'
end
from alumnos;
Note que cada "where" compara un valor puntual, por ello los valores devueltos son iguales
para algunos casos. Note que como omitimos la parte "else", en caso que el valor no
encuentre coincidencia con ninguno valor "when", retorna "null".
Podemos realizar comparaciones en cada "where". La sintaxis es la siguiente:
case
when VALORACOMPARAR OPERADOR VALOR1 then RESULTADO1
when VALORACOMPARAR OPERADOR VALOR2 then RESULTADO2
...
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, est entre 4 y 7 o supera el 7:
select nombre, nota, condicion=
case
when nota<4 then 'libre'
when nota >=4 and nota<7 then 'regular'
when nota>=7 then 'promocionado'
else 'sin nota'
end
from alumnos;
Puede utilizar una expresin "case" en cualquier lugar en el que pueda utilizar una
expresin.
Tambin se puede emplear con "group by" y funciones de agrupamiento.
SQL Server ejecuta la sentencia (en este caso, una subconsulta) luego del "if" si la
condicin es verdadera; si es falsa, ejecuta la sentencia del "else" (si existe).
Podemos emplear "if...else" en actualizaciones. Por ejemplo, queremos hacer un descuento
en el precio, del 10% a todos los libros de una determinada editorial; si no hay, mostrar un
mensaje:
if exists (select *from libros where editorial='Emece')
begin
update libros set precio=precio-(precio*0.1) where editorial='Emece'
select 'libros actualizados'
end
else
select 'no hay registros actualizados';
Note que si la condicin es verdadera, se deben ejecutar 2 sentencias. Por lo tanto, se deben
encerrar en un bloque "begin...end".
En el siguiente ejemplo eliminamos los libros cuya cantidad es cero; si no hay, mostramos
un mensaje:
if exists (select *from libros where cantidad=0)
delete from libros where cantidad=0
else
select 'No hay registros eliminados;
colocando "declare" el nombre de la variable que comienza con el smbolo arroba (@) y el
tipo de dato. Ejemplo:
declare @nombre varchar(20)
Para almacenar un valor en una variable se coloca el signo igual (=) entre la variable y el
valor a asignar.
Si le asignamos un valor resultado de una consulta, la sintaxis es:
select @nombre = autor from libros where titulo='Uno'
La utilidad de las variables consiste en que almacenan valores para utilizarlos en otras
consultas.
Por ejemplo, queremos saber todos los datos del libro con mayor precio de la tabla "libros"
de una librera. Para ello podemos emplear una variable para almacenar el precio ms alto:
declare @mayorprecio
select @mayorprecio:=max(precio) from libros
y luego mostrar todos los datos de dicho libro empleando la variable anterior:
select *from libros
where precio=@mayorprecio;
La funcin "textptr" retorna un puntero a texto (valor binario de 16). Si el campo no tiene
texto, retorna un puntero a null; por ello se debe usar la funcin "textvalid" para confirmar
si el puntero a texto existe.
Si la consulta retorna ms de un registro, "textptr" retorna un puntero a texto del ltimo
registro devuelto.
La funcion "textvalid" controla si un puntero a texto es vlido. Sintaxis:
textvalid ('TABLA.CAMPO', PUNTEROATEXTO);
Los argumentos son: el nombre de la tabla y campo y el nombre del puntero a texto que se
va a controlar. Retorna 1 si el puntero es vlido y 0 si no lo es. No se puede emplear
"updatetext", "writetext" y "readtext" si el puntero no es vlido.
La siguiente consulta muestra si los punteros son vlidos en cada registro del campo
"sinopsis" de la tabla "libros":
select titulo,
Solo disponemos punto y coma al final para que SQL Server ejecute todas las instrucciones
en un solo lote y exista la variable @puntero.
Si al insertar registros se ingresa un valor "null" en un campo "text", "ntext" o "image" o no
se ingresa valor, no se crea un puntero vlido. Para crear un puntero a texto vlido ejecute
un "insert" o "update" con datos que no sean nulos para el campo text, ntext o image.
Analicemos la sintaxis:
- PUNTEROATEXTO: puntero a texto vlido, binary(16).
- DESPLAZAMIENTO: nmero de bytes (para text o image) o caracteres (ntext) que se
mueve el puntero antes de comenzar a leer.
- CANTIDAD: nmero de bytes o caracteres a leer desde la posicin indicada por
DESPLAZAMIENTO. Si es 0, se leen 4KB bytes o hasta el final.
Leemos la informacin almacenada en el campo "sinopsis" de "libros" del registro con
cdigo 2, desde la posicin 9, 50 caracteres:
declare @puntero varbinary(16)
select @puntero=textptr(sinopsis)
from libros
where codigo=2
readtext libros.sinopsis @puntero 9 50;
Recuerde que si al insertar registros se ingresa un valor "null" en un campo "text", "ntext" o
"image" o no se ingresan datos, no se crea un puntero vlido y al intentar escribir dicho
campo ocurre un error, porque la funcin "writetext" requiere un puntero vlido. Para
evitarlo podemos chequer el puntero antes de pasrselo a la funcin de escritura:
declare @puntero varbinary(16)
select @puntero=textptr(sinopsis)
from libros where codigo=1
if (textvalid('libros.sinopsis', @puntero)=1)
writetext libros.sinopsis @puntero 'Trata de una gaviota que vuela ms
alto que las demas.'
else select 'puntero invalido, no se actualiz el registro';
Analizamos la sintaxis:
- TABLA.CAMPO: campo y tabla que se va a actualizar.
- PUNTEROATEXTO: valor del puntero, retornado por la funcin "textptr", que apunta al
dato text, ntext o image que se quiere actualizar.
- DESPLAZAMIENTODELPUNTERO: indica la posicin en que inserta el nuevo dato.
Especifica la cantidad de bytes (para campos text e image) o caracteres (para campos ntext)
que debe moverse el puntero para insertar el dato. Los valores pueden ser: 0 (el nuevo dato
se inserta al comienzo), "null" (coloca el puntero al final), un valor mayor a cero y menor o
igual a la longitud total del texto (inserta el nuevo dato en la posicin indicada) y un valor
mayor a la longitud total del campo (genera un mensaje de error).
Es importante recordar que cada caracter ntext ocupa 2 bytes.
- LONGITUDDEBORRADO: indica la cantidad de bytes (para text e image) o caracteres
(para ntext) a borrar comenzando de la posicin indicada por el parmetro
DESPLAZAMIENTODELPUNTERO. Si colocamos el valor 0 (no se borra ningn dato),
"null" (borra todos los datos desde la posicin indicada por el parmetro
DESPLAZAMIENTODELPUNTERO hasta el final), un valor mayor que cero y menor o
igual a la longitud del texto (borra tal cantidad) y un valor invlido, es decir, mayor a la
longitud del texto (genera un mensaje de error).
Es importante recordar que cada caracter "ntext" ocupa 2 bytes.
- DATOAINSERTAR: el dato que va a ser insertado en el campo. Puede ser char, nchar,
varchar, nvarchar, binary, varbinary, text, ntext, image, un literal o una variable. Si el dato
es un campo text, ntext o image de otra tabla, se debe indicar el nombre de la tabla junto
con el campo y el valor del puntero que apunta al tipo de dato text, ntext o image (retornado
por la funcin "textptr"), de esta forma:
TABLA.CAMPO PUNTERO;
Tenemos la tabla libros, con un campo de tipo text llamado "sinopsis"; hay un registro
cargado con el siguiente texto: "Para aprender PHP a paso." Necesitamos agregar antes de
"a paso" el texto "paso " para que el texto completo sea "Para aprender PHP paso a paso",
tipeamos:
declare @puntero binary(16)
select @puntero = textptr(sinopsis)
from libros
where titulo='Aprenda PHP'
updatetext libros.sinopsis @puntero
18 0 'paso ';
Entonces, se emplea "updatetext" para modificar datos de campos de tipo text, ntext e
image, pudiendo cambiar una porcin del texto.
Con este tipo de datos tambin puede utilizarse "like", pero "like" solamente puede
incluirse en la clusula "where".
- substring (TEXTO,INICIO,LONGITUD): devuelve una parte del texto especificado como
primer argumento, empezando desde la posicin especificada por el segundo argumento y
de tantos caracteres de longitud como indica el tercer argumento.
Ejemplo:
select titulo,substring(sinopsis,1,20)
from libros;
as
select *from libros
where cantidad <=10;
Y luego lo ejecutamos cada vez que comenzamos un nuevo ejercicio y as evitamos tipear
tantas sentencias:
exec pa_crear_libros;
Los parmetros se definen luego del nombre del procedimiento, comenzando el nombre con
un signo arroba (@). Los parmetros son locales al procedimiento, es decir, existen
solamente dentro del mismo. Pueden declararse varios parmetros por procedimiento, se
separan por comas.
Cuando el procedimiento es ejecutado, deben explicitarse valores para cada uno de los
parmetros (en el orden que fueron definidos), a menos que se haya definido un valor por
defecto, en tal caso, pueden omitirse. Pueden ser de cualquier tipo de dato (excepto cursor).
Luego de definir un parmetro y su tipo, opcionalmente, se puede especificar un valor por
defecto; tal valor es el que asume el procedimiento al ser ejecutado si no recibe parmetros.
Si no se coloca valor por defecto, un procedimiento definido con parmetros no puede
ejecutarse sin valores para ellos. El valor por defecto puede ser "null" o una constante,
tambin puede incluir comodines si el procedimiento emplea "like".
Creamos un procedimiento que recibe el nombre de un autor como parmetro para mostrar
todos los libros del autor solicitado:
create procedure pa_libros_autor
@autor varchar(30)
as
select titulo, editorial,precio
from libros
where autor= @autor;
Cuando pasamos valores con el nombre del parmetro, el orden en que se colocan puede
alterarse.
Podemos ejecutar el procedimiento anterior sin enviarle valores, usar los predeterminados.
Si enviamos un solo parmetro a un procedimiento que tiene definido ms de un parmetro
sin especificar a qu parmetro corresponde (valor por posicin), asume que es el primero.
Es decir, SQL Server asume que los valores se dan en el orden que fueron definidos, no se
puede interrumpir la secuencia.
Si queremos especificar solamente el segundo parmetro, debemos emplear la sintaxis de
paso de valores a parmetros por nombre:
exec pa_libros_autor_editorial2 @editorial='Paidos';
Los parmetros de salida pueden ser de cualquier tipo de datos, excepto text, ntext e image.
Creamos un procedimiento almacenado al cual le enviamos 2 nmeros y retorna el
promedio:
create procedure pa_promedio
@n1 decimal(4,2),
@n2 decimal(4,2),
@resultado decimal(4,2) output
as
select @resultado=(@n1+@n2)/2;
Declaramos una variable para guardar el valor devuelto por el procedimiento; ejecutamos el
procedimiento envindole 2 valores y mostramos el resultado.
La instruccin que realiza la llamada al procedimiento debe contener un nombre de variable
para almacenar el valor retornado.
Creamos un procedimiento almacenado que muestre los ttulos, editorial y precio de los
libros de un determinado autor (enviado como parmetro 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)='%',
@suma decimal(6,2) output,
@promedio decimal(6,2) output
as
select titulo,editorial,precio
from libros
where autor like @autor
select @suma=sum(precio)
from libros
where autor like @autor
select @promedio=avg(precio)
from libros
where autor like @autor;
Para ver el resultado, debemos declarar una variable en la cual se almacene el valor
devuelto por el procedimiento; luego, ejecutar el procedimiento asignndole el valor
devuelto a la variable, finalmente mostramos el contenido de la variable:
declare @retorno int
exec @retorno=pa_libros_ingreso 'Alicia en el pais...','Lewis Carroll'
select 'Ingreso realizado=1' = @retorno
exec @retorno=pa_libros_ingreso
select 'Ingreso realizado=1' = @retorno;
aparecen las tablas (y dems objetos) de las cuales depende el procedimiento, es decir, las
tablas referenciadas en el mismo. Podemos ejecutar el procedimiento seguido del nombre
de una tabla:
sp_depends libros;
Si queremos ver todos los procedimientos almacenados creados por nosotros, podemos
tipear:
select *from sysobjects
where xtype='P' and-- tipo procedimiento
name like 'pa%';--bsqueda con comodn
as INSTRUCCIONES;
Si quiere modificar un procedimiento que se cre con la opcin "with encryption" y quiere
conservarla, debe incluirla al alterarlo.
Creamos otro procedimiento que nos retorne el factorial de un nmero, tal procedimiento
llamar al procedimiento "pa_multiplicar":
create procedure pa_factorial
@numero int
as
declare @resultado int
declare @num int
set @resultado=1
set @num=@numero
while (@num>1)
begin
exec pa_multiplicar @resultado,@num, @resultado output
set @num=@num-1
end
select rtrim(convert(char,@numero))+'!='+convert(char,@resultado);
Cuando un procedimiento (A) llama a otro (B), el segundo (B) tiene acceso
a todos los objetos que cree el primero (A).
Para referenciarla en otras consultas, se debe incluir el numeral(#), que es parte del nombre.
Por ejemplo:
insert into #libros default values;
select *from #libros;
Una tabla temporal no puede tener una restriccin "foreign key" ni ser indexada, tampoco
puede ser referenciada por una vista.
Para crear tablas temporales globales se emplea la misma sintaxis que para crear cualquier
tabla, excepto que se coloca un signo numeral doble (##) precediendo el nombre.
create table ##NOMBRE(
CAMPO DEFINICION,
...
);
El (o los) numerales son parte del nombre. As que puede crearse una tabla permanente
llamada "libros", otra tabla temporal local llamada "#libros" y una tercera tabla temporal
global denominada "##libros".
No podemos consultar la tabla "sysobjects" para ver las tablas temporales, debemos tipear:
select *from tempdb..sysobjects;
para eliminar una tabla temporal create table #pepe (caca int)
if exists (select * from tempdb.dbo.sysobjects where name like'#pepe%')
select 'SI'
else
select 'NO'
drop table #pepe
133 - Funciones
SQL Server ofrece varios tipos de funciones para realizar distintas operaciones. Hemos
visto y empleado varias de ellas.
Se pueden emplear las funciones del sistema en cualquier lugar en el que se permita una
expresin en una sentencia "select".
Luego del nombre se colocan (opcionalmente) los parmetros de entrada con su tipo.
La clusula "returns" indica el tipo de dato retornado.
El cuerpo de la funcin, se define en un bloque "begin...end" que contiene las instrucciones
que retornan el valor. El tipo del valor retornado puede ser de cualquier tipo, excepto text,
ntext, image, cursor o timestamp.
Creamos una simple funcin denominada "f_promedio" que recibe 2 valores y retorna el
promedio:
create function f_promedio
(@valor1 decimal(4,2),
@valor2 decimal(4,2)
)
returns decimal (6,2)
as
begin
declare @resultado decimal(6,2)
set @resultado=(@valor1+@valor2)/2
return @resultado
end;
No olvide que cuando invocamos funciones que tienen definidos parmetros de entrada
DEBEMOS suministrar SIEMPRE un valor para l.
Podemos colocar un valor por defecto al parmetro, pero al invocar la funcin, para que
tome el valor por defecto DEBEMOS especificar "default". Por ejemplo, si llamamos a la
funcin anterior sin enviarle un valor:
select dbo.f_nombreMes();
Como cualquier otra funcin, se crea con "create function" seguida del nombre de la
funcin; luego (opcionalmente) los parmetros de entrada con su tipo de dato.
La clusula "returns" define un nombre de variable local para la tabla que retornar, el tipo
de datos a retornar (que es "table") y el formato de la misma (campos y tipos).
El cuerpo de la funcin se define tambin en un bloque "begin... end", el cual contiene las
instrucciones que insertan filas en la variable (tabla que ser retornada) definida en
"returns". "return" indica que las filas insertadas en la variable son retornadas; no puede ser
un argumento.
El siguiente ejemplo crea una funcin denominada "f_ofertas" que recibe un parmetro. La
funcin retorna una tabla con el codigo, ttulo, autor y precio de todos los libros cuyo precio
sea inferior al parmetro:
create function f_ofertas
(@minimo decimal(6,2))
returns @ofertas table-- nombre de la tabla
--formato de la tabla
(codigo int,
titulo varchar(40),
autor varchar(30),
precio decimal(6,2)
)
as
begin
insert @ofertas
select codigo,titulo,autor,precio
from libros
where precio < @minimo
return
end;
Las funciones que retornan una tabla pueden llamarse sin especificar propietario:
select *from f_ofertas(30);
select *from dbo.f_ofertas(30);
Dijimos que este tipo de funcin puede ser referenciada en el "from" de una consulta; la
siguiente consulta realiza un join entre la tabla "libros" y la tabla retornada por la funcin
"f_ofertas":
select *from libros as l
join dbo.f_ofertas(25) as o
on l.codigo=o.codigo;
Se puede llamar a la funcin como si fuese una tabla o vista listando algunos campos:
select titulo,precio from dbo.f_ofertas(40);
Como todas las funciones definidas por el usuario, se crea con "create function" seguido del
nombre que le damos a la funcin; luego declaramos los parmetros de entrada con su tipo
de dato entre parntesis. El valor por defecto es opcional.
"returns" especifica "table" como el tipo de datos a retornar. No se define el formato de la
tabla a retornar porque queda establecido en el "select".
El cuerpo de la funcin no contiene un bloque "begin...end" como las otras funciones.
La clusula "return" contiene una sola instruccin "select" entre parntesis. El resultado del
"select" es la tabla que se retorna. El "select" est sujeto a las mismas reglas que los "select"
de las vistas.
Creamos una funcin con valores de tabla en lnea que recibe un valor de autor como
parmetro:
create function f_libros
(@autor varchar(30)='Borges')
returns table
as
return (
select titulo,editorial
from libros
where autor like '%'+@autor+'%'
);
Estas funciones retornan una tabla y se hace referencia a ellas en la clusula "from", como
una vista:
select *from f_libros('Bach');
Recuerde a que todas las funciones que tienen definidos parmetros se les DEBE
suministrar valores para ellos al invocarse.
Recuerde que para que el parmetro tome el valor por defecto (si lo tiene) DEBE enviarse
"default" al llamar a la funcin; si no le enviamos parmetros, SQL Server muestra un
mensaje de error.
--incorrecto: select *from f_libros();
select *from f_libros(default);--correcto
Sintaxis para modificar una funcin 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
Veamos un ejemplo. Creamos una funcin que retorna una tabla en lnea:
end
Veamos un ejemplo:
create function f_libros
(@autor varchar(30)='Borges')
returns table
with encryption
as
return (
select titulo,editorial
from libros
where autor like '%'+@autor+'%'
);
- "sp_helptext": seguido del nombre de una funcin definida por el usuario nos muestra el
texto que define la funcin, excepto si ha sido encriptado.
- "sp_stored_procedures": muestra todos los procedimientos almacenados y funciones
definidas por el usuario.
- "sp_depends": seguido del nombre de un objeto, nos devuelve 2 resultados: 1) nombre,
tipo, campos, etc. 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). Por ejemplo, ejecutamos "sp_depends" seguido del nombre de una funcin
definida por el usuario:
sp_depends pa_libroslistado;
aparecen las tablas (y dems objetos) de las cuales depende el procedimiento, es decir, las
tablas (y campos) referenciadas en la misma. No aparecen objetos que dependan de la
funcin porque no existe ningn objeto que la referencie.
Podemos ejecutar el procedimiento seguido del nombre de una tabla:
sp_depends libros;
aparecen las funciones (y dems objetos) que dependen de ella (que la referencian). No
aparecen objetos de los cuales depende porque la tabla no los tiene.
- La tabla del sistema "sysobjects": muestra nombre y varios datos de todos los objetos de
la base de datos actual. La columna "xtype" indica el tipo de objeto. Si es una funcin
definida por el usuario escalar, muestra "FN", si es una funcin de tabla de varias
sentencias, muestra "TF" y si es una funcin de tabla en linea muestra "IF".
Si queremos ver el nombre, tipo y fecha de creacin de todas las funciones definidas por el
usuario, podemos tipear:
select name,xtype as tipo,crdate as fecha
from sysobjects
where xtype in ('FN','TF','IF');
- son apropiados para mantener la integridad de los datos, no para obtener resultados de
consultas.
Los disparadores, a diferencia de las restricciones "check", pueden hacer referencia a
campos de otras tablas. Por ejemplo, puede crearse un trigger de insercin en la tabla
"ventas" que compruebe el campo "stock" de un artculo en la tabla "articulos"; el
disparador controlara que, cuando el valor de "stock" sea menor a la cantidad que se
intenta vender, la insercin del nuevo registro en "ventas" no se realice.
Los disparadores se ejecutan DESPUES de la ejecucin de una instruccin "insert",
"update" o "delete" en la tabla en la que fueron definidos. Las restricciones se comprueban
ANTES de la ejecucin de una instruccin "insert", "update" o "delete". Por lo tanto, las
restricciones se comprueban primero, si se infringe alguna restriccin, el desencadenador
no llega a ejecutarse.
Los triggers se crean con la instruccin "create trigger". Esta instruccin especifica la tabla
en la que se define el disparador, los eventos para los que se ejecuta y las instrucciones que
contiene.
Sintaxis bsica:
create triggre NOMBREDISPARADOR
on NOMBRETABLA
for EVENTO- insert, update o delete
as
SENTENCIAS
Analizamos la sintaxis:
- "create trigger" junto al nombre del disparador.
- "on" seguido del nombre de la tabla o vista para la cual se establece el trigger.
- luego de "for", se indica la accin (evento, el tipo de modificacin) sobre la tabla o vista
que activar el trigger. Puede ser "insert", "update" o "delete". Debe colocarse al menos
UNA accin, si se coloca ms de una, deben separarse con comas.
- luego de "as" viene el cuerpo del trigger, se especifican las condiciones y acciones del
disparador; es decir, las condiciones que determinan cuando un intento de insercin,
actualizacin o borrado provoca las acciones que el trigger realizar.
Consideraciones generales:
- "create trigger" debe ser la primera sentencia de un bloque y slo se puede aplicar a una
tabla.
- un disparador se crea solamente en la base de datos actual pero puede hacer referencia a
objetos de otra base de datos.
- Las siguientes instrucciones no estn permitidas en un desencadenador: create database,
alter database, drop database, load database, restore database, load log, reconfigure, restore
log, disk init, disk resize.
- Se pueden crear varios triggers para cada evento, es decir, para cada tipo de modificacin
(insercin, actualizacin o borrado) para una misma tabla. Por ejemplo, se puede crear un
"insert trigger" para una tabla que ya tiene otro "insert trigger".
A continuacin veremos la creacin de un disparador para el suceso de insercin: "insert
triger".
Analizamos la sintaxis:
"create trigger" junto al nombre del disparador; "on" seguido del nombre de la tabla para la
cual se establece el trigger.
Luego de "for" se coloca el evento (en este caso "insert"), lo que indica que las inserciones
sobre la tabla activarn el trigger.
Luego de "as" se especifican las condiciones y acciones, es decir, las condiciones que
determinan cuando un intento de insercin provoca las acciones que el trigger realizar.
Creamos un trigger sobre la tabla "ventas" para el evento se insercin. Cada vez que se
realiza un "insert" sobre "ventas", el disparador se ejecuta. 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", restando al valor anterior la cantidad vendida:
create trigger DIS_ventas_insertar
on ventas
for insert
as
declare @stock int
select @stock= stock from libros
join inserted
on inserted.codigolibro=libros.codigo
where libros.codigo=inserted.codigolibro
if (@stock>=(select cantidad from inserted))
update libros set stock=stock-inserted.cantidad
from libros
join inserted
on inserted.codigolibro=libros.codigo
where codigo=inserted.codigolibro
else
begin
raiserror ('Hay menos libros en stock de los solicitados para la
venta', 16, 1)
rollback transaction
end
Dentro del trigger se puede acceder a esta tabla virtual "inserted" que contiene todos los
registros insertados, es lo que hicimos en el disparador creado anteriormente, lo que
solicitamos es que se le reste al "stock" de "libros", la cantidad ingresada en el nuevo
registro de "ventas", valor que recuperamos de la tabla "inserted".
"rollback transaction" es la sentencia que deshace la transaccin, es decir, borra todas las
modificaciones que se produjeron en la ltima transaccin restableciendo todo al estado
anterior.
"raiserror" muestra un mensaje de error personalizado.
Para identificar fcilmente 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 accin.
La instruccin "writetext" no activa un disparador.
Analizamos la sintaxis:
"create trigger" junto al nombre del disparador; "on" seguido del nombre de la tabla para la
cual se establece el trigger.
Luego de "for" se coloca el evento (en este caso "delete"), lo que indica que las
eliminaciones sobre la tabla activarn el trigger.
Luego de "as" se especifican las condiciones que determinan cuando un intento de
eliminacin causa las acciones que el trigger realizar.
El disparador del siguiente ejemplo se crea para la tabla "ventas", para que cada vez que se
elimine un registro de "ventas", se actualice el campo "stock" de la tabla "libros" (por
ejemplo, si el comprador devuelve los libros comprados):
create trigger DIS_ventas_borrar
on ventas
for delete
as
update libros set stock= libros.stock+deleted.cantidad
from libros
join deleted
on deleted.codigolibro=libros.codigo;
Si se ejecuta un "delete" sobre "libros" que afecte a varios registros, se activa el disparador
y evita la transaccin.
Si se ejecuta el siguiente "delete", que afecta a un solo registro, se activa el disparador y
permite la transaccin:
delete from libros where codigo=5;
Analizamos la sintaxis:
"create trigger" junto al nombre del disparador; "on" seguido del nombre de la tabla para la
cual se establece el trigger.
Luego de "for" se coloca el evento (en este caso "update"), lo que indica que las
actualizaciones sobre la tabla activarn el trigger.
Luego de "as" se especifican las condiciones y acciones, es decir, las condiciones que
determinan cuando un intento de modificacin provoca las acciones que el trigger realizar.
El siguiente disparador de actualizacin se crea para evitar que se modifiquen los datos de
la tabla "libros":
create trigger DIS_libros_actualizar
on libros
for update
as
raiserror('Los datos de la tabla "libros" no pueden modificarse', 10,
1)
rollback transaction
Empleamos "if update()" para que el trigger controle la actualizacin del campo "precio";
as, cuando el disparador detecte una actualizacin en tal campo, realizar las acciones
apropiadas (mostrar un mensaje y deshacer la actualizacin); en caso que se actualice otro
campo, el disparador se activa, pero permite la transaccin.
Creamos un disparador de actualizacin 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.codigo,
(d.titulo+'-'+ d.autor+'-'+d.editorial) as 'registro anterior',
(i.titulo+'-'+ i.autor+'-'+i.editorial) as 'registro actualizado'
from deleted as d
join inserted as i
on d.codigo=i.codigo
end
else
begin
raiserror('El precio y stock no pueden modificarse. La actualizacin
no se realiz.', 10, 1)
rollback transaction
end;
Empleamos "if update" para que el trigger controle si la actualizacin se realiza en ciertos
campos permitidos (titulo, autor y editorial) y no en los campos prohibidos (precio y
stock)); si se modifican los campos permitidos y ninguno de los no permitidos, mostrar los
antiguos y nuevos valores consultando las tablas "deleted" e "inserted", en caso que se
actualice un campo no permitido, el disparador muestra un mensaje y deshace la
transaccin.
Note que el disparador no controla los intentos de actualizacin sobre el campo "codigo",
esto es porque tal campo, no puede modificarse porque est definido "identity", si
intentamos modificarlo, SQL Server muestra un mensaje de error y el trigger no llega a
dispararse.
El trigger controla:
- si se intenta ingresar una inscripcin de un socio moroso, se deshace la transaccin;
- si se intenta eliminar una inscripcin de un socio que est en "morosos", se deshace la
transaccin;
- si se ingresa una nueva inscripcin y no se paga la matrcula, dicho socio se ingresa a la
tabla "morosos".
Veamos un ejemplo. Una empresa almacena los datos de sus empleados en una tabla
"empleados" y en otra tabla "clientes" los datos de sus clientes. Se crea una vista que
muestra los datos de ambas tablas:
create view vista_empleados_clientes
as
select documento,nombre, domicilio, 'empleado' as condicion from
empleados
union
select documento,nombre, domicilio,'cliente' from clientes;
El disparador anterior especifica que cada vez que se ingresen registros en la vista
"vista_empleados_clientes", en vez de (instead of) realizar la accin (insertar en la vista), se
ejecuten las sentencias del trigger, es decir, se ingresen los registros en las tablas
correspondientes.
Entonces, las opciones de disparo pueden ser:
a) "after": el trigger se dispara cuando las acciones especificadas (insert, delete y/o update)
son ejecutadas; todas las acciones en cascada de una restriccin "foreign key" y las
comprobaciones de restricciones "check" deben realizarse con xito antes de ejecutarse el
trigger. Es la opcin por defecto si solamente colocamos "for" (equivalente a "after").
La sintaxis es:
create triggre NOMBREDISPARADOR
on NOMBRETABLA
after | for-- son equivalentes
ACCION-- insert, update o delete
as
SENTENCIAS
Consideraciones:
- Se pueden crear disparadores "instead of" en vistas y tablas.
- No se puede crear un disparador "instead of" en vistas definidas "with check option".
- No se puede crear un disparador "instead of delete" y "instead of update" sobre tablas que
tengan una "foreign key" que especifique una accin "on delete cascade" y "on update
cascade" respectivamente.
- Los disparadores "after" no pueden definirse sobre vistas.
- No pueden crearse disparadores "after" en vistas ni en tablas temporales; pero pueden
referenciar vistas y tablas temporales.
- Si existen restricciones en la tabla del disparador, se comprueban DESPUES de la
ejecucin del disparador "instead of" y ANTES del disparador "after". Si se infringen las
restricciones, se revierten las acciones del disparador "instead of"; en el caso del disparador
"after", no se ejecuta.
Cuando se elimina una tabla o vista que tiene asociados triggers, todos los triggers
asociados se eliminan automticamente.
En la columna "name" nos muestra las tablas (y dems objetos si hubiese) de las cuales
depende el trigger, es decir, las tablas referenciadas en el mismo; el tipo de objeto en la
columna "type" (en este caso, todas tablas); la columna "update" indica si el objeto es
actualizado o no (note que la tabla "cursos" no se actualiza, solamente se consulta); la
columna "column" muestra el nombre del campo que se referencia.
No aparecen objetos que dependen del trigger porque no existe ningn objeto que lo
referencie.
Tambin podemos ejecutar el mismo procedimiento seguido del nombre de una tabla:
sp_depends inscriptos;
aparecen los objetos que dependen de ella (que la referencian). En este ejemplo: 1 solo
objeto, su nombre y tipo (trigger). No aparecen objetos de los cuales depende porque la
tabla no los tiene.
- Para conocer los disparadores que hay en una tabla especfica y sus acciones respectivas,
podemos ejecutar el procedimiento del sistema "sp_helptrigger" seguido del nombre de la
tabla o vista. Por ejemplo:
sp_helptrigger inscriptos;
trigger_name
trigger_owner isupdate
isdelete
isinsert
isafter isinsteadof
----------------------------------------------------------------------------------------------------------dis_inscriptos_insertar
dbo
0
0
1
0
1
El nombre del trigger, su propietario; en las 3 columnas siguientes indica para qu evento
se ha definido (un valor 1 indica que est definido para tal evento); las 2 ltimas columnas
indican el momento de disparo (un valor 1 se interpreta como verdadero y un 0 como
falso). En el ejemplo, el disparador "dis_inscriptos_insertar" est definido para el evento de
insercin (valor 1 en "isinsert") y es "instead of" (valor 1 en "isinsteadof").
- La tabla del sistema "sysobjects": muestra nombre y varios datos de todos los objetos de
la base de datos actual. La columna "xtype" indica el tipo de objeto. Si es un trigger
muestra "TR".
Si queremos ver el nombre, tipo y fecha de creacin de todos los disparadores, podemos
tipear:
select name,xtype as tipo,crdate as fecha
from sysobjects
where xtype = 'TR';
Se puede cambiar el evento del disparador. Por ejemplo, si cre un disparador para "insert"
y luego se modifica el evento por "update", el disparador se ejecutar cada vez que se
actualice la tabla.
Sintaxis para habilitar (o deshabilitar) todos los disparadores de una tabla especfica:
alter table NOMBRETABLA
ENABLE | DISABLE TRIGGER all;
No podemos revertir la transaccin con "rollback transaction" porque en ese caso TODOS
los registros modificados volveran a los valores anteriores, y lo que necesitamos es que
solamente aquellos que quedaron con valor negativo vuelvan a su valor original.
Tampoco podemos evitar que se actualicen todos los registros porque se actualizan antes
que las acciones del trigger se ejecuten.
Lo que hacemos es, en el cuerpo
COLLATE:
Una clusula que se puede aplicar a una definicin de base de datos o una definicin de
columna para definir el cotejo, o una expresin de cadena de caracteres para aplicar una
conversin de intercalacin.
Syntax Sintaxis
COLLATE {< collation_name > | database_default }
< collation_name > :: =
{ Windows_collation_name } | { SQL_collation_name }
Argumentos
Puede utilizar la clusula COLLATE para convertir una expresin de caracteres en una
intercalacin concreta. You can utilizar la clausula COLLATE prrafo convertir Una
Expresin de CARACTERES en Una intercalacin CONCRETA. Caracteres literales y las
variables se les asigna la intercalacin predeterminada de la base de datos actual. Caracteres
literales y variables las SE LES ASIGNA la intercalacin predeterminada de la Base de
Datos actual. Referencias a las columnas se les asigna la intercalacin de definicin de la
columna. Referencias uno las Columnas SE LES ASIGNA la intercalacin de Definicin de
la Columna. Para la recopilacin de una expresin, vea Prioridad de intercalacin. Para la
Recopilacin de Una Expresin, vea, Prioridad de intercalacin.
La clusula COLLATE slo se puede aplicar para el char, varchar, text, nchar, nvarchar
y ntext tipos de datos.
Las intercalaciones se identifican generalmente por un nombre de intercalacin. The
exception is in Setup where you do not specify a collation name for Windows collations,
but instead specify the collation designator, and then select check boxes to specify binary
sorting or dictionary sorting that is either sensitive or insensitive to either case or accents.
La excepcin es en el programa de instalacin en la que no se especifica un nombre de
intercalacin de las intercalaciones de Windows, sino que especifique el designador de
intercalacin y, a continuacin, seleccione las casillas de verificacin para especificar la
ordenacin binaria o de un orden de diccionario que se sea sensible o insensible a
cualquiera de los casos o los acentos.
Puede ejecutar la funcin del sistema fn_helpcollations para recuperar una lista de todos
los nombres de intercalacin vlidos para intercalaciones de Windows y SQL:
SELECT * FROM :: fn_helpcollations()
Problema:
on es.codcar COLLATE DATABASE_DEFAULT =ce.codcar COLLATE DATABASE_DEFAULT
Conflicto de intercalacin
Ver este mensaje cuando se ejecuta una consulta en SQL Server?
State 9, Line 5
Cannot resolve the collation conflict between
"SQL_Latin1_General_CP1_CI_AS" and "SQL_Latin1_General_Pref_CP1_CI_AS" in
the equal to operation.
La razn es que se est consultando dos bases de datos diferentes, cada una de ellas tiene un
conjunto de intercalacin diferente. You might be comparing columns in a WHERE clause,
JOINing two tables, using results from functions, etc. Es posible que se comparan las
columnas de una clusula WHERE, unir dos tablas, utilizando los resultados de las
funciones, etc
La solucin es aadir un indicador de colacin a su consulta. Let's say you're trying to
update a table A in Database 1 based on the values of a column in table B in Database 2:
Digamos que usted est tratando de actualizar una tabla de una base de datos en una base en
los valores de una columna en el cuadro B de la base de datos 2:
UPDATE A
SET column1 = B.column2
FROM Database2.dbo.B
WHERE guid COLLATE DATABASE_DEFAULT = B.guid COLLATE DATABASE_DEFAULT
CONVERT:
USE pubs
SELECT CONVERT(char(50), title), ytd_sales
FROM titles
WHERE type = 'trad_cook'
06/06/07
20070606
COLLATE
Una clusula que se puede aplicar a una definicin de base de datos o a una
definicin de columna para definir la intercalacin o una expresin de cadena de
caracteres para aplicar a una conversin de intercalacin.
Sintaxis
COLLATE {< collation_name > | database_default}
< collation_name > :: =
{ Windows_collation_name } | { SQL_collation_name }
Argumentos
collation_name
Es el nombre de la intercalacin que se va a aplicar a la expresin, la definicin de
columna o la definicin de base de datos. La intercalacin especificada en
collation_name slo puede ser una Windows_collation_name o una
SQL_collation_name especificada.
Windows_collation_name
Es el nombre de intercalacin de la intercalacin de Windows. Consulte Nombres de
intercalacin de Windows.
SQL_collation_name
Es el nombre de intercalacin de la intercalacin SQL. Consulte Nombres de
intercalacin SQL.
database_default
Hace que la clusula COLLATE herede la intercalacin de la base de datos actual.
Observaciones
La clusula COLLATE se puede especificar en varios niveles, incluidos los
siguientes:
Crear o alterar una base de datos.
Puede utilizar la clusula COLLATE de la instruccin CREATE DATABASE o
de cdigos compatible con el sistema operativo del equipo. Dichas acciones pueden
incluir:
Especificar una intercalacin predeterminada para una base de datos durante su
creacin.
Especificar una intercalacin para una columna durante la creacin o la alteracin
de una tabla.
Cuando se restaura o anexa una base de datos, la intercalacin predeterminada de la
base de datos y la intercalacin de las columnas char, varchar y text o los
parmetros de la base de datos deben ser compatibles con el sistema operativo.
Las traducciones de pginas de cdigos se admiten para los tipos de datos char y
varchar, pero no para el tipo de datos text. Data loss during code page translations is
not reported.
Si la intercalacin especificada o la intercalacin que utiliza el objeto de referencia,
usa una pgina de cdigos que no es compatible con los sistemas operativos
Windows , SQL Server devuelve un error. Para obtener ms informacin, consulte
la seccin Intercalaciones en el captulo Arquitectura de SQL Server de los Libros
en pantalla de SQL Server.
Se tiene que tener cuidado con el manejo de esta propiedad ya que si se requiere
hacer una consulta entre dos tablas y utilizar un dterminado campo y este no
contiene el mismo tipo la consulta marcara un error
Ejemplo: Muestra todas las base de datos con su collate.
SELECT name, collation_name
FROM sys.databases
El collation se especifica a nivel de columna al crear la tabla, para columnas de tipo
caracter. En caso de que no indiques el collation, el collation asignado por defecto es el
especificado al crear la base de datos.
Por lo tanto, an cuando a nivel de base de datos est especificado un collation especfico,
no significa que los datos de tipo caracter en las tablas tengan este collation, y an dentro
de una misma tabla, no necesariamente las columnas de tipo caracter tendrn el mismo.
Para averiguar el collation de una base de datos, consulta la vista de sistema sys.databases:
Cdigo:
SELECT name, collation_name
FROM
sys.databases
Considera que objetos dependientes del esquema de la base de datos (como constraints)
deben ser eliminado antes y recreados despues de ejecutar la sentencia anterior. El efecto de
esta sentencia es que nuevos objetos creados usarn por defecto el collation especificado.
Los objetos existentes no cambian su collation.
Para averiguar el collation de las columnas en una tabla, utiliza el procedimiento sp_help.
Por ejemplo:
Cdigo:
execute sp_help 'dbo.productos'
El collation se cambia columna por columna con alter table alter colum indicando
exactamente las mismas especificaciones de la columna y el nuevo collation. Suponiendo
que exista una columna codigo(char(10) not null) en una tabla productos:
Cdigo:
ALTER
TABLE dbo.productos
ALTER
COLUMN codigo CHAR(10) COLLATE
Sql_Latin1_General_CP1_CI_AS NOT NULL