Texto Referencial SQL Server
Texto Referencial SQL Server
Texto Referencial SQL Server
GESTIÓN 2014
1.1. Introducción
SQL Server 2005 es un sistema gestor de bases de datos relacionales de Microsoft
Corporation orientado a sistemas medianos y grandes aunque también puede rodar en
ordenadores personales. SQL Server Management Studio (SSMS) es la herramienta de
SQL Server que permite definir y gestionar todas las bases de datos almacenadas en el
servidor SQL Server 2005.
En este tema veremos cómo utilizar el SQL Server Management Studio para manejar
las bases de datos del servidor y organizaremos el texto en los siguientes puntos:
Existen diferentes versiones (ediciones) del producto, por lo que es un producto muy
versátil, que puede cumplir con las exigencias de cualquier empresa, puede ser utilizado
para gestionar bases de datos en un PC en modo local a gestionar todo el sistema de
información de grandes empresas pasando por sistemas que requieran menos potencia y
por sistemas móviles.
Para realizar este curso te recomendamos instalar la versión gratuita: Express. Puedes
descargarla desde la página web de Microsoft, desde el enlace para iniciar descarga.
Tan sólo deberemos seguir el asistente. Los puntos más importantes a tener en cuenta
son:
Lo ideal es que en este punto instales el programa, para ir probando lo que vayas
aprendiendo de aquí en adelante.
Las bases de datos de SQL Server 2005 utilizan tres tipos de archivos:
Archivos de registro
Los archivos de registro (archivos de log) almacenan toda la información de registro
que se utiliza para recuperar la base de datos, el también denominado registro de
transacciones. Como mínimo, tiene que haber un archivo de registro por cada base
de datos, aunque puede haber varios. La extensión recomendada para los nombres
de archivos de registro es .ldf.
SQL Server 2005 no exige las extensiones de nombre de archivo .mdf, .ndf y .ldf, pero
estas extensiones ayudan a identificar las distintas clases de archivos y su uso.
Cada base de datos tiene al menos 2 archivos (un archivo de datos principal y un
archivo de registro) y opcionalmente un grupo de archivos.
Las bases de datos de los usuarios se deben crear preferentemente fuera de la carpeta
Bases de datos del sistema
Para crear una nueva base de datos de usuario nos posicionamos sobre la carpeta
Bases de datos y con el botón derecho del ratón desplegamos el menú contextual del
que elegimos la opción Nueva base de datos…
Esta base de datos está asociada a dos archivos físicos, en la parte inferior aparecen
esos archivos. Para facilitarnos la tarea, al teclear el nombre de la bd lógica, se rellenan
automáticamente los nombres de los archivos físicos, el de datos con el mismo nombre y
el del archivo de registro con el mismo nombre seguido de _log. Estos nombres son los
nombres que se asumen por defecto pero los podemos cambiar, posicionando el cursor
en el nombre y cambiándolo.
Para cada archivo físico podemos definir una serie de parámetros como el tipo de
archivo (si es de datos o de transacciones Registro) y su ocupación inicial (Tamaño
inicial).
Si no indicamos ninguna ubicación podemos ver que los guarda en la carpeta del SQL
Server/MSSQL.n/MSSQL/DATA.
n representa un número que puede variar de una instalación a otra.
Estos son los archivos mínimos en los que se almacenará la base de datos, pero como
ya vimos anteriormente se puede almacenar en más archivos, los tenemos que definir
todos en esta ventana a continuación de los dos obligatorios.
La opción Adjuntar sólo se utiliza la primera vez, cuando todavía no tenemos la base
de datos en el disco.
Ésto es así porque SQL Server sigue en marcha, a pesar de que se cierre el gestor.
Ten en cuenta que el servidor de base de datos normalmente se crea para que sirva
información a diferentes programas, por eso sería absurdo que dejara de funcionar
cuando cerramos el programa gestor, que sólo se utiliza para realizar modificaciones
sobre la base.
Para poder realizar acciones sobre la base de datos, ésta debe estar desconectada.
Para ello, desde el SSMS, desplegamos el menú contextual de la base de datos que nos
interese manipular y seleccionaremos la opción Poner fuera de conexión:
Para volver a conectar la base de datos y seguir trabajando con ella, accederemos al
mismo menú contextual pero elegiremos la opción Poner en conexión:
En caso de que tu versión de SQL Server no tenga las opciones Poner en conexión y
Poner fuera de conexión, deberás utilizar la opción Separar... y luego volver a
adjuntarla.
Para crear una nueva tabla primero nos tenemos que posicionar en la base de datos
donde queremos que se almacene la tabla, desplegar el menú contextual y seleccionar la
opción Nueva tabla.
Algunos tipos no necesitan más, como por ejemplo el tipo entero (int), y otros se
pueden completar con una longitud, como los tipos alfanuméricos:
En este ejemplo hemos definido una columna (Codigo) de tipo Entero corto (Smallint),
y una columna (Nombre) que almacenará hasta 20 caracteres alfanuméricos (nchar(20)),
en este caso la longitud la indicamos en la pestaña Propiedades de columna en la
propiedad Longitud.
Las propiedades de la columna pueden variar dependiendo del tipo de datos de la
columna seleccionada, por ejemplo los campos enteros no tienen la propiedad longitud,
ya que el propio tipo define la longitud del campo, en cambio los campos de tipo numeric
o decimal no tiene la propiedad longitud pero sí las propiedades escala y precisión, los
valores que permiten definir el tamaño del campo.
Las columnas de este tipo se utilizan normalmente para numerar las filas de la tabla,
como no habrán dos filas con el mismo valor (el sistema se encarga de incrementar el
valor cada vez que se crea una nueva fila), estos campos se suelen utilizar como claves
primarias.
En SQL Server 2005 no existe el tipo de datos Contador pero se consigue el mismo
funcionamiento asignando a la columna un tipo de datos numérico y definiendo la columna
como columna de identidad.
Aunque este tipo de columnas se utiliza frecuentemente como clave primaria, SQL
Server no le asigna automáticamente esta función, la tenemos que definir nosotros
mismos, pero sí fuerza a que sea una columna sin valores nulos. No se puede definir más
de una columna de identidad por tabla.
Aparecerá una llave a la izquierda del nombre, símbolo de las claves principales:
Para definir una clave primaria compuesta por varias columnas, seleccionamos las
columnas manteniendo pulsada la tecla Ctrl y luego seleccionamos la opción.
Para quitar una clave principal, hacemos lo mismo pero en esta ocasión seleccionamos
la opción Quitar clave principal.
Del mismo modo si queremos eliminar la definición de una columna, nos posicionamos
en la columna a eliminar y seleccionamos la opción Eliminar columna:
Para insertar una nueva fila de datos sólo tenemos que rellenar los campos que
aparecen en esa fila (la del *), al cambiar de fila los datos se guardarán automáticamente
en la tabla a no ser que alguno infrinja alguna regla de integridad, en ese caso SQL Server
nos devuelve un mensaje de error para que corrijamos el dato erróneo, si no lo podemos
corregir entonces sólo podemos deshacer los cambios.
Como ya hemos visto, en una base de datos relacional, las relaciones entre las tablas
se implementan mediante la definición de claves ajenas, que son campos que contienen
valores que señalan a un registro en otra tabla, en esta relación así creada, la tabla
referenciada se considera principal y la que contiene la clave ajena es la subordinada.
Desde el entorno gráfico del SSMS podemos definir claves ajenas entrando en el
diseño de la tabla y desplegando el menú contextual del campo que va a ser clave ajena:
De esta forma hemos definido una relación entre las tablas Facturas y Clientes. Para
ver las relaciones existentes entre las diferentes tablas tenemos los diagramas.
La llave indica la tabla principal (padre) y el símbolo infinito señala la tabla que contiene
la clave ajena.
Hemos aprendido hasta ahora lo básico para poder crear una base de datos y rellenarla
con tablas relacionadas entre sí y con datos, ahora veamos cómo recuperar esos datos.
Para ello debemos abrir la zona de trabajo de tipo Query, abriendo una nueva consulta,
seleccionando previamente el servidor y pulsando el botón de la barra
de botones o si queremos realizar la consulta sobre un servidor con el cual todavía no
hemos establecido conexión, seleccionando de la barra de menús la opción Nuevo >
Consulta de motor de base de datos:
En este último caso nos aparecerá el cuadro de diálogo para establecer la conexión (el
mismo que vimos al principio del tema).
A continuación se abrirá una nueva pestaña donde podremos teclear las sentencias
SQL:
Además aparece una nueva barra de botones que nos permitirá ejecutar los comandos
más útiles del modo query.
Sólo tenemos que teclear la sentencia a ejecutar, por ejemplo empezaremos por crear
la base de datos.
Podemos incluir en una misma consulta varias sentencias SQL, cuando pulsamos
Ejecutar se ejecutarán todas una detrás de otra. Si tenemos varias consultas y sólo
queremos ejecutar una, la seleccionaremos antes de ejecutarla.
Cuando creamos una nueva consulta, ésta actuará sobre la base de datos activa en
ese momento. Por defecto la base de datos activa es la predeterminada (master). Si
queremos que la base de datos activa sea por ejemplo la base de datos ventas, hacemos
clic sobre su nombre en el Explorador de objetos, y ésta pasará a ser la base de datos
activa. Si ahora creamos una nueva consulta, ésta actuará sobre la base de datos ventas.
Si queremos crear una consulta que siempre actúe sobre una determinada base de
datos y no nos queremos preocupar de qué base de datos tenemos activa podemos
añadir al principio de la consulta la instrucción USE nombreBaseDatos; esto hará que
todas las instrucciones que aparezcan después, se ejecuten sobre la base de datos
indicada.
Por ejemplo:
USE ventas;
SELECT * FROM pedidos;
Obtiene todos los datos de la tabla pedidos que se encuentra en la base de datos
ventas.
Si no utilizamos USE y almacenamos la consulta, al abrirla otra vez, cogerá como base de
Color Categoría
Rojo Cadena de caracteres
Verde oscuro Comentario
Negro sobre fondo plateado Comando SQLCMD
Fucsia Función del sistema
Verde Tabla del sistema
Azul Palabra clave
Verde azulado Números de línea o parámetro de plantilla
Rojo oscuro Procedimiento almacenado de SQL
Server
Gris oscuro Operadores
Ahora sólo nos queda aprender a redactar sentencias SQL, cosa que se verá en otro
momento, mientras tanto podemos utilizar el Generador de Consulta que incluye SSMS y
que veremos a continuación en el apartado sobre vistas.
En cada fila de la rejilla se define una columna del resultado o una columna que se
utiliza para obtener el resultado.
En Columna tenemos el nombre de la columna de la se obtienen los datos o la
expresión cuando se trata de una columna calculada.
En Alias escribimos el nombre que tendrá la columna en la vista, también
corresponde con el encabezado de la columna en la rejilla de resultado. Si se deja el
campo en blanco, por defecto se asume el mismo nombre que hay en Columna.
En Tabla tenemos el nombre de la tabla del origen de la consulta a la que pertenece
la Columna, por ejemplo la primera columna del resultado se saca de la columna
Codigo de la tabla LIBROS y se llamará CodLibro. La cuarta columna de la vista
cogerá sus datos de la columna Usuario de la tabla Prestamos y se llamará Usuario
(Alias se ha dejado en blanco por lo que asume el nombre que hay en Columna.
En la columna Resultados indicamos si queremos que la columna se visualice o no,
las columnas con la casilla marcada se visualizan.
Las columnas Criterio de ordenación y Tipo de orden permiten ordenar las filas del
resultado según una o más columnas. Se ordena por las columnas que tienen algo
en Tipo de orden y cuando se ordena por varias columnas Criterio de ordenación
indica que primero se ordena por la columna que lleva el nº 1 y después por la
columna que lleva el nº 2 y así sucesivamente. En el ejemplo las filas del resultado
se ordenarán primero por código de libro y después por código de préstamo, todas
las filas dentro del mismo libro se ordenarán por código de préstamo.
En cada celda indicamos una condición que debe cumplir la columna correspondiente y
se puede combinar varias condiciones mediante O (OR) e Y (AND) según coloquemos las
condiciones en la misma columna o en columnas diferentes. En el ejemplo anterior
tenemos la condición compuesta: ((usuario=1) AND (Dias>5)) OR (Usuario=2).
También podemos Elimnar filas de la rejilla para eliminar columnas del resultado, lo
conseguimos seleccionando la fila haciendo clic sobre su extremo izquierda y cuando
aparece toda la fila remarcada pulsamos Supr o desde el menú contextual de la fila.
Podemos definir consultas más complejas como por ejemplo consultas de resumen,
pulsando sobre el botón Agrupar por de la barra de herramientas, se añade a la rejilla
una nueva columna Agrupar por con las siguientes opciones:
ver estos cambios debemos de ejecutar o Comprobar la sintaxis para que se actualicen
los demás paneles.
Por defecto el generador añade a la consulta una cláusula TOP (100) PERCENT que
indica que se visualizarán el 100% de las filas. Esta cláusula no la hemos definido
nosotros sino que la añade automáticamente el generador.
Una vez tenemos la vista definida la guardamos y podremos hacer con ella casi todo lo
que podemos hacer con una tabla. De hecho si nos fijamos en el Explorador de objetos,
en la carpeta Vistas:
Vemos que la estructura es muy similar a la estructura de una tabla. Y que podemos
modificar su definición y ejecutarla, igual que con las tablas:
Como ejemplos de sistemas gestores de bases de datos que utilizan SQL podemos
citar DB2, SQL Server, Oracle, MySql, Sybase, PostgreSQL o Access.
Ejercer un control sobre los datos tal como la asignación de privilegios de acceso a
los datos (GRANT/REVOKE).
La gestión de transacciones (COMMIT/ROLLBACK).
Una transacción se puede definir como un conjunto de acciones que se tienen que
realizar todas o ninguna para preservar la integridad de la base de datos.
Por ejemplo supongamos que tenemos una base de datos para las reservas de avión.
Cuando un usuario pide reservar una plaza en un determinado vuelo, el sistema tiene que
comprobar que queden plazas libres, si quedan plazas reservará la que quiera el usuario
generando un nuevo billete y marcando la plaza como ocupada. Aquí tenemos un proceso
que consta de dos operaciones de actualización de la base de datos (crear una nueva fila
en la tabla de billetes y actualizar la plaza reservada en el vuelo, poniéndola como
ocupada) estas dos operaciones se tienen que ejecutar o todas o ninguna, si después de
Texto de Referencia: Doc. Lic. Roberta Mallcu 33
BASE DE DATOS I SQL SERVER
crear el billete no se actualiza la plaza porque se cae el sistema, por ejemplo, la base de
datos quedaría en un estado inconsistente ya que la plaza constaría como libre cuando
realmente habría un billete emitido para esta plaza. En este caso el sistema tiene el
mecanismo de transacciones para evitar este error. Las operaciones se incluyen las dos
en una misma transacción y así el sistema sabe que las tiene que ejecutar las dos, si por
lo que sea no se pueden ejecutar las dos, se encarga de deshacer los cambios que se
hubiesen producido para no ejecutar ninguna.
Las instrucciones que gestionan las autorizaciones serán utilizadas normalmente por el
administrador mientras que las otras, referentes a proceso de transacciones serán
utilizadas también por los programadores.
El DML se compone de las instrucciones para el manejo de los datos, para insertar
nuevos datos, modificar datos existentes, para eliminar datos y la más utilizada, para
recuperar datos de la base de datos. Veremos que una sola instrucción de recuperación
de datos es tan potente que permite recuperar datos de varias tablas a la vez, realizar
cálculos sobre estos datos y obtener resúmenes.
El DML interactúa con el nivel externo de la base de datos por lo que sus instrucciones
son muy parecidas, por no decir casi idénticas, de un sistema a otro, el usuario sólo indica
lo que quiere recuperar no cómo se tiene que recuperar, no influye el cómo están
almacenados los datos.
A lo largo del curso se explicarán cada una de las formas de explotación de la base de
datos. Dependiendo de tu perfil profesional (programador o administrador) o de tu interés
personal te resultará más útil un bloque u otro.
TRANSACT-SQL es un lenguaje muy potente que nos permite definir casi cualquier
tarea que queramos efectuar sobre la base de datos. En este tema veremos que
TRANSACT-SQL va más allá de un lenguaje SQL cualquiera ya que incluye
características propias de cualquier lenguaje de programación, características que nos
permiten definir la lógica necesaria para el tratamiento de la información:
TRANSACT-SQL es un lenguaje muy potente que nos permite definir casi cualquier
tarea que queramos efectuar sobre la base de datos. En este tema veremos que
TRANSACT-SQL va más allá de un lenguaje SQL cualquiera ya que incluye
características propias de cualquier lenguaje de programación, características que
nos permiten definir la lógica necesaria para el tratamiento de la información:
Tipos de datos.
Definición de variables.
Estructuras de control de flujo.
Gestión de excepciones.
Funciones predefinidas.
.
Puede ser utilizado como cualquier SQL como lenguaje embebido en aplicaciones
desarrolladas en otros lenguajes de programación como Visual Basic, C, Java, etc. Y por
supuesto los lenguajes incluidos en la plataforma .NET.
Por ejemplo:
Esta instrucción nos permite SELECCIONAR el código y nombre DE los Clientes CUYA
localidad sea Valencia.
Si sabemos algo de inglés nos será más fácil interpretar a la primera lo que quiere decir
la instrucción, y de lo contrario, como el número de palabras que se emplean es muy
reducido, enseguida nos las aprenderemos.
CREATE (Crear)
DROP (Eliminar)
ALTER (Modificar)
Permite crear una base de datos llamada mibase, a continuación escribiremos las
demás cláusulas que completarán la acción, en este caso dónde se almacenará la base
de datos, cuánto ocupará, etc...
Permite crear una nueva tabla llamada mitabla, entre paréntesis completaremos la
acción indicando la definición de las columnas de la tabla.
Por ejemplo:
En esta sentencia nos aparecen dos cláusulas, la cláusula FROM que nos permite
indicar de dónde hay que coger los datos y la cláusula WHERE que permite indicar una
condición de selección.
Otra característica de una sentencia SQL es que acaba con un punto y coma (;)
originalmente éste era obligatorio y servía para indicar el fin de la instrucción, pero ahora
se puede omitir, aunque se recomienda su uso.
O por ejemplo si en una consulta cuyo origen son dos tablas, queremos hacer
referencia a un campo y ese nombre de campo es un nombre de campo en las dos tablas,
pues utilizaremos su nombre cualificado nombretabla.nombrecampo.
El valor NULL.
Puesto que una base de datos es un modelo de una situación del mundo real, ciertos
datos pueden inevitablemente faltar, ser desconocidos o no ser aplicables, esto se debe
de indicar de alguna manera especial para no confundirlo con un valor conocido pero que
sea cero por ejemplo, SQL tiene para tal efecto el valor NULL que indica precisamente la
ausencia de valor.
Por ejemplo: no es lo mismo que el alumno no tenga nota a que tenga la nota cero, esto
afectaría también a todos los cálculos que se pueden realizar sobre la columna nota.
Si queremos utilizar un nombre que no siga estas reglas, normalmente para poder
incluir espacios en blanco, lo tenemos que escribir encerrado entre corchetes [ ] (también
se pueden utilizar las comillas pero recomendamos utilizar los corchetes).
SQL Server proporciona un conjunto de tipos de datos del sistema que define todos los
tipos de datos que pueden utilizarse. También podemos definir nuestros propios tipos de
datos en Transact-SQL o Microsoft .NET Framework.
Para indicar valores negativos y positivos añadimos el prefijo + o - según sea el valor
positivo o negativo. Sin prefijo se entiende que el valor es positivo.
Tipos de operadores:
- Operadores numéricos:
suma +
resta -
multiplicación *
división /
módulo
%
(resto de una división)
AND &
OR |
OR exclusivo ^
- Operadores de comparación:
Igual a =
Mayor que >
Menor que <
Mayor o igual que >=
Menor o igual que <=
Distinto de <>
No es igual a !=
No menor que !<
No mayor que !>
- Operadores lógicos:
Aquí sólo los nombraremos ya que en el tema de consultas simples los veremos en
detalle.
ALL IN
AND LIKE
ANY NOT
BETWEEN OR
EXISTS SOME
Texto de Referencia: Doc. Lic. Roberta Mallcu 39
BASE DE DATOS I SQL SERVER
- Operadores de cadenas:
Concatenación +
Resultados de la expresión
2.8. Funciones
SQL Server 2005 proporciona numerosas funciones integradas y permite crear
funciones definidas por el usuario.
Las variables
En Transact-SQL podemos definir variables, que serán de un tipo de datos
determinado, como tipos de datos podemos utilizar los propios de la base de datos SQL-
SERVER, pero también podemos utilizar tipos propios del lenguaje que no pueden ser
utilizados en DDL. El tipo Cursor y el tipo Table son dos de estos tipos.
El nombre de la variable debe empezar por el símbolo @, este símbolo hace que SQL
interprete el nombre como un nombre de variable y no un nombre de objeto de la base de
datos.
Para asignar un valor a una variable, la asignación se realiza con la palabra SELECT y
el signo igual con el formato:
El valor puede ser cualquier valor constante, otro nombre de variable, una expresión
válida o algo más potente, parte de una sentencia SELECT de SQL.
Por ejemplo:
SELECT @empleados = 0;
/* Esto es un comentario
/* */ Varias líneas en varias líneas */
-- Una única línea -- Esto es un comentario en una única línea.
USE nbBaseDeDatos
Hace que la base de datos activa pase a ser la base de datos indicada en la instrucción,
las consultas que se ejecuten a continuación se harán sobre tablas de esa base de datos
si no se indica lo contrario. Es una instrucción útil para asegurarnos de que la consulta se
ejecuta sobre la base de datos correcta.
GO
después del CREATE DATABASE…; tenemos que poner GO antes del primer CREATE
TABLE para que el sistema efectúe la primera operación y la base de datos esté creada
antes de ejecutar el primer CREATE TABLE.
BEGIN...END
3.1. Introducción
Vamos a empezar por la instrucción que más se utiliza en SQL, la sentencia SELECT.
La sentencia SELECT es, con diferencia, la más compleja y potente de las sentencias
SQL, con ella podemos recuperar datos de una o más tablas, seleccionar ciertos registros
e incluso obtener resúmenes de los datos almacenados en la base de datos. Es tan
compleja que la estudiaremos a lo largo de varias unidades didácticas incorporando poco
a poco nuevas funcionalidades.
El resultado de una SELECT es una tabla lógica que alberga las filas resultantes de la
ejecución de la sentencia.
]
[HAVING < condicion_busqueda > ]
Empezaremos por ver las consultas más simples, basadas en una sola tabla y nos
limitaremos a la siguiente sintaxis:
SELECT [ALL|DISTINCT]
[TOP expresion [PERCENT] [WITH TIES]]
<lista_seleccion>
FROM <origen>
[WHERE <condicion_busqueda> ]
[ORDER BY {expression_columna|posicion_columna [ASC|DESC]} [
,...n ]]
<origen>::=
nb_tabla | nb_vista [[ AS ] alias_tabla ]
Tanto para las tablas como para las vistas, podemos hacer referencia a tablas que
están en otras bases de datos (siempre que tengamos los permisos adecuados), en este
caso tenemos que cualificar el nombre de la tabla, indicando delante el nombre de la base
de datos (Lógica) y el nombre del esquema al que pertenece la tabla dentro de la base de
datos.
Cuando no se definen esquemas, SQL-Server crea uno por defecto en cada base de
datos denominado dbo.
Se utilizan los nombres de alias para simplificar los nombres de tablas a veces largos y
también cuando queremos combinar una tabla consigo misma; ya volveremos sobre los
alias de tabla cuando veamos consultas multitabla.
Podemos escribir:
SELECT ...
FROM tabla1 Sacamos los datos de la tabla tabla1
SELECT ...
FROM tabla1 t1 Sacamos los datos de la tabla tabla1 y le
asignamos un alias de tabla: t1
SELECT ...
FROM tabla1 AS t1 Es equivalente a la sentencia anterior.
Si la tabla o la vista están en otra base de datos del mismo equipo que está ejecutando
la instancia de SQL Server, se utiliza el nombre cualificado con el formato
nbBaseDatos.nbEsquema.nbTabla.
Si la tabla o la vista están fuera del servidor local en un servidor vinculado, se utiliza un
nombre de cuatro partes con el formato nbservidor.catalogo.nbEsquema.nbTabla.
Volveremos más adelante sobre las conexiones remotas.
<lista_seleccion> ::=
{ *
| {nombre_tabla|nombre_vista|alias_tabla}.*
| { [{nombre_tabla|nombre_vista|alias_tabla}.]
{nb_columna|$IDENTITY|$ROWGUID}
|<expresion>
}[[AS] alias_columna]
| alias_columna = <expresion>
} [ ,...n ]
Separamos la definición de cada columna por una coma y las columnas del resultado
aparecerán en el mismo orden que en la lista de selección.
Para cada columna del resultado su tipo de datos, tamaño, precisión y escala son los
mismos que los de la expresión que da origen a esa columna.
El resultado sería:
El resultado sería:
El alias de columna se indica mediante la cláusula AS. Se escribe el nuevo texto tal cual
sin comillas siguiendo las reglas de los identificadores.
Ejemplo:
El resultado será :
Numclie nombrecliente
2101 Luis García Antón
2102 Alvaro Rodríguez
2103 Jaime Llorens
en vez de:
Numclie nombre
2101 Luis García Antón
2102 Alvaro Rodríguez
2103 Jaime Llorens
La palabra AS es opcional.
3.6. Funciones
Existen funciones que podemos utilizar en la lista de selección, e incluso en otras
cláusulas que veremos más adelante, como el WHERE. Las principales funciones son las
siguientes:
Funciones de fecha:
Función Descripción
GETDATE Devuelve la fecha actual.
GETUTCDATE Devuelve la hora UTC.
DATEPART Devuelve un entero que corresponde a la parte de la fecha solicitada.
DAY Devuelve el día de la fecha indicada.
MONTH Devuelve el mes de la fecha indicada.
YEAR Devuelve el año de la fecha indicada.
Devuelve una cadena de caracteres que representa el valor de la
DATENAME
unidad especificada de una fecha especificada.
Devuelve un valor datetime nuevo que resulta de sumar un intervalo
DATEADD
de tiempo a una fecha especificada.>
DATEDIFF Devuelve el nº de intervalos que hay entre dos fechas.
Devuelve el primer día de la semana establecido con SET
@@DATEFIRST
DATEFIRST.
SET DATEFIRST Establece el primer día de la semana en un número del 1 al 7.
Funciones de cadena:
Función Descripción
Otras funciones:
Función Descripción
ROUND Redondea un valor a la longitud y precisión indicadas.
CAST y CONVERT Convierten de un tipo de datos a otro de forma explícita.
CASE Evalúa una lista de condiciones.
ISNULL Reemplaza el valor NULL por otro especificado.
COALESCE Devuelve la primera expresión distinta de NULL entre sus argumentos
La expresión puede contener cualquier operador válido (+, -, *, /, &…), cualquier función
válida, nombres de columnas del origen de datos, nombres de parámetros o constantes y
para combinar varias operaciones se pueden utilizar los paréntesis.
El resultado será:
SELECT idfab,idproducto,descripcion,(existencias*precio) AS
valoracion
FROM productos;
El resultado sería:
FROM empleados;
El resultado será:
Listar las ventas en cada oficina con el formato: 22 tiene ventas de 186,042.00 €
El resultado sería:
oficina ventas
11 tiene ventas de 69300,00
12 tiene ventas de 73500,00
13 tiene ventas de 36800,00
21 tiene ventas de 83600,00
22 tiene ventas de 18600,00
23 tiene ventas de NULL
24 tiene ventas de 15000,00
26 tiene ventas de NULL
28 tiene ventas de 0,00
El incluir una constante como columna en la lista de selección puede parecer inútil (se
repetirá el mismo valor en todas las filas) pero veremos más adelante que tiene utilidad en
ciertos casos.
alias_columna = <expresion>
Ejemplo:
Pág. 3.6
SELECT *
FROM oficinas;
SELECT oficinas.*
FROM oficinas;
Esta forma se utiliza normalmente cuando el origen está basado en varias tablas y
queremos indicar todas las columnas no del origen completo sino de una tabla concreta.
Es equivalente a:
Podemos indicar una columna o varias separadas por una coma, la columna de
ordenación se especifica mediante el nombre de columna en el origen de datos o su
posición dentro de la lista de selección. Si utilizamos el nombre de columna, no hace falta
que la columna aparezca en la lista de selección. Si utilizamos la posición es la posición
de la columna dentro de la lista de selección empezando en 1.
Ejemplos:
Mostrar las ventas de cada oficina, ordenadas por orden alfabético de región y dentro
de cada región por ciudad.
Da como resultado:
Listar las oficinas de manera que las oficinas de mayores ventas aparezcan en primer
lugar.
Resultado:
En este caso hemos utilizado el alias de columna para hacer referencia a la columna
calculada y también se puede observar que las filas aparecen ordenadas por región
ascendente (no hemos incluido nada después del nombre de la columna) y dentro de cada
región por superávit y descendente.
SELECT dir
FROM oficinas;
dir
106
104
105
108
108
108
108
NULL
NULL
Si un mismo empleado dirige varias oficinas (por ejemplo el 108), su código aparece
repetido en el resultado. Para evitarlo modificamos la consulta:
dir
NULL
104
105
106
108
Los que se eliminan son valores duplicados de filas del resultado, por ejemplo:
dir region
NULL este
NULL norte
104 este
105 este
106 este
108 centro
108 oeste
Ahora el 108 aparece dos veces porque las dos filas donde aparece no son iguales
(porque tienen distinta región).
NOTA: La cláusula DISTINCT hace que la consulta tarde algo más en ejecutarse
debido al proceso adicional de buscar y eliminar las repeticiones, por lo que se aconseja
utilizarla únicamente cuando sea imprescindible.
La cláusula TOP indica que en el resultado no deben aparecer todas las filas
resultantes sino un cierto número de registros, las n primeras. Si la consulta incluye la
cláusula ORDER BY, se realiza la ordenación antes de extraer los n primeros registros.
La expresión representa ese número n y debe devolver un número entero sin signo.
Si existen más registros con las mismas ventas que el último valor de la lista, éstos no
saldrán en el resultado de la consulta.
En el ejemplo el registro con cod = 2 no sale en el resultado y tiene las mismas ventas
que cod = 3.
Si queremos que salgan añadimos la cláusula WITH TIES. La cláusula WITH TIES sólo
se puede emplear si la SELECT incluye un ORDER BY, de lo contrario dará error.
Obtenemos:
Se incluyen en el resultado todos los registros que tienen ventas iguales al último
registro.
Otro ejemplo:
Devuelve las 10 peores oficinas en cuanto a ventas: ordenamos las oficinas por ventas
de menor a mayor y sacamos las 10 primeras.
Devuelve:
WHERE <condicion_búsqueda>
<condicion_búsqueda> ::=
{ [NOT]<predicado>
|(<condicion_búsqueda>)
}
[{AND|OR} [NOT] {<predicado>|(<condicion_búsqueda>)}]
[ ...n ]
En el resultado de la consulta sólo aparecerán las filas que cumplan que la condición de
búsqueda sea TRUE, los valores NULL no se incluyen, por lo tanto, en las filas del
resultado. La condición de búsqueda puede ser una condición simple o una condición
compuesta por varias condiciones (predicados) unidas por operadores AND y OR, no hay
límite en cuanto al número de predicados que se pueden incluir. En las condiciones
compuestas se pueden utilizar paréntesis para delimitar predicados y se aconseja su uso
cuando se incluyen operadores AND y OR en la misma condición de búsqueda.
3.14. Predicados
En SQL tenemos 7 tipos de predicados, condiciones básicas de búsqueda:
Comparación estándar
Pertenencia a un intervalo (BETWEEN)
Pertenencia a un conjunto (IN)
Test de valor nulo (IS NULL).
Coincidencia con patrón (LIKE)
Si contiene (CONTAINS)
FREETEXT
Comparación estándar.
Compara el valor de una expresión con el valor de otra. Para la comparación se pueden
emplear = , <> , !=, < , <= , !<, > , >= ,!>
Sintaxis:
Un nombre de columna,
una constante,
una función (inclusive la función CASE),
una variable,
una subconsulta escalar o
cualquier combinación de nombres de columna, constantes y funciones conectados
mediante uno o varios operadores o una subconsulta.
Ejemplo:
Las columnas que aparecen en el WHERE no tienen por qué aparecer en la lista de
selección, esta instrucción es igual de válida:
Texto de Referencia: Doc. Lic. Roberta Mallcu 59
BASE DE DATOS I SQL SERVER
Hallar oficinas cuyas ventas estén por debajo del 80% de su objetivo:
SELECT oficina
FROM oficinas
WHERE ventas < (.8 * objetivo);
SELECT oficina
FROM oficinas
WHERE dir = 108;
Examina si el valor de la expresión de test está en el rango delimitado por los valores
resultantes de expresion1 y expresion2, estos valores no tienen porqué estar ordenados
en ANSI/ISO; expresion1 debe ser menor o igual a expresion2.
Ejemplo:
Para practicar puedes realizar este Ejercicio Pertenencia a un conjunto con IN.
Una condición de búsqueda puede ser TRUE, FALSE o NULL/UNKNOW, este último
caso se produce cuando algún campo que interviene en la condición tiene valor NULL.
A veces es útil comprobar explícitamente los valores NULL en una condición de búsqueda
ya que estas filas puede que queramos darles un tratamiento especial, para ello tenemos
el predicado IS NULL.
Este test produce un valor TRUE o FALSE, por lo que se podrá combinar con otras
condiciones. El valor NULL no es en sí un valor por eso no lo podemos utilizar en una
igualdad.
SELECT numemp,nombre
FROM empleados
WHERE oficina = NULL;
Esta instrucción no da error pero no obtiene lo que en principio parece que quiere
obtener. No obtenemos los empleados cuya oficina sea un valor nulo (es decir los
empleados que no tienen oficina), no obtenemos nada, en cambio los obtendremos
utilizando el test de valor nulo:
Resultado:
Se utiliza cuando queremos comparar el valor de una columna con un patrón en el que
se utilice caracteres comodines.
SELECT numemp,nombre
FROM empleados
WHERE nombre LIKE ‘An%’;
numemp nombre
SELECT numemp,nombre
FROM empleados
WHERE nombre LIKE ‘%z’;
numemp nombre
SELECT numemp,nombre
FROM empleados
WHERE nombre LIKE ‘%on%’;
numemp nombre
SELECT numemp,nombre
FROM empleados
WHERE nombre LIKE '__a%';
numemp nombre
Obtiene los nombres cuya tercera letra sea una a (en el patrón tenemos dos caracteres
subrayado).
SELECT numemp,nombre
FROM empleados
WHERE nombre LIKE '[a-d]%';
Es equivalente a escribir:
SELECT numemp,nombre
FROM empleados
WHERE nombre LIKE '[abcd]%';
SELECT numemp,nombre
FROM empleados
WHERE nombre LIKE '[^abcd]%';
SELECT numemp,nombre
FROM empleados
WHERE nombre LIKE '[^a-d]%';
[ESCAPE 'car_escape']
Por ejemplo queremos buscar los nombres compuestos que incluyen un subrayado. En
este caso tenemos que poner el carácter _ como un carácter normal no como un comodín,
así que lo escribiremos así:
SELECT numemp,nombre
FROM empleados
WHERE nombre LIKE '%[_]%';
O bien,
SELECT numemp,nombre
FROM empleados
WHERE nombre LIKE '%!_%' ESCAPE '!';
Para practicar puedes realizar este Ejercicio Test de correspondencia con LIKE.
Como siempre, se pueden utilizar paréntesis para alterar esta prioridad en una
condición de búsqueda.
Los operadores lógicos pueden devolver tres valores distintos: TRUE, FALSE, NULL
(UNKNOWN).
AND Combina dos condiciones y se evalúa como TRUE cuando ambas condiciones
son TRUE.
Hallar los vendedores que están por debajo de su cuota y tienen ventas inferiores a
30.000.
SELECT nombre
FROM empleados
WHERE ventas < cuota AND ventas < 30000;
Hallar los vendedores que están debajo de su cuota, pero cuyas ventas no sean
inferiores a 150.000.
SELECT nombre
FROM empleados
WHERE ventas < cuota AND ventas < 150000;
SELECT oficina
FROM oficinas
WHERE NOT dir = 108;
SELECT oficina
FROM oficinas
WHERE dir <> 108;
Devuelven:
Texto de Referencia: Doc. Lic. Roberta Mallcu 67
BASE DE DATOS I SQL SERVER
oficina
11
12
13
Las oficinas sin director no aparecen, para que aparezcan deben añadir otro predicado:
oficina dir
11 106
12 104
13 105
26 NULL
28 NULL
Unidad 4.
4.1. Introducción
Hasta ahora hemos visto consultas que obtienen los datos de una sola tabla, en este
tema veremos cómo obtener datos de diferentes tablas.
En esta parte ampliaremos la cláusula FROM y descubriremos nuevas palabras
reservadas (UNION, EXCEPT e INTERSECT) que corresponden a operaciones
relacionales.
Para obtener datos de varias tablas tenemos que combinar estas tablas mediante alguna
operación basada en el álgebra relacional.
El álgebra relacional define una serie de operaciones cuyos operandos son tablas y cuyo
resultado es también una tabla.
Las operaciones de álgebra relacional implementadas en Transact-Sql son:
La unión UNION
La diferencia EXCEPT
La intersección INTERSECT
El producto cartesiano CROSS JOIN
La composición interna INNER JOIN
La composición externa LEFT JOIN, RIGHT JOIN Y FULL JOIN
En todo el tema cuando hablemos de tablas nos referiremos tanto a las tablas que
físicamente están almacenadas en la base de datos como a las tablas temporales y a las
resultantes de una consulta o vista.
La sintaxis es la siguiente:
< consulta > representa la especificación de la consulta que nos devolverá la tabla a
combinar.
Ejemplo: Suponemos que tenemos una tabla Valencia con las nuevas oficinas de
Valencia y otra tabla Madrid con las nuevas oficinas de Madrid y queremos obtener una
tabla con las nuevas oficinas de las dos ciudades:
El resultado sería:
OFI ciudad
11 Valencia
28 Valencia
23 Madrid
OFI ciudad
11 Valencia
23 Madrid
28 Valencia
Ahora las filas aparecen ordenadas por el número de oficina y hemos utilizado el
nombre de columna de la primera consulta.
Cuando aparezcan en el resultado varias filas iguales, el sistema por defecto elimina las
repeticiones.
Si se especifica ALL, el sistema devuelve todas las filas resultante de la unión incluidas las
repetidas
El empleo de ALL también hace que la consulta se ejecute más rápidamente ya que el
sistema no tiene que eliminar las repeticiones.
Se pueden combinar varias tablas con el operador UNION. Por ejemplo supongamos
que tenemos otra tabla Pamplona con las oficinas nuevas de Pamplona:
Otro ejemplo:
Obtener todos los productos cuyo precio exceda de 20 € o que se haya vendido más de
300 euros del producto en algún pedido.
Pág. 4.1
{<consulta>|(<consulta>)}
EXCEPT
{<consulta>|(<consulta>)}
[{EXCEPT {<consulta>|(<consulta>)}}[ ...n ] ]
[ORDER BY {expression_columna|posicion_columna [ASC|DESC]}
[ ,...n ]]
T1 T2
Cod Codigo
1 2
2 3
4 4
5 5
Devuelve:
Cod
1
6
Ejemplo:
Listar los productos que no aparezcan en ningún pedido.
{ <consulta>|(<consulta>)}
INTERSECT
{<especificacion_consulta>|(<especificacion_consulta>)}
[{INTERSECT {<consulta>|(<consulta>)}} [ ...n ] ]
[ORDER BY {expression_columna|posicion_columna [ASC|DESC]}
[ ,...n ]]
Devuelve:
Cod
2
4
5
Ejemplo: Obtener todos los productos que valen más de 20 euros y que además se
haya vendido en un pedido más de 300 euros de ese producto.
La sentencia SELECT permite realizar esta composición, incluyendo dos o más tablas
en la cláusula FROM.
Empezaremos por estudiar la operación a partir de la cual están definidas las demás
operaciones de composición de tabla, el producto cartesiano.
Tabla_origen puede ser un nombre de tabla o de vista o una tabla derivada (resultado
de una SELECT), en este último caso la SELECT tiene que aparecer entre paréntesis y la
tabla derivada debe llevar asociado obligatoriamente un alias de tabla. También puede ser
una composición de tablas.
Se pueden utilizar hasta 256 orígenes de tabla en una instrucción, aunque el límite varía
en función de la memoria disponible y de la complejidad del resto de las expresiones de la
consulta. También se puede especificar una variable table como un origen de tabla.
Ejemplo:
SELECT *
FROM empleados, oficinas;
Si ejecutamos esta consulta veremos que las filas del resultado están formadas por las
columnas de empleados y las columnas de oficinas. En las filas aparece cada empleado
combinado con la primera oficina, luego los mismos empleados combinados con la
segunda oficina y así hasta combinar todos los empleados con todas las oficinas.
Si ejecutamos:
SELECT *
FROM empleados CROSS JOIN oficinas;
Obtenemos lo mismo.
Este tipo de operación no es la que se utiliza más a menudo, lo más frecuente sería
combinar cada empleado con los datos de SU oficina. Lo podríamos obtener añadiendo a
la consulta un WHERE para filtrar los registros correctos:
SELECT *
FROM empleados, oficinas
WHERE empleados.oficina=oficinas.oficina;
Aquí nos ha aparecido la necesidad de cualificar los campos ya que el nombre oficina
es un campo de empleados y de oficinas por lo que si no lo cualificamos, el sistema nos
da error.
Hemos utilizado en la lista de selección *, esto nos recupera todas las columnas de las
dos tablas.
Recupera todas las columnas de empleados y las columnas ciudad y región de oficinas.
También podemos combinar una tabla consigo misma, pero en este caso hay que
definir un alias de tabla, en al menos una, sino el sistema da error ya que no puede
nombrar los campos.
SELECT *
FROM oficinas, oficinas as ofi2;
FROM
<tabla_origen> INNER JOIN <tabla_origen> ON <condicion_combi>
SELECT *
FROM empleados INNER JOIN oficinas
ON empleados.oficina=oficinas.oficina;
SELECT *
FROM pedidos INNER JOIN productos
ON producto = idproducto AND fab = idfab;
Es fácil ver la utilidad de esta instrucción y de hecho se utilizará muy a menudo, pero
hay algún caso que no resuelve. En las consultas anteriores, no aparecen las filas que no
tienen fila correspondiente en la otra tabla.
No aparecen los empleados que no tienen oficina, ni las oficinas que no tienen
empleados, porque para que salga la fila, debe de existir una fila de la otra tabla que
cumpla la condición.
Para resolver este problema debemos utilizar otro tipo de composición, la composición
externa.
Sintaxis
FROM
<tabla_origen> {LEFT|RIGHT|FULL} [OUTER] JOIN <tabla_origen>
ON <condicion_combi>
Obtiene los empleados con su oficina y los empleados (tabla a la izquierda LEFT del
JOIN) que no tienen oficina aparecerán también en el resultado con los campos de la tabla
oficinas rellenados a NULL.
Obtiene los empleados con su oficina y las oficinas (tabla a la derecha RIGHT del JOIN)
que no tienen empleados aparecerán también en el resultado con los campos de la tabla
empleados rellenados a NULL.
Aparecen tanto los empleados sin oficina como las oficinas sin empleados.
NOTA: Cuando necesitamos obtener filas con datos de dos tablas con una condición de
combinación utilizaremos un JOIN, os aconsejo empezar por escribir el JOIN con la
condición que sea necesaria para combinar las filas, y luego plantearos si la composición
debe de ser interna o externa. Para este segundo paso ésta sería la norma a seguir:
Si pueden haber filas de la primera tabla que no estén relacionadas con filas de la
segunda tabla y nos interesa que salgan en el resultado, entonces cambiamos a
LEFT JOIN.
Si pueden haber filas de la segunda tabla que no estén relacionadas con filas de la
primera tabla y nos interesa que salgan en el resultado, entonces cambiamos a
RIGHT JOIN.
Si necesitamos LEFT y RIGHT entonces utilizamos FULL JOIN.
Por ejemplo:
O bien:
Unidad 5.
5.1. Introducción
Una de las funcionalidades de la sentencia SELECT es el permitir obtener resúmenes
de los datos contenidos en las columnas de las tablas.
Para poder llevarlo a cabo la sentencia SELECT consta de una serie de cláusulas
específicas (GROUP BY, HAVING), y Transact-SQL tiene definidas unas funciones para
poder realizar estos cálculos, las funciones de agregado (también llamadas funciones de
columna).
La diferencia entre una consulta de resumen y una consulta de las que hemos visto hasta
ahora es que en las consultas normales las filas del resultado se obtienen directamente de
las filas del origen de datos y cada dato que aparece en el resultado tiene su dato
correspondiente en el origen de la consulta mientras que las filas generadas por las
consultas de resumen no representan datos del origen sino un total calculado sobre estos
datos. Esta diferencia hará que las consultas de resumen tengan algunas limitaciones que
veremos a lo largo del tema.
Un ejemplo sería:
A la izquierda tenemos una consulta simple que nos saca las oficinas con sus ventas
ordenadas por región, y a la derecha una consulta de resumen que obtiene la suma de las
ventas de las oficinas de cada región
Expresion puede ser de cualquier tipo excepto text, image o ntext. No se permite
utilizar funciones de agregado ni subconsultas. El tipo de dato devuelto es int.
Si el número de valores devueltos por expresion es superior a 231-1, COUNT genera un
error, en ese caso hay que utilizar la función COUNT_BIG.
La función cuenta los valores distintos de NULL que hay en la columna. La palabra ALL
indica que se tienen que tomar todos los valores de la columna, mientras que DISTINCT
hace que se consideren todas las repeticiones del mismo valor como uno solo. Estos
parámetros son opcionales, por defecto se considera ALL.
Por ejemplo:
Devuelve 4 porque tenemos cuatro valores distintos, no nulos, en la columna región, los
valores repetidos los considera sólo una vez. Ahora sí nos devuelve cuántas regiones
tenemos en oficinas.
Si utilizamos * en vez de expresión, devuelve el número de filas del origen que nos
quedan después de ejecutar la cláusula WHERE.
Por ejemplo:
Es mejor que:
Las dos nos devuelven el número de empleados que tienen una oficina asignada pero
la primera es mejor porque se calcula más rápidamente.
Devuelve la suma de las ventas de todas las oficinas y de los objetivos de todas las
oficinas, el de mayor importe.
GROUPING (nb_columna)
Es una función de agregado que genera como salida una columna adicional con el valor
1 si la fila se agrega mediante el operador CUBE o ROLLUP, o el valor 0 cuando la fila no
es el resultado de CUBE o ROLLUP.
Nb_columna tiene que ser una de las columnas de agrupación y la cláusula GROUP BY
debe contener el operador CUBE o ROLLUP.
En el siguiente punto, cuando veamos las cláusulas CUBE y ROLLUP quedará más claro.
Muchas veces cuando calculamos resúmenes nos interesan totales parciales, por
ejemplo saber de cada empleado cuánto ha vendido, y cuál ha sido su pedido máximo, de
cada cliente cuándo fue la última vez que nos compró, etc.
En todos estos casos en vez de obtener una fila única de resultados necesitamos una fila
por cada empleado, cliente, etc.
Una consulta con una cláusula GROUP BY agrupa los datos de la tabla origen y
produce una única fila resultado por cada grupo formado. Las columnas indicadas en el
GROUP BY se llaman columnas de agrupación o agrupamiento .
Cuando queremos realizar una agrupación múltiple, por varias columnas, éstas se
indican en la cláusula GROUP BY en el orden de mayor a menor agrupación igual que con
la cláusula ORDER BY.
expresion_agrupacion puede ser una columna o una expresión no agregada que haga
referencia a una columna devuelta por la cláusula FROM. Un alias de columna que esté
definido en la lista de selección no puede utilizarse para especificar una columna de
agrupamiento.
No se pueden utilizar columnas de tipo text, ntext e image en expresion_agrupacion.
Ejemplo:
Resultado:
Hay empleados sin oficinas (con oficina a nulo), estos forman un grupo con el valor
NULL en oficina, en este caso hay dos empleados así.
Ejemplo:
Resultado:
Número Importe
rep clie
de pedidos máximo
211 225,0
101 1
3 0
210
102 2 21,30
6
212
102 1 37,50
0
211
103 2 21,00
1
210 275,0
105 4
3 0
211
105 1 37,45
1
210
106 1 14,58
1
210 313,5
107 1
9 0
212
107 2 24,30
4
211
108 1 29,25
2
211
108 1 71,00
4
211
108 3 14,20
8
Hemos dicho que los resúmenes se calculan sobre todas las filas del origen después de
haber ejecutado el WHERE, pues ALL permite obtener un resumen de las filas que no
cumplen el WHERE.
ALL Incluye todos los grupos y conjuntos de resultados, incluso aquellos en los que no
Texto de Referencia: Doc. Lic. Roberta Mallcu 86
BASE DE DATOS I SQL SERVER
Resultado:
Número Importe
rep clie
de pedidos máximo
210
101 0 NULL
2
210
101 0 NULL
8
211 225,0
101 1
3 0
210
102 2 21,30
6
212
102 1 37,50
0
211
103 2 21,00
1
210 275,0
105 4
3 0
211
105 1 37,45
1
210
106 1 14,58
1
211
106 0 NULL
7
210 313,5
107 1
9 0
212
107 2 24,30
4
211
108 1 29,25
2
211
108 1 71,00
4
211
108 3 14,20
8
Cuál ha sido el efecto de añadir ALL? Se han añadido filas para las filas del origen que
no cumplen la condición del WHERE pero sin que intervengan en el cálculo de las
funciones de agregado.
Por ejemplo el representante 101 tiene pedidos con el cliente 2102 pero estos pedidos no
son del año 1997, por eso aparece la primera fila (no estaba en el resultado de la otra
consulta) pero con 0 y NULL como resultados de las funciones de agregado.
ROLLUP especifica que, además de las filas que normalmente proporciona GROUP
BY, se incluyen filas de resumen en el conjunto de resultados. Los grupos se resumen en
un orden jerárquico, desde el nivel inferior del grupo hasta el superior. La jerarquía del
grupo se determina por el orden en que se especifican las columnas de agrupamiento.
Cambiar el orden de las columnas de agrupamiento puede afectar al número de filas
generadas en el conjunto de resultados.
Por ejemplo:
Resultado:
Número Importe
rep clie
de pedidos máximo
225,0
101 2113 1
0
NUL 225,0
101 1
L 0
102 2106 1 21,30
102 2120 1 37,50
NUL
102 3 37,50
L
103 2111 2 21,00
NUL
103 2 21,00
L
275,0
105 2103 4
0
105 2111 1 37,45
NUL 275,0
105 5
L 0
106 2101 1 14,28
NUL
106 1 14,28
L
313,5
107 2109 1
0
107 2124 2 24,30
NUL 313,5
107 3
L 0
108 2112 1 29,25
CUBE especifica que, además de las filas que normalmente proporciona GROUP BY,
deben incluirse filas de resumen en el conjunto de resultados. Se devuelve una fila de
resumen GROUP BY por cada posible combinación de grupo y subgrupo del conjunto de
resultados. En el resultado se muestra una fila de resumen GROUP BY como NULL, pero
se utiliza para indicar todos los valores.
Por ejemplo:
Resultado:
Número Importe
rep clie
de pedidos máximo
225,0
101 2113 1
0
NUL 225,0
101 1
L 0
102 2106 1 21,30
102 2120 1 37,50
NUL
102 3 37,50
L
103 2111 2 21,00
NUL
103 2 21,00
L
275,0
105 2103 4
0
105 2111 1 37,45
NUL 275,0
105 5
L 0
106 2101 1 14,28
Texto de Referencia: Doc. Lic. Roberta Mallcu 89
BASE DE DATOS I SQL SERVER
NUL
106 1 14,28
L
313,5
107 2109 1
0
107 2124 2 24,30
NUL 313,5
107 3
L 0
108 2112 1 29,25
108 2114 1 71,00
108 2118 3 14,20
NUL
108 5 71,00
L
... ... ... ...
NUL 450,0
NULL 23
L 0
NULL 2101 1 14,58
275,0
NULL 2103 4
0
NULL 2106 2 21,30
NULL 2107 1 6,32
NULL 2108 1 56,25
313,5
NULL 2109 1
0
NULL 2111 3 37,45
450,0
NULL 2112 2
0
225,0
NULL 2113 1
0
NULL 2114 1 71,00
NULL 2118 3 14,20
NULL 2120 1 37,50
NULL 2124 2 24,30
Efecto: Obtenemos además de los resultados obtenidos con ROLLUP (los totales por
cada representante), los totales por el otro criterio (los totales por cada cliente).
El número de filas de resumen del conjunto de resultados se determina mediante el
número de columnas que contiene la cláusula GROUP BY. Cada operando (columna) de
la cláusula GROUP BY se enlaza según el agrupamiento NULL y se aplica el
agrupamiento al resto de los operandos (columnas). CUBE devuelve todas las
combinaciones posibles de grupo y subgrupo.
Tanto si utilizamos CUBE como ROLLUP, nos será útil la función de agregado
GROUPING.
Si cogemos por ejemplo la primera fila remarcada (101 NULL …) el valor NULL, no
sabemos si se refiere a una fila de subtotal o a que el representante 101 ha realizado un
pedido sin número de cliente. Para poder salvar este problema se utiliza la función de
agregado GROUPING.
FROM pedidos
WHERE YEAR(fechapedido) = 1997
GROUP BY rep, clie WITH ROLLUP;
Las filas que corresponden a subtotales aparecen con un 1 y las normales con un cero.
Ahora que estamos más familiarizados con las columnas de agrupamiento debemos
comentar una regla a no olvidar:
HAVING funciona igual que la cláusula WHERE pero en vez de actuar sobre las filas
del origen de datos, actúa sobre las filas del resultado, selecciona grupos de filas por lo
que la condición de búsqueda sufrirá alguna limitación, la misma que para la lista de
selección:
Ejemplo:
Resultado:
13 1
22 1
Esta SELECT es la misma que la del primer ejemplo del apartado sobre la cláusula
GROUP BY, la diferencia es que le hemos añadido la cláusula HAVING, que hace que del
resultado sólo se visualicen los grupos que cumplan la condición. Es decir sólo aparecen
las oficinas que tienen menos de 2 empleados.
Siempre que en una condición de selección haya una función de columna, la condición
deberá incluirse en la cláusula HAVING, además, como HAVING filtra filas del resultado,
sólo puede contener expresiones (nombres de columnas, expresiones, funciones…) que
también pueden aparecer en la lista de selección, por lo que también se aplica la misma
regla a no olvidar:
HAVING SUM(ventas)=10000
Unidad 6.
Las subconsultas (I)
6.1. Introducción
Una subconsulta es una consulta que aparece dentro de otra consulta o subconsultas,
en la lista de selección o en la cláusula WHERE o HAVING, originalmente no se podían
incluir en la lista de selección.
Una subconsulta se denomina también consulta o selección interna, mientras que la
instrucción que contiene la subconsulta es conocida como consulta o selección externa.
Aparece siempre encerrada entre paréntesis y tiene la misma sintaxis que una
sentencia SELECT normal con alguna limitación:
No puede incluir una cláusula COMPUTE o FOR BROWSE y sólo puede incluir una
cláusula ORDER BY cuando se especifica también una cláusula TOP.
Ejemplo de subconsulta: Listar los empleados cuya cuota no supere el importe vendido
por el empleado.
SELECT nombre
FROM empleados
WHERE cuota <= (SELECT SUM(importe)
FROM pedidos
WHERE rep = numemp);
La columna oficina se encuentra en los dos orígenes (oficinas y empleados) pero esta consulta
no dará error (no se nos pedirá cualificar los nombres como pasaría en una composición de
tablas), dentro de la subconsulta se considera oficina el campo de la tabla empleados. Con lo
que compararía la oficina del empleado con la misma oficina del empleado y eso no es lo que
queremos, queremos comparar la oficina del empleado con la oficina de oficinas, lo
escribiremos pues así para forzar a que busque la columna en la tabla oficinas.
Los operadores de comparación sin modificar son los operadores de comparación que
vimos con la cláusula WHERE.
Sintaxis:
En este caso la segunda expresión será una subconsulta, con una sola columna en la lista de
selección y deberá devolver una única fila como mucho.
Ese valor único será el que se compare con el resultado de la primera expresión.
Si la subconsulta no devuelve ninguna fila, la comparación opera como si la segunda expresión
fuese nula.
Si la subconsulta devuelve más de una fila o más de una columna, da error.
Ejemplo:
SELECT nombre
FROM empleados
WHERE cuota <= (SELECT SUM(importe)
FROM pedidos
WHERE rep= numemp);
<expresion> IN subconsulta
Ejemplo:
SELECT *
FROM empleados
WHERE oficina IN (SELECT oficina
FROM oficinas
WHERE region = 'Este');
Por cada empleado se calcula la lista de las oficinas del Este (nº de oficina) y se evalúa si la
oficina del empleado está en esta lista. Obtenemos pues los empleados de oficinas del Este.
José
1987- 20000,0 14300,0
104 Gonzále 33 23 dir ventas 106
05-19 0 0
z
SELECT *
FROM empleados
WHERE oficina IN (SELECT oficina
FROM oficinas
WHERE region=’Otro’);
La lista generada está vacía por lo que la condición IN devuelve FALSE y en este caso
no sale ningún empleado.
SELECT empleados.*
FROM Empleados INNER JOIN oficinas ON empleados.oficina =
oficinas.oficina
WHERE region = 'Este';
SELECT *
FROM empleados
WHERE oficina NOT IN (SELECT oficina
FROM oficinas
WHERE region = 'Este');
Devuelve los empleados cuya oficina no esté en la lista generada por la subconsulta, es
decir empleados que trabajan en oficinas que no son del Este.
* En la consulta anterior no salen los empleados que no tienen oficina ya que para esos
empleados la columna oficina contiene NULL por lo que no se cumple el NOT IN.
* Si la subconsulta no devuelve ninguna fila, la condición se cumplirá para todas las filas
de la consulta externa, en este caso todos los empleados.
* Si la subconsulta devuelve algún valor NULL, la condición NOT IN es NULL lo que nos
puede ocasionar algún problema.
Por ejemplo, queremos obtener las oficinas que no están asignadas a ningún empleado.
SELECT *
FROM Oficinas
WHERE oficina NOT IN (SELECT oficina
FROM empleados);
Esta consulta no devuelve ninguna fila cuando sí debería ya que hay oficinas que nos están
asignadas a ningún empleado. El problema está en que la columna oficina de la tabla
empleados admite nulos por lo que la subconsulta devuelve valores nulos en todos los
empleados que no están asignados a ninguna oficina. Estos valores nulos hacen que no se
cumpla el NOT IN. La solución pasa por eliminar estos valores molestos:
SELECT *
FROM Oficinas
WHERE oficina NOT IN (SELECT oficina
FROM empleados
WHERE oficina IS NOT NULL);
En este caso, como un empleado puede tener varios pedidos hay que añadir DISTINCT
para eliminar las repeticiones de empleados (si un empleado tiene varios pedidos de ACI
aparecería varias veces).
Sin embargo esta sentencia con NOT IN, queremos los empleados que no tienen
pedidos de ACI:
Esta consulta devuelve los empleados que tienen pedidos que no son de ACI, pero un
empleado puede tener pedidos de ACI y otros de otros fabricantes y por estos otros
saldría en el resultado cuando sí tiene pedidos de ACI y no debería salir.
Hay que tener mucho cuidado con este tipo de preguntas.
El test ANY
ANY significa que, para que una fila de la consulta externa satisfaga la condición
especificada, la comparación se debe cumplir para al menos un valor de los devueltos por
la subconsulta.
Por cada fila de la consulta externa se evalúa la comparación con cada uno de los
valores devueltos por la subconsulta y si la comparación es True para alguno de los
valores ANY es verdadero, si la comparación no se cumple con ninguno de los valores de
la consulta, ANY da False a no ser que todos los valores devueltos por la subconsulta
sean nulos en tal caso ANY dará NULL.
Si la subconsulta no devuelve filas ANY da False incluso si expresion es nula.
Ejemplo:
SELECT *
FROM empleados
WHERE cuota > ANY (SELECT cuota
FROM empleados empleados2
WHERE empleados.oficina = empleados2.oficina);
Obtenemos los empleados que tienen una cuota superior a la cuota de alguno de sus
compañeros de oficina, es decir los empleados que no tengan la menor cuota de su
oficina.
El test ALL
SELECT *
FROM empleados
WHERE cuota > ALL (SELECT cuota
FROM empleados empleados2
WHERE empleados.oficina = empleados2.oficina);
En el ejemplo anterior obtenemos los empleados que tengan una cuota superior a todas
las cuotas de la oficina del empleado. Podríamos pensar que obtenemos el empleado de
mayor cuota de su oficina pero no lo es, aquí tenemos un problema, la cuota del empleado
aparece en el resultado de subconsulta por lo tanto > no se cumplirá para todos los
valores y sólo saldrán los empleados que no tengan oficina (para los que la subconsulta
no devuelve filas).
Para salvar el problema tendríamos que quitar del resultado de la subconsulta la cuota
del empleado modificando el WHERE:
De esta forma saldrían los empleados que tienen una cuota mayor que cualquier otro
empleado de su misma oficina.
O bien
Para no considerar los empleados que tengan la misma cuota que el empleado. En este
caso saldrían los empleados con la mayor cuota de sus oficina, pero si dos empleados
tienen la misma cuota superior, saldrían, hecho que no sucedería con la otra versión.
Ejemplo:
SELECT *
FROM empleados
WHERE EXISTS (SELECT *
FROM pedidos
WHERE numemp = rep and fab ='ACI');
Obtenemos los empleados que tengan un pedido del fabricante ACI. Por cada
empleado, se calcula la subconsulta (obteniendo los pedidos de ese empleado y con
fabricante ACI), si existe alguna fila, el empleado sale en el resultado, si no, no sale.
Cuando se utiliza el operador EXISTS es muy importante añadir una referencia externa,
no es obligatorio pero en la mayoría de los casos será necesario. Veámoslo con ese
mismo ejemplo, si quitamos la referencia externa:
SELECT *
FROM empleados
WHERE EXISTS (SELECT *
FROM pedidos
WHERE fab ='ACI');
Sea el empleado que sea, la subconsulta siempre devolverá filas (si existe algún
pedido cuyo fabricante sea ACI) o nunca, indistintamente del empleado que sea, por lo
que se obtendrán todos los empleados o ninguno para que el resultado varíe según las
filas de la consulta externa habrá que incluir una referencia externa.
Otra cosa a tener en cuenta es que la lista de selección de una subconsulta que se
especifica con EXISTS casi siempre consta de un asterisco (*). No hay razón para
enumerar los nombres de las columnas porque no se van a utilizar y supone un trabajo
extra para el sistema.
SELECT *
FROM empleados
WHERE NOT EXISTS (SELECT *
FROM pedidos
WHERE fab ='ACI' AND rep=numemp);
Unidad 7.
Actualización de datos (I)
7.1. Introducción
Hasta ahora hemos trabajado con tablas que tenían datos introducidos y cuando nos ha
hecho falta hemos añadido nuevos datos en las mismas y hemos modificado algún dato
directamente desde el entorno de SSMS, en este tema veremos cómo hacerlo con
instrucciones de Transact-SQL.
Seguimos en el DML porque las instrucciones que veremos actúan sobre los datos de la
base de datos no sobre su definición y tenemos tres tipos de operaciones posibles:
SELECT ...
INTO nb_NuevaTabla
FROM ...
En la nueva tabla las columnas tendrán el mismo tipo y tamaño que las columnas del
resultado de la SELECT, se llamarán con el nombre de alias de la columna o en su
defecto con el nombre de la columna, pero no se transfiere ninguna otra propiedad del
campo o de la tabla como por ejemplo las claves e índices.
<destino> ::=
{
[nbBaseDatos.nbEsquema. | nbEsquema.]nbTablaVista
}
Con esta instrucción podemos insertar una fila de valores determinados o un conjunto
de filas derivadas de otra consulta.
Delante de VALUES, de forma opcional podemos indicar una lista de columnas entre
paréntesis. Las columnas son columnas del destino.
Cuando indicamos nombres de columnas, esas columnas serán las que reciban los
valores a insertar, la asignación de valores se realiza por posición, la primera columna
recibe el primer valor, la segunda columna el segundo, y así sucesivamente.
En la lista, las columnas pueden estar en cualquier orden y también se pueden omitir
algunas columnas.
Una columna que no aparezca en la lista de columnas se rellenará de acuerdo a su
definición:
Cuando no se indica una lista de columnas el sistema asume por defecto todas las
columnas de la tabla y en el mismo orden que aparecen en la definición de la tabla, en
este caso, los valores se tienen que especificar en el mismo orden que las columnas en la
definición de la tabla, y se tiene que especificar un valor por cada columna ya que los
valores se rellenan por posición, la primera columna recibe el primer valor, la segunda
columna el segundo, y así sucesivamente.
Cuando se insertan nuevas filas en una tabla, el sistema comprobará que la nueva fila
no infrinja ninguna regla de integridad, por ejemplo no podremos asignar a una columna
PRIMARY KEY un valor nulo o que ya exista en la tabla, a una columna UNIQUE un valor
que ya exista en la tabla, a una columna NOT NULL un valor NULL, a una clave ajena
(FOREIGN KEY) un valor que no exista en la tabla de referencia.
Ejemplos.
En este caso hemos indicado sólo dos columnas y dos valores, las demás columnas se
rellenan con el valor por defecto si lo tiene (DEFAULT) o con NULL. Si alguna columna no
nombrada no admite nulos ni tiene cláusula DEFAULT definida, la instrucción dará error.
Aquí no hemos indicado una lista de columnas luego los valores se tienen que indicar
en el mismo orden que las columnas dentro de la tabla, si nos equivocamos de orden, el
valor se guardará en una columna errónea (si los tipos son compatibles) o generará un
mensaje de error y la fila no se insertará (si los tipos no son compatibles).
Tabla_derivada es cualquier instrucción SELECT válida que devuelva filas con los datos
que se van a cargar en el destino.
Cada fila devuelta por la SELECT es una lista de valores que se intentará insertar como
con la cláusula VALUES, por lo que las columnas devueltas por la SELECT deberán
cumplir las mismas reglas que los valores de la lista de valores anteriores.
Ejemplo:
En este caso no hemos incluido una lista de columnas, por lo que en la SELECT tenemos
que generar los valores en el mismo orden que en trabajo.
Si hubiesemos escrito:
Hubiese dado error porque la columna col1 es INT y el valor a asignar es texto (el
nombre de la ciudad de la oficina).
En este caso hemos incluido una lista de columnas, la SELECT debe generar los
valores correspondientes, y col3 que no se rellena explícitamente se rellenará con NULL
porque la columna col3 no está definida como columna calculada, ni con DEFAULT, ni
IDENTITY y además admite nulos.
Hace que la nueva fila contenga los valores predeterminados definidos para cada
columna.
Hay que tener en cuenta una serie de aspectos al utilizar esta instrucción:
Puede generar filas duplicadas en la tabla si los valores que se generan son siempre los
mismos.
Si la tabla tiene una clave principal, esta tendrá que estar basada en una columna con la
propiedad IDENTITY para que se generen valores diferentes automáticamente.
Si una columna está definida como NOT NULL tendrá que incluir un DEFAULT o ser una
columna calculada con una expresión compatible.
UPDATE
[ TOP ( expression ) [ PERCENT ] ]
Texto de Referencia: Doc. Lic. Roberta Mallcu 107
BASE DE DATOS I SQL SERVER
<destino>
SET { nbcolumna = { expresion | DEFAULT | NULL }
} [ ,...n ]
[ FROM{ <origen> }]
[ WHERE <condicion> ]
[;]
<destino> ::=
{
[nbBaseDatos.[nbEsquema.]| nbEsquema.]nbTablaVista
}
Por ejemplo:
Actualiza todas las filas de la tabla oficinas dejando el campo ventas con el valor cero.
Si el campo ventas está definido con un valor predeterminado 0, la sentencia anterior
equivale a:
En una misma sentencia podemos actualizar varias columnas, sólo tenemos que indicar
las distintas asignaciones separadas por comas:
Si no queremos actualizar todas las filas de la tabla sino unas cuantas, utilizaremos la
cláusula TOP, o unas determinadas, utilizaremos la cláusula WHERE.
Por ejemplo:
[ WHERE <condicion> ]
Utilizamos la cláusula WHERE para filtrar las filas a actualizar. Se actualizarán todas las
filas que cumplan la condición. Por ejemplo si queremos actualizar sólo las oficinas del
Este:
UPDATE oficinas
SET ventas = 0
WHERE region = 'Este';
Cuando el campo de la otra tabla se utiliza para la cláusula SET, entonces debemos
utilizar la cláusula FROM.
La cláusula FROM permite definir un origen de datos basado en varias tablas, y ese
origen será el utilizado para realizar la actualización.
Por ejemplo queremos actualizar el importe de los pedidos con el precio de la tabla
productos.
Además del permiso de UPDATE, se requieren permisos SELECT para la tabla que se
actualiza si la instrucción UPDATE contiene una cláusula WHERE o en el caso de que el
argumento expression de la cláusula SET utilice una columna de la tabla, y permisos
SELECT para la tabla del origen si utilizamos una cláusula FROM o un WHERE con
subconsulta.
DELETE
[ TOP ( expression ) [ PERCENT ] ] [ FROM ] <destino>
[ FROM <origen>]
[ WHERE < condicion>]
[; ]
<destino> ::=
{
[nbBaseDatos. nbEsquema. | nbEsquema.]nbTablaVista
}
Con esta instrucción podemos eliminar una o varias filas de una tabla.
DELETE oficinas;
Equivalente a:
La cláusula WHERE permite eliminar determinadas filas, indica una condición que
deben cumplir las filas que se eliminan.
Por ejemplo:
DELETE oficinas
WHERE region = ’Este’;
Por ejemplo:
Originalmente sólo se podía indicar una tabla en la cláusula FROM, pero ahora
podemos indicar un origen basado en varias tablas.
Si utilizamos un origen basado en varias tablas, se debe de utilizar una extensión de
TRANSACT-SQL que consiste en escribir dos cláusulas FROM, una indica la tabla de
donde eliminamos las filas y la otra el origen que utilizamos para eliminar.
Este caso se produce cuando las filas a eliminar dependen de un valor que está en otra
tabla. Por ejemplo queremos eliminar los empleados de las oficinas del Este. Como la
región de la oficina no está en empleados, habría que añadir al origen la tabla oficinas
para poder formular la condición del WHERE:
En el origen tenemos las dos tablas y en la primera FROM indicamos de qué tabla
queremos borrar.
Esto se podía haber resuelto, como toda la vida, mediante una subconsulta:
Texto de Referencia: Doc. Lic. Roberta Mallcu 111
BASE DE DATOS I SQL SERVER
Para finalizar no debemos olvidar que para poder ejecutar un DELETE se requieren
permisos DELETE en la tabla de donde vamos a eliminar, y también se requieren los
permisos para utilizar SELECT si la instrucción contiene una cláusula WHERE.
En el ejemplo anterior, si un empleado asignado a una oficina del Este tiene pedidos, no
se podrá eliminar y entonces no se eliminará ningún empleado.
TRUNCATE TABLE
[nbBaseDatos.[nbEsquema.]| nbEsquema.]nbTabla [; ]
Esta sentencia quita todas las filas de una tabla sin registrar las eliminaciones
individuales de filas. Desde un punto de vista funcional, TRUNCATE TABLE es
equivalente a la instrucción DELETE sin una cláusula WHERE; no obstante, TRUNCATE
TABLE es más rápida y utiliza menos recursos de registros de transacciones y de sistema.
Pero no todo son ventajas, no se puede utilizar TRUNCATE TABLE en las siguientes
tablas:
Tablas a las que se hace referencia mediante una restricción FOREIGN KEY (las
tablas que entran como principales en una relación).
Tablas que participan en una vista indizada.
Unidad 8.
Texto de Referencia: Doc. Lic. Roberta Mallcu 113
BASE DE DATOS I SQL SERVER
8.1. Introducción
El DDL (Data Definition Language, o Data Description Language según autores), es la
parte del SQL dedicada a la definición de la base de datos, consta de sentencias para
definir la estructura de la base de datos, permite definir gran parte del nivel interno de la
base de datos. Por este motivo estas sentencias serán utilizadas normalmente por el
administrador de la base de datos.
La definición de la estructura de la base de datos incluye tanto la creación inicial de los
diferentes objetos que formarán la base de datos, como el mantenimiento de esa
estructura. Las sentencias del DDL utilizan unos verbos que se repiten para los distintos
objetos. Por ejemplo para crear un objeto nuevo el verbo será CREATE y a continuación
el tipo de objeto a crear. CREATE DATABASE es la sentencia para crear una base de
datos, CREATE TABLE nos permite crear una nueva tabla, CREATE INDEX crear un
nuevo índice… Para eliminar un objeto utilizaremos el verbo DROP (DROP TABLE, DROP
INDEX…) y para modificar algo de la definición de un objeto ya creado utilizamos el verbo
ALTER (ALTER TABLE, ALTER INDEX…).
Los objetos que veremos en este tema son:
Bases de datos
Tablas
Vistas
Índices
Como ya hemos comentado, las sentencias DDL están más orientadas al administrador
de la base de datos, es el que más las va a utilizar, el programador tiene que conocer
cuestiones relativas a la estructura interna de una base de datos, pero no tiene que ser
experto en ello por lo que el estudio del tema se centrará en las sentencias y sobre todo
en las cláusulas que pensamos pueden ser útiles a un programador y no entraremos en
mucho detalle en cuanto a la estructura física de la base de datos y en la administración
de la misma.
Como ya vimos en el primer tema, las bases de datos de SQL Server 2005 utilizan tres
tipos de archivos:
CREATE DATABASE
[ , <grupo> [ ,...n ] ]
[ LOG ON { < esp_fichero > [ ,...n ] } ]
]
[ COLLATE nbintercalacion]
[ WITH <external_access_option> ]
]
[;]
Con la cláusula ON especificamos los ficheros utilizados para almacenar los archivos
de datos.
[ ON
[ PRIMARY ] [ <esp_fichero> [ ,...n ]
[ , <grupo> [ ,...n ] ]
<esp_fichero> ::=
(
NAME = nbfichero_logico ,
FILENAME = 'nbfichero_fisico'
[ , SIZE = tamaño [ KB | MB | GB | TB ] ]
[ , MAXSIZE = { max_size [ KB | MB | GB | TB ] |
UNLIMITED } ]
[ , FILEGROWTH = incremento_crecimiento [ KB | MB | GB |
TB | % ] ]
)
Cada archivo también puede tener un tamaño máximo especificado con MAXSIZE. Si
no se especifica un tamaño máximo, el archivo puede crecer hasta utilizar todo el espacio
disponible en el disco. Esta característica es especialmente útil cuando SQL Server se
utiliza como una base de datos incrustada en una aplicación para la que el usuario no
dispone fácilmente de acceso a un administrador del sistema. El usuario puede dejar que
los archivos crezcan automáticamente cuando sea necesario y evitar así las tareas
administrativas de supervisar la cantidad de espacio libre en la base de datos y asignar
más espacio manualmente.
<grupo> ::=
{
FILEGROUP nbgrupo [ DEFAULT ]
<esp_fichero> [ ,...n ]
}
Nbgrupo es el nombre del grupo y a continuación indicamos los archivos de datos que
pertenecen a ese grupo, los archivos pertenecientes al grupo se indican con los del grupo
principal.
DEFAULT
Cambia el grupo de archivos predeterminado de la base de datos a Nbgrupo. Sólo un
grupo de archivos de la base de datos puede ser el grupo de archivos predeterminado.
Con la cláusula LOG ON definiremos los archivos utilizados para almacenar el registro
de la base de datos (los archivos de registro).
La sintaxis es la siguiente:
COLLATE <nbintercalacion>
< nbintercalacion >:: =
nbinterWindows_ CaseSensitivity_AccentSensitivity
[ WITH <external_access_option> ]
<external_access_option> ::=
{
DB_CHAINING { ON | OFF }
| TRUSTWORTHY { ON | OFF }
}
Para crear una instantánea de base de datos (copia de sólo lectura de una base de
datos).
Para crear una base de datos protegida mediante contraseña, opción disponible para
SQL Server Mobile (Microsoft SQL Server 2005 Mobile Edition (SQL Server Mobile), antes
denominado Microsoft SQL Server 2000 Windows CE 2.0 (SQL Server CE), es una base
de datos compacta y con una gran variedad de funciones diseñada para admitir una lista
ampliada de dispositivos inteligentes y Tablet PC. Entre los dispositivos inteligentes están
todos los dispositivos que ejecuten Microsoft Windows CE 5.0, Microsoft Mobile
Pocket PC 2003, Microsoft Mobile Version 5.0 Pocket PC o Microsoft Mobile Version 5.0
Smart Phone. Esta compatibilidad adicional con dispositivos permite a los programadores
usar la misma funcionalidad de base de datos en un gran número de dispositivos.)
La base de datos puede ser una base de datos normal o una instantánea de base de
datos.
Para poder ejecutar la sentencia el usuario debe tener permiso de CONTROL y se debe
de ejecutar en un contexto diferente del de la base de datos a eliminar, por ejemplo:
use b1
Texto de Referencia: Doc. Lic. Roberta Mallcu 118
BASE DE DATOS I SQL SERVER
DROP DATABASE b1
Como se ve en la sintaxis podemos eliminar varias bases de datos con una sóla
sentencia DROP DATABASE.
Por ejemplo:
Para poder ejecutar esta sentencia se debe de tener el permiso ALTER en la base de
datos. Esta sentencia se debe ejecutar en el modo de confirmación automática (modo de
administración de transacciones predeterminado) y no se permite en una transacción
explícita o implícita.
Las instantáneas de bases de datos no se pueden modificar, y para modificar las opciones
de base de datos asociadas a la réplica, se utiliza el procedimiento almacenado del
sistema sp_replicationdboption.
Sintaxis:
Con esta sentencia resumida vemos que nos permite cambiar la definición de la base
de datos, nos va a permitir cambiar la definición de los ficheros que conforman la base de
datos, también nos permite cambiar la definición de los grupos, la definición de varias
opciones, el tipo de intercalación e incluso cambiar el nombre de la base de datos (con la
cláusula MODIFY NAME).
Por ejemplo:
Como con la instrucción CREATE DATABASE veremos aquí un resumen de lo que más
le puede interesar a un programador, sin entrar en demasiados detalles de administración.
Como muchas de las palabras ya las hemos explicado con la sentencia CREATE
DATABASE, sólo insistiremos en lo nuevo.
<cambiar_ficheros>::=
{
ADD FILE < esp_fichero > [ ,...n ]
[ TO FILEGROUP { nbgrupo | DEFAULT } ]
| ADD LOG FILE < esp_fichero > [ ,...n ]
| REMOVE FILE nbfichero
| MODIFY FILE < esp_fichero >
}
Con este grupo de opciones podemos cambiar la definición de los archivos de datos de
la base de datos.
ADD FILE permite añadir un nuevo archivo de datos (o varios) si no se añade nada (o TO
FILEGROUP DEFAULT), el archivo se añadirá al grupo principal, si añadimos TO
FILEGROUP nbgrupo, se añadirá el archivo al grupo indicado.
Con ADD LOG FILE podemos añadir un nuevo archivo de registro.
Con REMOVE FILE nbfichero eliminamos el archivo con nombre nbfichero.
Se elimina la definición del archivo lógico (nbfichero) y elimina el archivo físico asociado.
El archivo no se puede quitar a menos que esté vacío.
<esp_fichero>::=
(
NAME = nbarchivo
[ , NEWNAME = nuevo_nbarchivo ]
[ , FILENAME = 'nbarchivo_fisico' ]
[ , SIZE = tamaño [ KB | MB | GB | TB ] ]
[ , MAXSIZE = { tamaño_máximo [ KB | MB | GB | TB ] |
UNLIMITED } ]
[ , FILEGROWTH = incremento [ KB | MB | GB | TB| % ] ]
[ , OFFLINE ]
)
Con FILENAME podemos cambiar el nombre del fichero físico, esto nos permite
también cambiar la ubicación del archivo físico.
Por ejemplo:
La cláusula OFFLINE establece el archivo sin conexión e impide el acceso a todos los
objetos del grupo de archivos. ¡Muy importante!, esta opción sólo se debe de utilizar si el
archivo está dañado y si se puede restaurar. Un archivo establecido en OFFLINE sólo se
puede restablecer con conexión mediante la restauración del archivo a partir de una copia
de seguridad. Para obtener más información acerca de cómo restaurar un solo archivo,
consultar en la ayuda la sentencia RESTORE (Transact-SQL).
UNLIMITED especifica que el tamaño del archivo aumenta hasta que el disco esté
lleno. En SQL Server 2005, un archivo de registro especificado con un aumento ilimitado
tiene un tamaño máximo de 2 TB y un archivo de datos tiene un tamaño máximo de 16
TB.
<cambiar_grupos>::=
{
| ADD FILEGROUP nbgrupo
| REMOVE FILEGROUP nbgrupo
| MODIFY FILEGROUP nbgrupo
{
{ READONLY | READWRITE }
| { READ_ONLY | READ_WRITE }
}
| DEFAULT
Para cambiar este estado, se debe tener acceso exclusivo a la base de datos.
El grupo de archivos principal no puede ser de sólo lectura.
Se puede utilizar indistintamente la palabra clave READONLY o READ_ONLY, pero
READONLY se quitará en una versión futura de Microsoft SQL Server por lo que se
recomienda READ_ONLY.
Para finalizar tenemos el apartado <opciones> que nos permite definir y/o cambiar
muchas opciones de la base de datos. La lista de opciones es muy larga, como podemos
observar a continuación, y no entraremos en detalles.
<opciones>::=
SET
{
{ <optionspec> [ ,...n ] [ WITH <termination> ] }
| ALLOW_SNAPSHOT_ISOLATION {ON | OFF }
| AUTO_SHRINK { ON | OFF }
| AUTO_UPDATE_STATISTICS { ON | OFF }
| AUTO_UPDATE_STATISTICS_ASYNC { ON | OFF }
}
<sql_option> ::=
{
ANSI_NULL_DEFAULT { ON | OFF }
| ANSI_NULLS { ON | OFF }
| ANSI_PADDING { ON | OFF }
| ANSI_WARNINGS { ON | OFF }
| ARITHABORT { ON | OFF }
| CONCAT_NULL_YIELDS_NULL { ON | OFF }
| NUMERIC_ROUNDABORT { ON | OFF }
| QUOTED_IDENTIFIER { ON | OFF }
| RECURSIVE_TRIGGERS { ON | OFF }
}
<recovery_option> ::=
{
RECOVERY { FULL | BULK_LOGGED | SIMPLE }
| TORN_PAGE_DETECTION { ON | OFF }
| PAGE_VERIFY { CHECKSUM | TORN_PAGE_DETECTION | NONE }
}
< database_mirroring_option> ::=
{ <partner_option> | <witness_option> }
<partner_option> ::=
PARTNER { = 'partner_server'
| FAILOVER
| FORCE_SERVICE_ALLOW_DATA_LOSS
| OFF
| RESUME
| SAFETY { FULL | OFF }
| SUSPEND
| REDO_QUEUE ( integer { KB | MB | GB } |
UNLIMITED )
| TIMEOUT integer
}
<witness_option> ::=
WITNESS { = 'witness_server'
| OFF
}
<supplemental_logging_option> ::=
SUPPLEMENTAL_LOGGING { ON | OFF }
<service_broker_option> ::=
{
ENABLE_BROKER
| DISABLE_BROKER
| NEW_BROKER
| ERROR_BROKER_CONVERSATIONS
}
<date_correlation_optimization_option> ::=
{
DATE_CORRELATION_OPTIMIZATION { ON | OFF }
}
<parameterization_option> ::=
{
PARAMETERIZATION { SIMPLE | FORCED }
}
<termination> ::=
{
ROLLBACK AFTER integer [ SECONDS ]
| ROLLBACK IMMEDIATE
| NO_WAIT
}
Se pueden ver más detalles de estas opciones en la ayuda de SQL SERVER buscando
ALTER DABATABASE.
CREATE TABLE
[ nbBaseDatos.[nbEsquema].| nbEsquema.]nbTabla
( { <definicion_columna> | < definicion_colCalc > } [
,...n ]
[ <restriccion_tabla> ] [ ,...n ] )
[ ; ]
Los nombres de columnas deben seguir las reglas de los identificadores y deben ser
únicos en la tabla. nbCol puede contener de 1 a 128 caracteres. nbCol se puede omitir en
las columnas creadas con un tipo de datos timestamp, en tal caso, si no se especifica
nbCol, el nombre de la columna timestamp será de manera predeterminada timestamp.
En cuanto al tipo de dato, esta es la sintaxis:
<tipo_dato> ::=
[nbEsquema_tipo. ] nbtipo
[ nbEsquema_tipo. ] nbtipo
nbtipo Especifica el tipo de datos de la columna y nbEsquema_tipo el esquema al que
pertenece el tipo. El tipo de datos puede ser uno de los siguientes:
Un tipo de datos del sistema de SQL Server 2005 como los que ya conocemos.
Un tipo de alias basado en un tipo de datos del sistema de SQL Server. Los tipos de
datos de alias se crean con la instrucción CREATE TYPE para poder utilizarlos en
una definición de tabla. La asignación NULL o NOT NULL de un tipo de datos de
alias puede anularse durante la instrucción CREATE TABLE. No obstante, la
especificación de longitud no se puede cambiar; la longitud del tipo de datos de alias
no se puede especificar en una instrucción CREATE TABLE.
Un tipo definido por el usuario CLR. Los tipos definidos por el usuario CLR se crean
con la instrucción CREATE TYPE para poder utilizarlos en una definición de tabla.
Max sólo se aplica a los tipos de datos varchar, nvarchar y varbinary para almacenar
231 bytes de datos de caracteres y binarios, y 230 bytes de datos Unicode.
Para obtener más información acerca de los valores de precisión y de escala válidos,
visita el siguiente avanzado.
[ COLLATE nbIntercalacion ]
Con la cláusula COLLATE podemos definir el tipo de intercalación que se utilizará para
la columna (Ver CREATE TABLE).
NOT NULL se puede especificar para las columnas calculadas sólo si se especifica
también PERSISTED.
Con la cláusula DEFAULT podemos especificar un valor por defecto, es decir el valor
que tomará el campo cuando no se haya especificado explícitamente un valor durante la
inserción. Las definiciones DEFAULT se pueden aplicar a cualquier columna excepto a las
definidas como timestamp o a aquellas que tengan la propiedad IDENTITY. Si se
especifica un valor por defecto a una columna de un tipo definido por el usuario, dicho tipo
debe ser compatible con la conversión implícita de exp_constante en el tipo definido por el
usuario. exp_constante sólo puede ser NULL o un valor constante (por ejemplo, una
cadena de caracteres, una función escalar o una función del sistema, definida por el
usuario o CLR).
Para mantener la compatibilidad con las versiones anteriores de SQL Server, se puede
asignar un nombre de restricción a DEFAULT con [ CONSTRAINT nbRestriccion ]. Los
nombres de restricción deben ser únicos en el esquema al que pertenece la tabla.
[ ROWGUIDCOL ]
ROWGUIDCOL indica que la nueva columna es una columna de GUID de filas. Sólo se
puede designar una columna uniqueidentifier por tabla como columna ROWGUIDCOL.
La propiedad ROWGUIDCOL se puede asignar únicamente a una columna
uniqueidentifier.
Las columnas de tipos de datos definidos por el usuario no se pueden designar con
ROWGUIDCOL.
La propiedad ROWGUIDCOL no impone la unicidad de los valores almacenados en la
columna. ROWGUIDCOL tampoco genera automáticamente valores para nuevas filas
insertadas en la tabla, por lo que se debe de utilizar la función NEWID en las instrucciones
INSERT o utilizar la función NEWID como el valor predeterminado de la columna para
generar valores únicos en cada fila.
Para ver más consideraciones sobre columnas IDENTITY y ROWGUIDCOL.
Por último nos quedan las restricciones de clave que aparecen en la sintaxis como:
Texto de Referencia: Doc. Lic. Roberta Mallcu 128
BASE DE DATOS I SQL SERVER
[ <restriccion_columna> [ ...n ] ]
< restriccion_columna > ::=
[ CONSTRAINT nbRestriccion]
{ { PRIMARY KEY | UNIQUE }[ CLUSTERED | NONCLUSTERED ]
[ WITH FILLFACTOR = factorRelleno
| WITH ( < opcion_indice > [ , ...n ] )
]
[ ON { partition_scheme_name ( partition_column_name
)
| filegroup | "default" } ]
| [ FOREIGN KEY ]
REFERENCES [ nbEsquema.] nbTablaPadre [ ( col_padre
) ]
[ ON DELETE { NO ACTION | CASCADE | SET NULL | SET
DEFAULT } ]
}
[ ON UPDATE { NO ACTION | CASCADE | SET NULL | SET
DEFAULT } ]
[ NOT FOR REPLICATION ]
| CHECK [ NOT FOR REPLICATION ] (expresion_validacion)
nbRestriccion es el nombre de la restricción, como hemos visto antes, debe ser único
en el esquema al que pertenece la tabla. Las restricciones se implementan internamente
con índices por lo que a veces podemos utilizar el término índice o restricción
indistintamente.
PRIMARY KEY indica que la columna es la clave principal de la tabla. Sólo se puede
crear una restricción PRIMARY KEY para cada tabla. Si la clave primaria (principal) está
compuesta por varias columnas entonces no podemos utilizar esta restricción, tendremos
que utilizar una restricción de tabla que veremos más adelante.
CLUSTERED indica que el índice que se va a crear es un índice agrupado. Como sólo
puede haber un índice agrupado por tabla, si todavía no hay ninguno definido, por defecto
se creará con la clave primaria, si ya existe un índice agrupado, la clave principal se
creará sin índice agrupado.
Una clave primaria no puede contener valores nulos, por lo que todas las columnas
definidas en una restricción PRIMARY KEY se deben definir como NOT NULL. Si cuando
definimos la columna, no se indica nada, la columna se establecerá a NOT NULL.
Si la clave principal se define en una columna de tipo definido por el usuario CLR, la
implementación del tipo debe admitir el orden binario.
UNIQUE indica que la columna no admite valores duplicados, por lo que se crea un índice
único. Una tabla puede tener varios índices únicos.
Son cláusulas que nos permiten definir con más detalle el índice pero que no veremos
aquí por entrar demasiado en cuestiones internas.
La cláusula CHECK.
Con CHECK indicamos una regla de validación que deberán cumplir todas las filas de la
tabla, es una restricción que exige la integridad del dominio al limitar los valores posibles
que se pueden escribir en la columna.
expression es una expresión lógica que devuelve TRUE o FALSE.
Si queremos definir una restricción CHECK sobre una columna calculada, esta se deberá
definir como PERSISTED.
Una columna puede tener cualquier número de restricciones CHECK y la condición puede
incluir varias expresiones lógicas combinadas con AND y OR. Varias restricciones CHECK
para una columna se validan en el orden en que se crean.
La condición de búsqueda debe evaluarse como una expresión booleana y no puede
hacer referencia a otra tabla.
Una restricción CHECK en el nivel de columna sólo puede hacer referencia a la columna
restringida y una restricción CHECK en el nivel de tabla sólo puede hacer referencia a
columnas de la misma tabla.
Las restricciones CHECK no se pueden definir en las columnas text, ntext o image.
Por ejemplo queremos que la columna Precio de la tabla que estamos definiendo no
pueda contener valores negativos:
…
Precio CURRENCY CONSTRAINT precio_pos CHECK (Precio > = 0)
…
Por último a nivel de columna podemos definir una restricción de clave ajena:
[ FOREIGN KEY ]
REFERENCES [ nbEsquema.] nbTablaPadre [ ( col_padre )
]
[ ON DELETE { NO ACTION | CASCADE | SET NULL | SET
DEFAULT } ]
[ ON UPDATE { NO ACTION | CASCADE | SET NULL | SET
DEFAULT } ]
[ NOT FOR REPLICATION ]
Con esta cláusula definimos una regla de integridad referencial, los valores contenidos
en la columna deberán apuntar a un registro en la tabla de referencia (la tabla padre).
La palabra FOREIGN KEY no es obligatoria cuando estamos a nivel de columna, el
utilizarla o no tiene el mismo efecto.
Nbesquema es el nombre del esquema al que pertenece la tabla padre y nbTablaPadre es
el nombre de la tabla padre.
Indica qué ocurre cuando se intenta eliminar un registro padre en la relación que
estamos definiendo. El valor predeterminado es NO ACTION.
NO ACTION El Motor de base de datos genera un error y no es posible eliminar la fila de
la tabla primaria (el padre).
CASCADE Si se borra una fila de la tabla primaria, se eliminan automáticamente todas
las filas correspondientes de la tabla que estamos definiendo, en otras palabras, si se
elimina un padre, se eliminan todos sus hijos.
SET NULL Si se borra una fila de la tabla primaria, todas las filas correspondientes de la
tabla que estamos definiendo tomarán el valor NULL en el campo clave ajena. En otras
palabras, si se elimina un padre, sus hijos se quedan sin padre.
Para ejecutar esta restricción, la columna clave ajena debe admitir valores NULL.
SET DEFAULT Es como la anterior pero en vez del valor NULL toman el valor que tienen
predeterminado. Si no hay ningún valor predeterminado establecido de forma explícita,
tomarán el valor NULL. Hay que tener en cuenta que el valor predeterminado debe de
existir en la tabla primaria.
….,
Proveedor INTEGER REFERENCES Proveedores ON DELETE NO
ACTION,
…)
Estas dos sentencias son equivalentes e indican que si se intenta borrar de la tabla
Proveedores un proveedor asignado a un artículo, el sistema da un error y no deja
eliminar el proveedor.
….,
Proveedor INTEGER REFERENCES Proveedores ON DELETE CASCADE,
…)
….,
Indica qué ocurre cuando se intenta cambiar un valor del campo relacionado de la tabla
padre en la relación que estamos definiendo. El valor predeterminado es NO ACTION.
….,
Proveedor INTEGER REFERENCES Proveedores ON UPDATE NO
ACTION,
…)
….,
Proveedor INTEGER REFERENCES Proveedores ON UPDATE CASCADE,
…)
….,
Proveedor INTEGER REFERENCES Proveedores ON UPDATE SET
NULL,
…)
Hasta el momento hemos aprendido a definir restricciones sobre una columna, mientras
la estamos definiendo añadimos a su definición la restricción o restricciones que
queramos.
También existen restricciones de tabla, son restricciones que se definen después de
definir todas las columnas de la tabla y que pueden afectar a una o varias columnas de la
tabla. Como veremos la sintaxis para definir una restricción de tabla es muy parecida a la
sintaxis de la misma restricción de columna, lo que varía es que ahora tenemos que
indicar las columnas afectadas por la restricción.
Como las cláusulas son las mismas que para las restricciones de columna, no
repetiremos la explicación de cada cláusula, lo que veremos es un ejemplo y la
explicación de ese ejemplo.
Volviendo al ejemplo anterior de la tabla de Personas, podemos definir la misma
utilizando restricciones de tabla:
codigo int,
dni int,
madre int,
padre int,
dniTutor int,
PRIMARY KEY (codigo),
UNIQUE (dni),
FOREIGN KEY (madre) REFERENCES Personas,
FOREIGN KEY (padre) REFERENCES Personas (codigo),
FOREIGN KEY (dniTutor) REFERENCES Personas (dni));
Utilizando la restricciones de tabla parece que la definición queda más clara, por un
lado tenemos la definición de cada columna, y luego las restricciones.
El Motor de la base de datos entendería que queremos definir dos claves primarias y
eso es imposible. En este caso habría que utilizar una restricción de tabla:
Ocurre lo mismo con las demás restricciones. Imaginemos ahora una tabla de líneas de
pedido en la que tenemos en una línea el producto pedido, y la cantidad pedida.
pedido INT,
nlin INT,
codprod INT,
codprov INT,
cantidad INT,
PRIMARY KEY (pedido, nlin),
FOREIGN KEY (codprod,codprov) REFERENCES Productos,
UNIQUE (pedido,codprod,codprov));
La combinación (codprod,codprov) forma una clave ajena que hace referencia a la tabla
Productos, en este caso como la clave principal de la tabla Productos está compuesta por
los dos campos, la clave ajena tiene que tener el mismo número de campo y del mismo
tipo.
Con la restricción UNIQUE indicamos que la combinación formada por un número de
pedido un código de producto y código de proveedor no se puede repetir, esto hace que
no se puedan insertar en un mismo pedido dos líneas del mismo producto. No se puede
duplicar la combinación pero sí las columnas individualmente (pueden haber varias filas
con el mismo número de pedido, varias filas con el mismo código de producto y varias filas
con el mismo codigo de proveedor.
Una columna calculada es una columna cuyo valor no se introduce, sino que se obtiene
como resultado de un cálculo.
expresion es la expresión que define el valor de una columna calculada y está basada
en otras columnas de la tabla.
Por ejemplo, una columna calculada puede ser definida así:
Una tabla temporal es una tabla creada por un determinado proceso y desaparece
cuando termina éste.
Se pueden crear tablas temporales locales y globales. Las tablas temporales locales son
visibles sólo en la sesión actual y las tablas temporales globales son visibles para todas
las sesiones.
Para indicar que la tabla que queremos crear es temporal añadimos a su nombre el prefijo
# (#nbTabla) para tablas temporales locales y el prefijo ## (##nbTabla) tablas temporales
globales.
Por ejemplo:
Esta instrucción crea una tabla temporal local llamada trabajo con una sola columna.
Las tablas temporales funcionan casi como las tablas normales con algunas diferencias.
nbTabla no puede tener más de 116 caracteres. Esto se debe a que si se crea una
tabla temporal local en un procedimiento almacenado o una aplicación que varios usuarios
pueden ejecutar al mismo tiempo, el Motor de base de datos tiene que ser capaz de
distinguir las tablas creadas por los distintos usuarios, lo consigue añadiendo
internamente un sufijo numérico a cada nombre de tabla temporal local. El nombre
completo de una tabla temporal tal como se almacena en la tabla sysobjects de tempdb
consta del nombre de la tabla especificado en la instrucción CREATE TABLE y el sufijo
numérico generado por el sistema.
Para que las reglas de integridad referencial se cumplan, no se puede eliminar una
tabla señalada por una restricción FOREIGN KEY. Primero se debe quitar la restricción
FOREIGN KEY o la tabla que tiene la clave ajena.
Se pueden quitar varias tablas de cualquier base de datos en una misma sentencia
DROP TABLE. Se irán eliminando en el mismo orden en que aparecen en la lista por lo
que podremos eliminar dos tablas relacionadas con una sola sentencia pero escribiendo la
tabla que contiene la clave ajena primero y después la tabla principal.
Ejemplo:
Elimina la tabla miTabla tanto su definición como los datos, índices definidos sobre ella
y permisos.
Ejemplo:
Para añadir una nueva columna o restricción utilizamos la cláusula ADD seguida de la
definición de lo que queremos añadir, para eso seguimos la misma sintaxis que para
definir las columnas y restricciones de tabla del CREATE TABLE.
Por ejemplo:
Añade una restricción de clave primaria sobre la columna codcli que ya existe en la
tabla.
Para finalizar, las dos últimas cláusulas nos permiten indicar si se tienen que comprobar
o no determinadas restricciones y habilitar y deshabilitar triggers.
CHECK CONSTRAINT ALL activa la comprobación de todas las restricciones definidas
sobre la tabla.
DISABLE TRIGGER ALL deshabilita todos los triggers definidos sobre la tabla.
Cuando deshabilitamos un trigger, éste sigue definido, pero no entra en acción cuando se
produce el evento que debería activarlo. En cualquier momento lo podremos habilitar con
otra instrucción ALTER TABLE.
Para ejecutar CREATE VIEW, se necesita, como mínimo, el permiso CREATE VIEW
en la base de datos y el permiso ALTER en el esquema en el que se está creando la vista.
Sintaxis:
nbVista Es el nombre de la nueva vista. Los nombres de vistas deben seguir las reglas
de los identificadores.
Ejemplos:
Crea una vista con los datos de todos los empleados y de sus oficinas.
En este caso hemos tenido que definir alias de campo porque en el origen de la sentencia
SELECT existe duplicidad de nombres.
Por defecto las columnas de la vista heredan los nombres de las columnas de la
sentencia SELECT asociada, pero podemos cambiar estos nombres indicando una lista
de columnas después del nombre de la vista.
En definitiva se puede optar por utilizar la lista de columnas o definir alias de campo en
la sentencia SELECT.
Las columnas que se vayan a modificar en la vista deben hacer referencia directa a los
datos subyacentes de las columnas de la tabla, es decir que las columnas no se pueden
obtener de otra forma, como con una función de agregado: AVG, COUNT, SUM, MIN,
MAX, GROUPING, STDEV, STDEVP, VAR y VARP, o un cálculo.
Las columnas formadas mediante los operadores de conjunto UNION, UNION ALL,
CROSSJOIN, EXCEPT e INTERSECT equivalen a un cálculo y tampoco son
actualizables.
Las columnas que se van a modificar no se ven afectadas por las cláusulas GROUP
BY, HAVING o DISTINCT.
Para eliminar una vista de una base de datos tenemos la sentencia DROP TABLE.
Sintaxis:
Se eliminan las vista de la base de datos actual. Cuando eliminamos una vista
eliminamos su definición y los permisos asociados a ella.
Se pueden quitar varias vistas en una misma sentencia DROP VIEW escribiendo los
nombres de las vistas a eliminar separados por comas.
Para ejecutar DROP VIEW, como mínimo, se necesita el permiso ALTER en SCHEMA
o el permiso CONTROL en OBJECT.
Ejemplo:
Si eliminamos una tabla mediante DROP TABLE, se deben quitar explícitamente, con
DROP VIEW, las vistas basadas en esta tabla ya que no se quitarán por sí solas.
Un índice simple está definido sobre una sóla columna de la tabla mientras que un
índice compuesto está formado por varias columnas de la misma tabla (tabla sobre la cual
está definido el índice.
Cuando se define un índice sobre una columna, los registros que se recuperen utilizando
el índice aparecerán ordenados por el campo indexado. Si se define un índice compuesto
por las columnas col1 y col2, las filas que se recuperen utilizando dicho índice aparecerán
ordenadas por los valores de col1 y todas las filas que tengan el mismo valor de col1 se
ordenarán a su vez por los valores contenidos en col2, función igual que la cláusula
ORDER BY vista en el tema de consultas simples.
Por ejemplo si definimos un índice compuesto basado en las columnas (provincia,
localidad), las filas que se recuperen utilizando este índice aparecerán ordenadas por
provincia y dentro de la misma provincia por localidad.
Índice único
Índice único es aquel en el que no se permite que dos filas tengan el mismo valor en la
columna de clave del índice. Es decir que no permite valores duplicados.
Inconvenientes
Hay que evitar crear demasiados índices en tablas que se actualizan con mucha
frecuencia y procurar definirlos con el menor número de columnas posible.
Es conveniente utilizar un número mayor de índices para mejorar el rendimiento de
consultas en tablas con pocas necesidades de actualización, pero con grandes
volúmenes de datos. Un gran número de índices contribuye a mejorar el rendimiento
de las consultas que no modifican datos, como las instrucciones SELECT, ya que el
optimizador de consultas dispone de más índices entre los que elegir para
determinar el método de acceso más rápido.
La indización de tablas pequeñas puede no ser una solución óptima, porque puede
provocar que el optimizador de consultas tarde más tiempo en realizar la búsqueda
de los datos a través del índice que en realizar un simple recorrido de la tabla. De
este modo, es posible que los índices de tablas pequeñas no se utilicen nunca; sin
embargo, sigue siendo necesario su mantenimiento a medida que cambian los datos
de la tabla.
Se recomienda utilizar una longitud corta en la clave de los índices agrupados. Los
índices agrupados también mejoran si se crean en columnas únicas o que no
admitan valores NULL.
Un índice único en lugar de un índice no único con la misma combinación de
columnas proporciona información adicional al optimizador de consultas y, por tanto,
resulta más útil.
Hay que tener en cuenta el orden de las columnas si el índice va a contener varias
columnas. La columna que se utiliza en la cláusula WHERE en una condición de
búsqueda igual a (=), mayor que (>), menor que (<) o BETWEEN, o que participa en
una combinación, debe situarse en primer lugar. Las demás columnas deben
ordenarse basándose en su nivel de diferenciación, es decir, de más distintas a
menos distintas.
Ejemplos:
Crea un índice no agrupado sobre las columnas apellidos y nombre de la tabla Clientes
en la base de datos actual, las filas se ordenarán de forma ascendente por apellido y
dentro del mismo apellido por nombre.
Crea un índice no agrupado sobre las columnas edad y apellidos de la tabla Clientes en
la base de datos actual, las filas se ordenarán de forma descendente por edad y
ascendente por apellido. Aparecerán los clientes de mayor a menor edad y los clientes de
la misma edad se ordenarán por apellido (por orden alfabético).
Crea un índice único sobre la columna col de la tabla Clientes en la base de datos
actual, la columna col no podrá contener valores duplicados.
Sintaxis simplificada:
Ejemplo:
Objetivo
Copiar una base de datos que está en uso en un servidor, y adjuntarla o actualizarla en
otro.
1. Sabemos que la base de datos está en los archivos físicos que definimos cuando
definimos la base de datos, estos archivos se localizan en una determina ruta. Esta
información se encuentra en las propiedades de la base de datos, para acceder a la
ventana de propiedades de la base de datos (parecida la que se abrió cuando creamos la
base de datos) utilizamos como siempre el menú contextual que nos llevará a la ventana
Propiedades de la base de datos:
2. Una vez sabemos la ruta, utilizamos el Explorador de Windows para abrir a la carpeta
donde se encuentran los archivos.
Ya tenemos una copia de la base de datos de clase. Ahora vamos a ver cómo incluirla en
el otro ordenador, es decir, en casa.
- En caso de que la base de datos no exista, deberás adjuntarla como ya hemos visto:
Desde el menú contextual de bases de datos y eligiendo la Adjuntar...
- En caso de que la base de datos ya exista y lo que quieras sea actualizarla, deberás:
2. Sobreescribir los archivos físicos por los nuevos que llevas en el pendrive, desde
el Explorador de Windows.