Documentos de Académico
Documentos de Profesional
Documentos de Cultura
1
Visítame en http://siliconproject.com.ar/neckkito/
SQL ORDENADA......................................................................................................................5
PREDICADOS.....................................................................................................................................7
TOP..................................................................................................................................................7
DISTINCT.......................................................................................................................................8
OTRA MANERA DE CONSEGUIR EL MISMO RESULTADO...........................................10
DISTINCTROW............................................................................................................................10
UTILIZACIÓN DE LA CLÁUSULA WHERE.................................................................................11
CARACTERES COMODÍN.........................................................................................................11
OPERADORES.............................................................................................................................12
MARCO SEGÚN EL TIPO DE DATOS.......................................................................................12
CLÁUSULA WHERE, COMODINES Y OPERADORES...........................................................12
EJEMPLOS CON OPERADORES MATEMÁTICOS............................................................13
EJEMPLOS CON OPERADORES DE COMPARACIÓN......................................................14
BETWEEN... AND..............................................................................................................14
IN..........................................................................................................................................14
LIKE.....................................................................................................................................15
EJEMPLOS CON COMPARADORES LÓGICOS..................................................................17
AND.....................................................................................................................................17
OR........................................................................................................................................18
XOR......................................................................................................................................18
IMP / EQV............................................................................................................................19
NOT......................................................................................................................................20
ISNULL / NOT ISNULL.....................................................................................................21
PARA ACABAR ESTE CAPÍTULO.................................................................................................22
2
Visítame en http://siliconproject.com.ar/neckkito/
MAX() / MIN()................................................................................................................10
CONSULTAS ANIDADAS, O SUBCONSULTAS...........................................................................10
UTILIZANDO “IN”......................................................................................................................10
UTILIZANDO “ANY”/”SOME”..................................................................................................12
UTILIZANDO “EXISTS”.............................................................................................................12
COMBINACIÓN DE ELEMENTOS EN SQL..................................................................................13
COMBINACIÓN EXTERNA (O LLÁMAME... “OUTER JOINS”)...........................................13
CORRESPONDENCIA CON LAS CONSULTAS-OBJETO EN ACCESS. TIPOS DE
COMBINACIÓN......................................................................................................................15
COMBINACIÓN INTERNA (O LLÁMAME... “INNER JOIN”)...............................................16
CONSULTA “UNION” / “UNION ALL”.....................................................................................17
CONSULTA “TRANSFORM”......................................................................................................19
AUTOCOMBINACIÓN................................................................................................................21
SELF JOIN....................................................................................................................................22
CLÁUSULA “HAVING”...................................................................................................................24
PARA FINALIZAR ESTE CAPÍTULO.............................................................................................25
3
Visítame en http://siliconproject.com.ar/neckkito/
DEFINIR UNA CLAVE EXTERNA: FOREING KEY.........................................................8
BORRAR UNA TABLA................................................................................................................10
CREAR ÍNDICES (con CREATE INDEX)..................................................................................10
ÍNDICES CON REGISTROS DUPLICADOS.........................................................................11
PROHIBIR VALORES NULOS EN EL ÍNDICE...............................................................12
IGNORAR VALORES NULOS EN EL ÍNDICE................................................................13
ÍNDICE CON REGISTROS NO DUPLICADOS....................................................................14
CREAR UN ÍNDICE CON CLAVE PRIMARIA................................................................15
ELIMINAR ÍNDICES...................................................................................................................15
MODIFICAR UNA TABLA..........................................................................................................15
AÑADIR CAMPOS..................................................................................................................16
BORRAR CAMPOS.................................................................................................................16
CREAR ÍNDICES (con ALTER TABLE)................................................................................17
CREAR UNA CLAVE PRINCIPAL....................................................................................17
CREAR UNA CLAVE EXTERNA......................................................................................17
MODIFICAR EL TIPO DE RELACIÓN........................................................................18
AÑADIR UNA REGLA DE VALIDACIÓN............................................................................20
ELIMINAR ÍNDICES..............................................................................................................20
PARA FINALIZAR EL CAPÍTULO (¡Y EL CURSO!)....................................................................21
4
Visítame en http://siliconproject.com.ar/neckkito/
CURSO DE SQL
CAPÍTULO 11
Índice de contenido
CAPÍTULO 1.......................................................................................................................................1
INTRODUCCIÓN................................................................................................................................2
¿POR QUÉ ESTE CURSO?............................................................................................................2
CONFESIONES ÍNTIMAS.............................................................................................................2
Y EN ESTE PRIMER CAPÍTULO.................................................................................................3
EL LENGUAJE SQL...........................................................................................................................3
RÁPIDAMENTE... ¿QUÉ ES?.......................................................................................................3
TIPOS DE DATOS..........................................................................................................................4
DATOS TIPO TEXTO................................................................................................................4
DATOS TIPO MEMO.................................................................................................................5
DATOS TIPO NÚMERO............................................................................................................6
DATOS TIPO FECHA/HORA....................................................................................................7
DATOS TIPO MONEDA............................................................................................................8
DATOS TIPO AUTONUMÉRICO.............................................................................................8
DATOS SÍ/NO (DATOS BOOLEANOS)...................................................................................8
DATOS OBJETO OLE...............................................................................................................8
DATOS BINARIOS....................................................................................................................9
CUADRO RESUMEN................................................................................................................9
ALGUNOS COMPONENTES DE SQL.......................................................................................10
COMANDOS............................................................................................................................10
CLÁUSULAS...........................................................................................................................11
PREDICADOS..........................................................................................................................11
OPERACIONES.......................................................................................................................11
OPERADORES........................................................................................................................12
FUNCIONES AGREGADAS...................................................................................................12
PREPARACIÓN Y EXPLICACIONES VARIAS PARA SEGUIR EL RESTO DEL CURSO.........13
PARA FINALIZAR ESTE CAPÍTULO.............................................................................................18
1
Visítame en http://siliconproject.com.ar/neckkito/
INTRODUCCIÓN
Entonces se enciende una bombilla en eso que llaman cerebro y pienso: “¿por qué no hacer un
curso para que los sufridos usuarios de Access puedan entender qué están haciendo?”
Y, como diría Aristóteles, de la potencia al acto: de ahí que ahora los “afortunados” tengáis en
vuestras manos este curso (modestia aparte, claro... je, je...).
Como habréis podido intuir, y quienes me conocéis un poco ya habréis adivinado, la idea de
este curso no es meterse a fondo en teoría sobre SQL; mi intención es darle un carácter
práctico, y el objetivo final es que al ver una sentencia SQL sepáis qué está haciendo, además
de poder construiros vosotros mismos vuestras propias instrucciones para “esos códigos que
tan bien funcionan en nuestras BD's”.
Finalmente lo que se explicará en este curso sobre SQL está enfocado, principalmente, a su
funcionamiento con Access. Cierto es que SQL es un lenguaje estándar, pero bueno, digamos
que cada sistema gestor de bases de datos puede tener sus propias particularidades. Sin
embargo, e insisto en ello, el enfoque que se dé será siempre de cara a su desarrollo para
Access.
Doy por supuesto que el lector tiene un cierto control sobre VBA para Access, dado que los
ejemplos van a estar basados prácticamente en este lenguaje de programación. Aunque
intentaré explicar qué estoy haciendo hay cosas que se darán por sabidas. Si tenemos dudas
siempre podemos consultar este fantástico manual sobre VBA para Access (je, je...)
Espero que este curso os sea útil. Y, si encontráis algún error o “desastre”, además de pedir
disculpas por adelantado, os rogaría que me lo comunicarais para poder “enmendar la pifia”.
¡Suerte!
CONFESIONES ÍNTIMAS
No me considero un “monstruo” de SQL. De hecho, a mis efectos, diría que soy un neófito en
esto de SQL. ¿Por qué? Porque Access nos facilita muchísimo el trabajo de construcción de
SQL's que son las que, generalmente, nos funcionan perfectamente en nuestras BD's.
2
Visítame en http://siliconproject.com.ar/neckkito/
Supongo que por esta “falta de necesidad” no se me ha ocurrido profundizar hasta las entrañas
“más oscuras” de SQL. En fin...
Como casi todo en la vida no se puede empezar la casa por el techo. Por ello este primer
capítulo será un poco (mucho) teórico. De hecho, pienso que es mejor un sólo capítulo (este)
fundamentalmente teórico que no teoría por aquí, teoría por allá...
Por eso os pido un poco de paciencia, puesto que es imprescindible sentar las bases de
terminología, conceptos y “otros chascarrillos” antes de meternos de lleno en temas prácticos.
Pero tranquilos, que ya sabéis que a mí me gusta más la práctica que la teoría, por lo que
intentaré ser 3B: bueno, bonito y breve.
En cuanto a la preparación de los datos la idea es crearse una BD de ejemplo y que con ella
seamos capaces de desarrollar todas las diferentes explicaciones que se llevarán a cabo en los
siguientes capítulos. Sé que también es un esfuerzo, pero estoy convencido de que el mismo
tendrá una buena recompensa.
Evidentemente se puede seguir el curso sin realizar la parte práctica, pero si en alguna parte
nos perdemos y no hemos seguido los ejemplos probablemente este esfuerzo que hacemos al
principio lo tengamos que realizar tarde o temprano si queremos entender bien qué estamos
haciendo. En definitiva, que es una decisión personal de cada uno.
Finalmente, recordad que todos los contenidos estarán basados en la aplicación de sentencias
SQL dentro de VB para Access. No debemos perder de vista lo anterior.
EL LENGUAJE SQL
<<El lenguaje de consulta estructurado o SQL (por sus siglas en inglés structured query language) es
2 [http://es.wikipedia.org/wiki/SQL ]. Consulta en línea el 21/04/12
3
Visítame en http://siliconproject.com.ar/neckkito/
un lenguaje declarativo de acceso a bases de datos relacionales que permite especificar diversos tipos de
operaciones en estas. Una de sus características es el manejo del álgebra y el cálculo relacional permitiendo
efectuar consultas con el fin de recuperar -de una forma sencilla- información de interés de una base de
datos, así como también hacer cambios sobre ella.>>
– Un lenguaje de programación...
– para bases de datos relacionales... (¡Caramba!
Access es un GBDR3)
– que a través de unos instrumentos...
– nos permite efectuar consultas...
– para extraer información de la base de datos.
Se utiliza SQL porque es un lenguaje estándar de una gran aceptación y que, salvo honrosas
excepciones, nos permite manipular bases de datos independientemente del sistema gestor. Es
decir, que en principio nos da igual si es Access quien gestiona la BD, SQL-Server, Oracle o
phpMyAdmin, entre otros.
Otra de las ventajas de SQL es su relativa sencillez, de manera que con el conocimiento de
unas pocas palabras “claves” podemos efectuar potentes consultas para conseguir la
información necesaria.
Finalmente, nuestro “querido” VBA acepta la implementación de SQL dentro del código, con lo
que si sabemos programar en VBA y SQL podemos obtener una sinergia importante para una
mejor utilización de nuestra BD.
Como ya comentaba en la introducción, a partir de aquí las referencias que se hagan serán
todas referidas a su utilización en Access y en VBA para Access (insisto en que lo anterior no
excluye su uso, en un alto porcentaje, en otros sistemas de gestión). Veremos cómo
complementar estos dos lenguajes de programación para conseguir las sinergias que
comentábamos antes.
TIPOS DE DATOS
Vamos a partir, para este epígrafe, de lo “conocido” para llegar a lo “desconocido”. Y Access
será nuestra “luz y guía” para ello.
4
Visítame en http://siliconproject.com.ar/neckkito/
Que un dato sea de longitud variable o fija tiene su repercusión en el tamaño de
almacenamiento en bites del dato. Eso quiere decir que:
¿Cómo definimos uno y otro en SQL? Pues utilizando las “palabras reservadas” que tenemos
para ello. Disponemos de varias palabras reservadas en algunos casos (es decir, como si fueran
sinónimos). La siguiente tabla muestra de qué opciones disponemos:
4 Como habréis imaginado esta definición de tipo dato no se puede establecer a través de la interface de Access, sino que debemos
hacerlo a través de una SQL. En capítulos posteriores veremos cómo realizar esta operación.
5
Visítame en http://siliconproject.com.ar/neckkito/
Para definir un campo como memo utilizamos:
VALORES DECIMALES
– Tenemos un tipo de datos, denominados “de coma flotante de precisión simple”, que
abarcan un intervalo de valores positivos y negativos que va desde/hasta:
– Para valores negativos: -3.402823E38 y -1,401298E-45
– Para valores positivos: 1,401298E-45 y 3,402823E38
Es lo que en VB conocemos somo SINGLE
– Tenemos otro tipo de datos, denominados “de coma flotante de precisión doble”, que
6
Visítame en http://siliconproject.com.ar/neckkito/
abarcan un intervalo de valores positivos y negativos que va desde/hasta:
– Para valores negativos: -1,79769313486231E308 y
-4,940656458441247E-324
– Para valores positivos: 4,940656458441247E-324 y
1,79769313486231E308
Es lo que en VB conocemos como DOUBLE
– Tenemos otro tipo de valores, que denominamos “datos
decimales”, en los que no profundizaremos en este capítulo,
debido a sus características “especiales”. Para que nos
entendamos, y por decirlo de alguna manera, a no ser que
desarrollemos una base de datos para la NASA, en la que
necesitemos un factor de precisión decimal altísimo (¡pero
que muy muy alto!), mejor no utilizar este tipo de datos.
creo que “tenemos de sobra”.
Para definir estos tipos de datos en SQL tenemos:
En SQL tendríamos:
7
Visítame en http://siliconproject.com.ar/neckkito/
TIPO DATO VB SQL
Date DATETIME / DATE / TIME / TIMESTAMP
8
Visítame en http://siliconproject.com.ar/neckkito/
No hay una equivalencia exacta en VB para un objeto OLE. Si tuviéramos que almacenarlo
utilizaríamos un tipo VARIANT.
Y para definirlos en SQL tendríamos:
DATOS BINARIOS
Los he dejado para lo último porque este tipo de datos no se
puede definir desde la interfaz de Access (no tenemos la opción al
crear la tabla). ¿Y qué es un dato binario?
Un dato binario no es más que cualquier tipo de dato que se muestra en su formato nativo, sin
sufrir ninguna transformación por parte de Access. En pocas palabras, lo que se escribe es lo
que se muestra.
Hay que decir que los valores binarios son datos de longitud fija (echad un vistazo al apartado
de los datos de texto si no nos acordamos de qué significa “longitud fija”). Cierto es que se
pueden almacenar datos binarios de longitud variable, pero necesitaríamos utilizar ADO para
poder manipular este tipo de datos (no entraremos en esto, de todas maneras).
Para representar estos datos en SQL tenemos:
Binarios BINARY
CUADRO RESUMEN
Después de esta “disertación sobre tipos de datos” probablemente tengamos la cabeza más
que hinchada... Os pongo pues aquí un cuadro resumen con todo lo que acabamos de
comentar:
Texto – Longitud variable (String en VBA) ALPHANUMERIC / STRING / TEXT / TEXT (N) /
VARCHAR
Texto - Memo LONGTEXT / LONGCHAR / MEMO / NOTE
Numérico Byte (Byte en VBA) BYTE / INTEGER1
Numérico entero (Integer en VBA) SMALLINT / SHORT / INTEGER2
Númerico entero largo (Long en VBA) INTEGER / LONG / INT / INTEGER4
Numérico simple (Single en VBA) REAL / SINGLE / FLOAT4 / IEEESINGLE
Numérico doble (Double en VBA) FLOAT / DOUBLE / FLOAT8 / IEEEDOUBLE /
NUMBER
Numérico Id. de réplica GUID
Numérico decimal DECIMAL
Fecha/Hora (Date en VBA) DATETIME / DATE / TIME / TIMESTAMP
Moneda (Currency en VBA) MONEY / CURRENCY
Autonumérico COUNTER / AUTOINCREMENT
9
Visítame en http://siliconproject.com.ar/neckkito/
Sí/No (Boolean en VBA) BIT / LOGICAL / LOGICAL1
COMANDOS
Si partimos de la base que una instrucción la definimos como una expresión de consulta SQL
generada por un comando y sus argumentos o parámetros podremos decir que un comando es
aquella instrucción que se puede ejecutar directamente en una consulta SQL.
En el lenguaje SQL podemos encontrar dos tipos de comandos:
– Los pertenecientes al lenguaje de definición de datos (DDL)
– Los pertenecientes al lenguaje de manipulación de datos (DML)
Los primeros permiten crear y definir tablas, campos, índices, procedimientos almacenados,
vistas, usuarios y grupos de trabajo.
De las anteriores acciones hay algunas que son exclusivas de trabajo en ADO. En este curso no
se van a ver estos comandos.
Los segundos permiten crear consultas para ordenar, filtrar y extraer datos de la BD.
Por ejemplo, entre los primeros tendríamos:
CREATE TABLE
ALTER TABLE
CREATE INDEX
DROP TABLE
DROP INDEX
SELECT
UPDATE
10
Visítame en http://siliconproject.com.ar/neckkito/
INSERT
DELETE
CLÁUSULAS
Podríamos decir que las cláusulas son condiciones que
permiten la modificación la definición de los datos que
vamos a manipular o seleccionar.
Por ejemplo, son cláusulas:
AS
FROM
WHERE
GROUP BY
CONSTRAINT
HAVING
ORDER BY
PROCEDURE
PREDICADOS
Como predicados podríamos entender aquellas expresiones que, de alguna manera, modifican
la acción de los comandos en cuanto al resultado que se va obtener.
Serían predicados:
ALL
DISTINCT
DISTINCTROW
TOP
UNION
OPERACIONES
Mediante las operaciones definimos alguna “operación específica” (valga la redundancia) que
condiciona la ejecución de la SQL y, por extensión, los resultados mostrados.
Serían operaciones:
UNION
INNER JOIN
LEFT JOIN
RIGHT JOIN
11
Visítame en http://siliconproject.com.ar/neckkito/
OPERADORES
Dentro de los operadores podemos encontrar dos tipos:
– Operadores lógicos
– Operadores matemáticos y de comparación
Dentro de los operadores lógicos tendríamos:
AND
OR
XOR
NOT
< >
<= >=
= <>
BETWEEN...AND IN
LIKE
FUNCIONES AGREGADAS
Las funciones agregadas permiten manipular grupos de registros con la finalidad de retornar
un sólo valor, que será el que defina la propia función.
12
Visítame en http://siliconproject.com.ar/neckkito/
PREPARACIÓN Y EXPLICACIONES VARIAS PARA SEGUIR EL
RESTO DEL CURSO
Vamos a desarrollar el curso sobre un ejemplo de una base
de datos5, para poder ver aplicaciones prácticas de las
sentencias SQL.
Los ejemplos de sentencias SQL los vamos a ver
incardinados dentro de código VBA, de manera que, en la
mayoría de casos, no tendremos una SQL “directa”, sino
que la pasaremos por una variable, a los simples efectos de
poder ver con mayor claridad las diferentes estructuras de
las SQL.
Las consultas de acción no tienen mayor problema, en este aspecto, porque las vamos a
ejecutar y vamos a poder ver los resultados de manera directa o indirecta; para las consultas
de selección, sin embargo, no podemos apreciar directamente sus resultados. Para poder
verlos tendremos que convertir nuestra SQL en un objeto-consulta de Access, y ello nos
obligará a seguir la siguiente estructura en los códigos:
– Borramos el objeto-consulta por si existiera (si ya existe obtendríamos un error de
código)
– Creamos la SQL
– La convertimos en un objeto-consulta, para poder ver los resultados.
Para poder realizar lo anterior utilizaremos un módulo, que nos ejecutará el primer y el tercer
paso, dejando el segundo en el código del botón que programemos (las programaremos a
través de clicks de botón porque considero que es un proceso muy sencillo), lo cual nos
permitirá centrarnos en esta segunda parte, esto es, en la SQL propiamente dicha.
Para hacer lo anterior vamos a seguir estos pasos:
1.- Creamos una BD en blanco, y sacamos el editor de VB (ALT+F11)
2.- Insertamos un módulo (VBE menú → Insertar → Módulo)
3.- Guardamos ese módulo con el nombre de mdlProcesos
4.- En ese módulo escribimos los siguientes procedimientos6:
…
Public Sub eliminaConsulta(nomConsulta As String)
Dim qry As Object
For Each qry In CurrentData.AllQueries
If qry.Name = nomConsulta Then
DoCmd.DeleteObject acQuery, qry.Name
Exit For
End If
Next
End Sub
…
Public Sub creaConsulta(nomConsulta As String, laSql As String)
13
Visítame en http://siliconproject.com.ar/neckkito/
Dim qryDef As DAO.QueryDef
Set qryDef = CurrentDb.CreateQueryDef(nomConsulta)
qryDef.SQL = laSql
End Sub
…
Vamos a seguir con nuestra BD. Vamos a crearnos una
tabla donde introduciremos los datos personales de los
trabajadores. A esta tabla la llamaremos TTrabPersonal. Le
daremos la siguiente estructura:
A continuación nos crearemos una segunda tabla, con los datos laborales de los trabajadores,
y la llamaremos TTrabLaboral, y tendrá la siguiente estructura:
Debemos tener en cuenta que el campo [IdTrab] lo hemos definido a través de un asistente
para búsquedas, que nos ha buscado, en la tabla TTrabPersonal, sus tres primeros campos en
este orden: [Id], [ApellTrab] y [NomTrab]; hemos ordenado por apellidos ascendente,
ocultando la clave principal.
Es decir, que aunque este campo nos muestre apellidos-nombre el valor que almacena es el
código del trabajador.
El mismo proceso se ha seguido para el campo [DependeDe]
Vamos a crearnos una tabla con los datos de los clientes de la empresa, que llamaremos
TClientes. Tendrá la siguiente estructura:
14
Visítame en http://siliconproject.com.ar/neckkito/
Ahora vamos a crear una tabla de ventas donde reflejaremos las
ventas realizadas a los clientes. La llamaremos TVentas, y tendrá
la siguiente estructura:
Teniendo en cuenta que para el campo [IdCliVta] hemos utilizado el asistente para búsquedas,
que ha buscado en la tabla TClientes el nombre del cliente. Es decir, nos muestra el nombre del
cliente, pero almacena su código.
Si hemos realizado correctamente los pasos anteriores la ventana de relaciones nos debería
haber quedado así:
Vamos a crearnos seguidamente una tabla auxiliar, que llamaremos TMeses, que tendrá la
siguiente estructura (no vamos a poner ningún campo como clave principal):
15
Visítame en http://siliconproject.com.ar/neckkito/
Finalmente crearemos una tabla muy simple, cuya idea es que nos recoja el usuario que está
operando en ese momento en la BD. Esta BD tendrá siempre un solo registro (el nombre del
usuario activo), que llamaremos TUsuarioAct, y la construiremos con esta simple estructura:
Ya tenemos las estructuras de las tablas preparadas. Ahora sólo hay que introducir datos.
Evidentemente podéis dar de alta los datos que queráis, pero como yo voy a mostrar los
resultados en base a la información que haya en estas tablas o bien os bajáis la BD de ejemplo
y anexáis los datos a vuestras tablas o bien operáis directamente con la BD de ejemplo...
Como siempre, a gusto del consumidor.
Yo os indico los registros que he dado de alta:
Para la tabla TClientes:
16
Visítame en http://siliconproject.com.ar/neckkito/
Para la tabla TTrabLaboral
17
Visítame en http://siliconproject.com.ar/neckkito/
escrito:
Creo que este capítulo ha sido interesante: hemos cogido dolor de cabeza al leer tanta teoría y
hemos cogido dolor de dedos al tener que prepararnos tantas tablas con datos. Como reza el
dicho: “Para lucir hay que sufrir”... je, je...
Sinceramente creo que era necesario realizar este esfuerzo inicial. En los próximos capítulos
veremos cómo sacar rendimiento a tantos “desvelos”.
Un saludo, y...
¡Suerte!
18
Visítame en http://siliconproject.com.ar/neckkito/
CURSO DE SQL
CAPÍTULO 21
Índice de contenido
INTRODUCCIÓN................................................................................................................................2
MANOS A LA OBRA.....................................................................................................................2
PRIMERA INCURSIÓN: CONSULTAS DE SELECCIÓN...............................................................2
UN INCISO SOBRE LA LLAMADA A LOS CAMPOS...............................................................2
SELECCIÓN DE TODOS LOS CAMPOS DE UNA TABLA.......................................................3
SELECCIÓN DE CAMPOS DE VARIAS TABLAS NO RELACIONADAS...............................3
ORDENANDO NUESTROS RESULTADOS................................................................................3
PRACTIQUEMOS CON UN EJEMPLO............................................................................................4
SQL SIMPLE..............................................................................................................................4
SQL “COMPUESTA”.................................................................................................................5
SQL ORDENADA......................................................................................................................5
PREDICADOS.....................................................................................................................................7
TOP..................................................................................................................................................7
DISTINCT.......................................................................................................................................8
OTRA MANERA DE CONSEGUIR EL MISMO RESULTADO...........................................10
DISTINCTROW............................................................................................................................10
UTILIZACIÓN DE LA CLÁUSULA WHERE.................................................................................11
CARACTERES COMODÍN.........................................................................................................11
OPERADORES.............................................................................................................................12
MARCO SEGÚN EL TIPO DE DATOS.......................................................................................12
CLÁUSULA WHERE, COMODINES Y OPERADORES...........................................................12
EJEMPLOS CON OPERADORES MATEMÁTICOS............................................................13
EJEMPLOS CON OPERADORES DE COMPARACIÓN......................................................14
BETWEEN... AND..............................................................................................................14
IN..........................................................................................................................................14
LIKE.....................................................................................................................................15
EJEMPLOS CON COMPARADORES LÓGICOS..................................................................17
AND.....................................................................................................................................17
OR........................................................................................................................................18
XOR......................................................................................................................................18
IMP / EQV............................................................................................................................19
NOT......................................................................................................................................20
ISNULL / NOT ISNULL.....................................................................................................21
PARA ACABAR ESTE CAPÍTULO.................................................................................................22
1
Visítame en http://siliconproject.com.ar/neckkito/
INTRODUCCIÓN
MANOS A LA OBRA
La BD que utilizaremos de ejemplo para ir desarrollando este capítulo fue la que construimos
(o nos bajamos) en el capítulo 1. De todas maneras ya habréis visto en la nota a pie de página
anterior que os podéis bajar la BD con los ejemplos desarrollados de este capítulo, por si
queréis usarla como “consulta” o “guía”.
Y dicho lo anterior no perdamos más tiempo con discursos y entremos de lleno ya en materia.
Si estamos trabajando sobre una sola tabla las estructuras anteriores nos funcionarán
perfectamente, pero si tenemos dos o más tablas la cosa se complica un poco.
Personalmente soy de la opinión que, por facilidad de lectura de código, es mejor indicar la
tabla de origen del campo, aunque la consulta sea del tipo más simple. Con ello conseguimos,
además, optimizar el rendimiento de la SQL. Evidentemente esto es una opinión “personal” y
no hay porque seguirla obligatoriamente.
Para indicar la tabla de origen debemos separar con un punto la tabla del campo. De esta
manera, nuestra estructura anterior quedaría de la siguiente manera:
2
Visítame en http://siliconproject.com.ar/neckkito/
SELECCIÓN DE TODOS LOS CAMPOS DE UNA TABLA
o también
Como podemos observar, hemos separado utilizando comas (,) tanto los campos que
queremos como las tablas que queremos.
Evidentemente, si queremos ordenar por dos campos, nuestra sentencia quedaría así:
Lo anterior nos da una ordenación ascendente (de la A a la Z). ¿Qué ocurre si queremos una
ordenación descendente?
3
Visítame en http://siliconproject.com.ar/neckkito/
PRACTIQUEMOS CON UN EJEMPLO
Para que “quede constancia” de nuestros esfuerzos vamos a
creamos un formulario en blanco, al que llamaremos
FConsultasSQL, y que nos servirá para meter los botones
para practicar los distintos tipos de SQL que hemos visto
hasta ahora. Recordad que los códigos para las consultas de
selección, para que podamos ver los resultados, tendrán la
siguiente estructura:
SQL SIMPLE
Insertamos un botón de comando, al que llamaremos cmdSimpleSobreClientes. Lo que vamos
a hacer es extraer toda la información de la tabla TClientes. El código que debemos generar al
botón en el evento “Al hacer click” es el siguiente:
…
Private Sub cmdSimpleSobreClientes_Click()
'Definimos las variables
Dim miSql As String, nomQuery As String
'Indicamos qué nombre va a tener la consulta
nomQuery = "CClientes"
'La borramos si ya existe a través del código del módulo mdlProcesos
Call eliminaConsulta(nomQuery)
Si queremos podemos cambiar el asterisco por “ALL *”, y comprobaremos que los resultados
son los mismos.
Para abundar más en el tema vamos a realizar una consulta que nos dé el nombre del cliente y
su población. Para ello creamos un nuevo botón de comando, lo llamamos cmdNomyPoblCli y
le generamos el siguiente código (os recomiendo que intentéis crearla vosotros antes de echar
un vistazo al código):
…
Private Sub cmdNomyPoblCli_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CNombreYPoblacionClientes"
Call eliminaConsulta(nomQuery)
4
Visítame en http://siliconproject.com.ar/neckkito/
Call creaConsulta(nomQuery, miSql)
DoCmd.OpenQuery nomQuery
End Sub
…
SQL “COMPUESTA”
Vamos a imaginarnos que necesitamos crear una consulta
como la anterior, pero que necesitamos, en cada registro,
que nos aparezca el nombre del usuario activo.
…
Private Sub cmdClientesYUser_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CClienteYUsuario"
Call eliminaConsulta(nomQuery)
Es decir:
SQL ORDENADA
Vamos a ordenar nuestros resultados. Para ello insertaremos un nuevo botón de comando
(cmdOrdenadoAsc) y vamos a generarle el siguiente código:
…
Private Sub cmdOrdenadoAsc_Click()
Dim miSql As String, nomQuery As String
5
Visítame en http://siliconproject.com.ar/neckkito/
nomQuery = "CNombreYPoblacionClientesAscendente"
Call eliminaConsulta(nomQuery)
Podemos realizar varias ordenaciones por diferentes campos en la misma consulta. El orden de
ordenación lo estableceremos nosotros por el orden en que escribamos tras el ORDER BY. Por
ejemplo, si queremos ordenar por población y, dentro de esta ordenación, a su vez ordenar por
cliente deberíamos escribir este código en el botón cmdOrdenadoAsc2:
…
Private Sub cmdOrdenadoAsc2_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CNombreYPoblacionClientesAscendente2"
Call eliminaConsulta(nomQuery)
Como vemos, la estructura es igual a nuestra consulta simple; simplemente lo que hacemos es
añadir el ORDER BY identificando a continuación el campo que nos dará la ordenación.
¿Y si queremos el orden descendente? Pues ya deberíamos saber hacerlo, pero por si las
moscas el código asignado al botón cmdOrdenadoDesc sería:
…
Private Sub cmdOrdenadoDesc_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CNombreYPoblacionClientesAscendente"
Call eliminaConsulta(nomQuery)
6
Visítame en http://siliconproject.com.ar/neckkito/
miSql = "SELECT TClientes.NomCli, TClientes.PoblCli FROM TClientes" _
& " ORDER BY TClientes.NomCli DESC"
¿Fácil, no?
PREDICADOS
Aprovecharemos lo que hemos aprendido anteriormente para aplicar predicados a nuestras
SQL's.
TOP
Supongamos que queremos ver el importe más alto de todas las ventas que hemos realizado.
Para ello necesitaríamos utilizar el predicado TOP. Como queremos ver una (1) sola venta (la
mayor) necesitaremos indicárselo al TOP. Es decir:
…
Private Sub cmdTop_Click()
Dim miSql As String, nomQuery As String
nomQuery = "VentaImporteMasAlto"
Call eliminaConsulta(nomQuery)
7
Visítame en http://siliconproject.com.ar/neckkito/
DoCmd.OpenQuery nomQuery
End Sub
…
Sigamos con el TOP. Imaginemos que no queremos utilizar valores absolutos, sino que
queremos utilizar porcentajes. Es decir, que queremos saber el 10% de las ventas más altas.
Para ello utilizaríamos la estructura:
…
Private Sub cmdTop10_Click()
Dim miSql As String, nomQuery As String
nomQuery = "VentaImporteMasAlto10xCiento"
Call eliminaConsulta(nomQuery)
miSql = "SELECT TOP 10 PERCENT TVentas.ImpVta FROM TVentas ORDER BY TVentas.ImpVta DESC"
Y el resultado sería:
DISTINCT
Si realizáramos una selección de los clientes a los cuales hemos vendido género podríamos
utilizar la siguiente SQL:
…
Private Sub cmdDistinct_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CClientesConVenta"
8
Visítame en http://siliconproject.com.ar/neckkito/
Call eliminaConsulta(nomQuery)
Como podemos ver, este listado no nos es demasiado práctico, porque se producen
repeticiones del nombre de cliente.
Para obtener valores únicos podemos utilizar el predicado DISTINCT, de acuerdo a la siguiente
estructura:
SELECT DISTINCT …
…
Private Sub cmdDistinct_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CClientesConVenta"
Call eliminaConsulta(nomQuery)
9
Visítame en http://siliconproject.com.ar/neckkito/
OTRA MANERA DE CONSEGUIR EL MISMO RESULTADO
Para este tipo de selección podemos utilizar la cláusula GROUP BY
para obtener el mismo resultado.
…
Private Sub cmdGBy_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CClientesConVenta2"
Call eliminaConsulta(nomQuery)
DISTINCTROW
Con DISTINCTROW, a diferencia de DISTINC (que sólo examina el contenido de los campos
seleccionados), se examina el contenido del registro completo independientemente de los
campos indicados en el SELECT.
Para poder realizar un ejemplo vamos, en nuestra tabla TTrabPersonal, a insertar un nuevo
trabajador, con la característica que va a compartir apellido con uno de los trabajadores ya
existentes. Por ejemplo, yo he añadido el siguiente registro:
…
Private Sub cmdDistincRow_Click()
Dim miSql As String, nomQuery As String
10
Visítame en http://siliconproject.com.ar/neckkito/
nomQuery = "CTrabDistinctRow"
Call eliminaConsulta(nomQuery)
Con el resultado:
Sin embargo, antes de entrar de lleno con esta cláusula vamos a ver un par de curiosidades
sobre cómo maximizar la eficacia de los filtros.
CARACTERES COMODÍN
Podemos utilizar, en combinación con la cláusula WHERE, los operadores que vimos en el
primer capítulo (operadores matemáticos y operadores lógicos), y podemos también utilizar lo
que se denominan “caracteres comodín”.
Bueno... Dicho así quizá no acabe de entenderse del todo. Vamos a ver...
● Si yo escribo ENE* podré obtener resultados como ENE (letra n), ENERO o ENERGIA, porque
* representa cero (letra n) o más caracteres.
● Si yo escribo LO?O podré obtener resultados como LOBO, o LORO, pero no LOBEZNO, porque
? representa cualquier carácter, pero sólo uno. Para que me devolviera LOBEZNO debería
buscar LO????O.
● Si yo escribo A#B podré obtener resultados como A1B, o A9B, pero no A11B, porque sólo he
utilizado una almohadilla (un dígito), y A11B contiene dos dígitos numéricos.
11
Visítame en http://siliconproject.com.ar/neckkito/
● Si yo escribo [a-c]* podré obtener resultados como azul, barco, casa, pero no dedo, porque
estoy buscando palabras que empiecen por a, b o c.
Veremos un par de ejemplos de utilización de estos caracteres comodín un poco más adelante.
OPERADORES
Como comentábamos en el capítulo primero, tenemos dos tipos de operadores: los operadores
matemáticos y los operadores lógicos.
Su combinación con la cláusula WHERE nos permite una gran versatilidad de filtros y de
búsquedas para extraer los datos que nos interesan.
Como ya los comentamos en el capítulo anterior los veremos a través de diversos ejemplos.
Vamos a empezar con una serie de ejemplos de cómo podemos utilizar los diferentes
elementos que hemos visto hasta ahora.
12
Visítame en http://siliconproject.com.ar/neckkito/
EJEMPLOS CON OPERADORES MATEMÁTICOS
Vamos a realizar una consulta sobre la tabla TVentas donde
obtengamos las ventas de importe mayor a 5000 euros.
…
Private Sub cmdVtasMas5000_Click()
Dim miSql As String, nomQuery As String
nomQuery = "VentasMas5000"
Call eliminaConsulta(nomQuery)
Imaginemos que queremos conocer las ventas realizadas a partir de abril 2012. En este caso
estamos trabajando con un dato de tipo fecha, por lo que debemos recordar enmarcarlo entre
almohadillas.
…
Private Sub cmdVtasSupAbril12_Click()
Dim miSql As String, nomQuery As String
nomQuery = "VentasSupAbril12"
Call eliminaConsulta(nomQuery)
Como podemos ver, la operativa con operadores matemáticos es sencilla y no creo que
necesitemos más ejemplos sobre el tema.
13
Visítame en http://siliconproject.com.ar/neckkito/
EJEMPLOS CON OPERADORES DE COMPARACIÓN
BETWEEN... AND...
La estructura, tras el WHERE, para utilizar este operador
sería:
…
Private Sub cmdVtas1T12_Click()
Dim miSql As String, nomQuery As String
nomQuery = "Ventas1T12"
Call eliminaConsulta(nomQuery)
Fijaos que he enmarcado las fechas entre almohadillas y que he utilizado el formato de fecha
inglés de nuevo.
IN
El operador IN nos permite seleccionar registros con valores que coincidan con la condición
marcada en el propio IN.
Por ejemplo, queremos saber qué clientes tenemos en las poblaciones de Valencia y Badajoz.
Nuestra SQL sería:
…
Private Sub cmdClientesValenciaBadajoz_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CClientesValenciaYBadajoz"
Call eliminaConsulta(nomQuery)
14
Visítame en http://siliconproject.com.ar/neckkito/
DoCmd.OpenQuery nomQuery
End Sub
…
…
Private Sub cmdMesesIN_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CMesesConIN"
Call eliminaConsulta(nomQuery)
LIKE
El operador LIKE nos sirve para buscar por aproximación, y lo utilizamos combinándolo con los
caracteres comodín que hemos visto unos apartados más arriba.
Supongamos que queremos saber qué trabajadores están relacionados con el departamento de
ventas. Podríamos pues filtrar por aquellos cuyo cargo contenga las palabras “ven”.
…
Private Sub cmdTrabRelVtas_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CTrabRelacionadosVentas"
Call eliminaConsulta(nomQuery)
Fijaos que, como estamos buscando una cadena de texto, debemos enmarcar la condición
entre comillas simples.
15
Visítame en http://siliconproject.com.ar/neckkito/
Supongamos que queremos mostrar todos los trabajadores cuyo apellido empiece por las
letras de la F a la J.
…
Private Sub cmdTrabFJ_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CTrabFaJ"
Call eliminaConsulta(nomQuery)
Del mismo modo, si quisiéramos añadir a la anterior búsqueda aquellos trabajadores cuyo
apellido empiece también por las letras que van de la V a la Z escribiríamos:
…
Private Sub cmdTrabFJ_VZ_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CTrabFaJyVaZ"
Call eliminaConsulta(nomQuery)
Si, por el contrario, lo que queremos es ver todos los trabajadores menos aquellos cuyo
apellido empiece por las letras de la F a la J escribiríamos:
…
Private Sub cmdTrabNoFJ_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CTrabNoFaJ"
Call eliminaConsulta(nomQuery)
Otro ejemplo con dígitos. Imaginemos que queremos conocer aquellos trabajadores cuyo
teléfono acabe con un 2 seguido de cualquier dígito. Nuestra SQL sería:
16
Visítame en http://siliconproject.com.ar/neckkito/
…
Private Sub cmdTrabTfno2x_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CTrabTfno2x"
Call eliminaConsulta(nomQuery)
Finalmente, imaginemos que queremos saber qué trabajadores tienen, en su apellido, la letra I
y la letra O, pero que sólo haya un carácter en medio de ambas letras.
…
Private Sub cmdTrabIxO_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CTrabIxO"
Call eliminaConsulta(nomQuery)
AND
El operador AND obliga a que se cumplan todas las condiciones especificadas para devolver
registros.
Su estructura sería:
Por ejemplo, vamos a recuperar los clientes que sean de Valencia y en su nombre aparezcan
las letras “Frut”.
17
Visítame en http://siliconproject.com.ar/neckkito/
El código sería:
…
Private Sub cmdCliFrutValencia_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CClientesFrutValencia"
Call eliminaConsulta(nomQuery)
OR
Con el operador se nos devuelven registros siempre que se cumpla una de las dos condiciones,
o ambas (pueden ser más de dos, ojo).
Por ejemplo, si queremos saber qué clientes tenemos en Madrid o en Bilbao deberíamos
escribir:
…
Private Sub cmdCliMadridBilbao_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CClientesMadridBilbao"
Call eliminaConsulta(nomQuery)
XOR
Con el operador XOR obtenemos el registro si sólo se cumple una de las condiciones; si se
cumplen ambas o no se cumple ninguna no obtenemos ningún registro.
18
Visítame en http://siliconproject.com.ar/neckkito/
nomTabla.nomCampoY <operador><condicion> XOR …
…
Private Sub cmdXor_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CEjemploXOR"
Call eliminaConsulta(nomQuery)
IMP / EQV
A modo de información os comentaré que existen los operadores IMP y EQV. No realizaremos
ningún ejemplo sobre los mismos, pero sí os dejaré indicadas sus tablas de verdad, por si en
alguna ocasión os pudieran ser de utilidad.
19
Visítame en http://siliconproject.com.ar/neckkito/
IMP
Expresión1 Expresión2 Devuelve
Verdadero Verdadero Verdadero
Verdadero Falso Falso
Verdadero Null Null
Falso Verdadero Verdadero
Falso Falso Verdadero
Falso Null Verdadero
Null Verdadero Verdadero
Null Falso Null
Null Null Null
EQV
Expresión1 Expresión2 Devuelve
Verdadero Verdadero Verdadero
Verdadero Falso Falso
Falso Verdadero Falso
Falso Falso Verdadero
NOT
El uso del NOT es de lo más sencillo: se antepone a todos los operadores que hemos visto
anteriormente y convierte su significado en el contrario.
Por ejemplo, en un epígrafe anterior hemos visto cómo podíamos sacar los meses impares. Si
quisiéramos sacar los meses pares aprovechando el código que ya tenemos escrito podríamos
utilizar el operador NOT, con lo que obtendríamos:
…
Private Sub cmdNot_Click()
Dim miSql As String, nomQuery As String
20
Visítame en http://siliconproject.com.ar/neckkito/
nomQuery = "CMesesConNOTIN"
Call eliminaConsulta(nomQuery)
WHERE ISNULL(nomTabla.nomCampo)
o utilizando el NOT
Vamos, en nuestra tabla TClientes, a añadir un nuevo cliente, pero no le asignaremos ninguna
población. El registro nos quedaría una cosa así:
…
Private Sub cmdIsNull_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CClientesSinPoblacion"
Call eliminaConsulta(nomQuery)
Para devolver todos los registros menos el que acabamos de dar de alta simplemente
construiríamos la SQL así:
21
Visítame en http://siliconproject.com.ar/neckkito/
PARA ACABAR ESTE CAPÍTULO...
Hemos hecho una primera “incursión” en el lenguaje SQL
con sentencias muy simples. El objetivo del mismo era que
os familiarizarais con las estructuras y con las palabras
clave que generalmente veréis en una sentencia SQL
(hablando muy en general). Así, si en un código os
encontráis con SELECT, FROM, ORDER BY... ya sabréis
inmediatamente que estamos hablando de este lenguaje.
Finalmente, hemos aprendido también cómo filtrar los datos mediante consultas de selección,
aplicando la cláusula WHERE y muchos operadores que tenemos a nuestra disposición.
En próximos capítulos iremos viendo otras posibilidades para manejar datos a través del
Structured Query Language
Un saludo, y
¡suerte!
22
Visítame en http://siliconproject.com.ar/neckkito/
CURSO DE SQL
CAPÍTULO 31
Índice de contenido
COMPLIQUEMOS UN POCO LAS CONSULTAS DE SELECCIÓN..............................................2
VAMOS ALLÁ................................................................................................................................2
CREACIÓN DE “LITERALES”.....................................................................................................2
UTILIZACIÓN DE “ALIAS”.........................................................................................................3
ALIAS DIRECTO COMO CAMPO..........................................................................................3
ALIAS DIRECTO COMO TABLA............................................................................................4
ALIAS INDIRECTO: USO DE FUNCIONES AGREGADAS.................................................5
OPERACIONES MATEMÁTICAS Y OTRAS “POSIBILIDADES”..................................6
FUNCIONES DE VALORES SIMPLES...............................................................................7
ABS().................................................................................................................................8
SQR().................................................................................................................................8
MOD()...............................................................................................................................8
ROUND()..........................................................................................................................8
FUNCIONES DE GRUPOS DE VALORES (FUNCIONES DE AGREGADO)..................8
COUNT()...........................................................................................................................8
SUM()................................................................................................................................9
AVG()................................................................................................................................9
STDEV() / STDEVP().......................................................................................................9
FIRST() / LAST()............................................................................................................10
MAX() / MIN()................................................................................................................10
CONSULTAS ANIDADAS, O SUBCONSULTAS...........................................................................10
UTILIZANDO “IN”......................................................................................................................10
UTILIZANDO “ANY”/”SOME”..................................................................................................12
UTILIZANDO “EXISTS”.............................................................................................................12
COMBINACIÓN DE ELEMENTOS EN SQL..................................................................................13
COMBINACIÓN EXTERNA (O LLÁMAME... “OUTER JOINS”)...........................................13
CORRESPONDENCIA CON LAS CONSULTAS-OBJETO EN ACCESS. TIPOS DE
COMBINACIÓN......................................................................................................................15
COMBINACIÓN INTERNA (O LLÁMAME... “INNER JOIN”)...............................................16
CONSULTA “UNION” / “UNION ALL”.....................................................................................17
CONSULTA “TRANSFORM”......................................................................................................19
AUTOCOMBINACIÓN................................................................................................................21
SELF JOIN....................................................................................................................................22
CLÁUSULA “HAVING”...................................................................................................................24
PARA FINALIZAR ESTE CAPÍTULO.............................................................................................25
1
Visítame en http://siliconproject.com.ar/neckkito/
COMPLIQUEMOS UN POCO LAS CONSULTAS DE SELECCIÓN
VAMOS ALLÁ...
CREACIÓN DE “LITERALES”
Puede interesarnos, en un momento dado, mostrar una información puntual a través de una
consulta, e identificar claramente qué información estamos obteniendo.
Un literal no es más que una cadena de texto que nos mostrará el valor literal que hayamos
escrito en cada registro de la consulta.
Supongamos que queremos ver las ventas, pero con impuestos incluidos, y que nuestro
impuesto es el 18%. Para no perder de vista que estamos trabajando con valores “impuesto
incluido” podríamos querer que en cada registro se mostrara dicha información.
…
Private Sub cmdLiteral_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CLiteral"
Call eliminaConsulta(nomQuery)
2
Visítame en http://siliconproject.com.ar/neckkito/
Fijaos que, aunque no sea una solución muy “elegante”, para una consulta puntual nos puede
sacar del apuro.
También cabe destacar que podemos realizar operaciones matemáticas con los valores de los
registros directamente sobre la SQL. En nuestro caso hemos multiplicado por 1,18:
TVentas.ImpVta*1.18
UTILIZACIÓN DE “ALIAS”
En ocasiones puede interesarnos crear un campo que no existe inicialmente en la tabla. Esta
creación puede ser realizada de dos maneras:
– De manera directa
– De manera indirecta, porque aplicamos alguna función.
¿Y qué es un alias? Para que nos entendamos, es el nombre que nos “inventamos” para poder
hacer referencia a ese campo que no existe, inicialmente.
Supongo que, hasta ahora, la cosa está clara (¿o no?). La verdad es que sin ver un ejemplo
este concepto puede parecer un poco difuso. Vamos pues a plantear una hipótesis de trabajo
para la creación de un alias de manera directa.
Evidentemente podríamos crear una consulta como ya sabemos e imprimirla, pero como
queremos quedar bien con el jefe vamos a crearle un campo más a la consulta, en blanco, y
que además la columna esté identificada con el título “Punteado”.
Para ello vamos a crearnos una SQL que utilizará un alias, y ese alias será precisamente el
texto “Punteado”.
3
Visítame en http://siliconproject.com.ar/neckkito/
…
Private Sub cmdAliasPunteado_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CAliasPunteado"
Call eliminaConsulta(nomQuery)
miSql = "SELECT TVentas.IdCliVta, TVentas.ImpVta, NULL AS Punteado" _
& " FROM TVentas" _
& " WHERE TVentas.FechVta>#12-31-2011#"
<valor/expresión> AS <alias>
– El campo que hace de filtro NO tiene porqué mostrarse en los resultado (filtramos por
fecha de venta pero no se ve en la consulta)
– Para indicar que queremos un campo vacío utilizamos NULL
Es decir, que si nuestro jefe se pone “tonto” y dice que quiere la palabra NO para poder él ir
tachándola nuestra SQL debería quedar:
4
Visítame en http://siliconproject.com.ar/neckkito/
Para comodidad de lectura de código podemos utilizar AS, aunque en el caso de tablas
podemos poner el alias directamente, sin necesidad de utilizar el AS.
…
Private Sub cmdAliasTabla_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CAliasTabla"
Call eliminaConsulta(nomQuery)
Si nos fijamos hemos definido el alias sobre la tabla tras la cláusula FROM, a través de ( FROM
TVentas AS TV), y todas las referencias a nomTabla han sido hechas con “TV”.
Si hubiéramos escrito nuestra SQL así (fijaos lo escrito tras el FROM) nuestra SQL funcionaría
igualmente bien:
Hago también esta separación a efectos pedagógicos, porque pienso que la sistemática del
alias se entiende mejor si realizamos esta categorización.
Quería hacer esta aclaración porque dudo que si alguien busca información por ahí sobre este
tema pueda encontrar estos términos de “alias directo” o “alias indirecto” (o, al menos, yo he
sido incapaz de encontrar algo parecido). Hay que ser originales, ¿verdad?
Clarificado lo anterior vamos a ver este tema de funciones agregadas, pero antes, para hacer
este apartado más completo, veremos el uso de operaciones matemáticas y otras
“posibilidades”.
5
Visítame en http://siliconproject.com.ar/neckkito/
OPERACIONES MATEMÁTICAS Y OTRAS “POSIBILIDADES”
Podemos realizar operaciones matemáticas en la propia SQL
y asignarles un alias. Por ejemplo, ¿nos acordamos de
nuestra SQL de “Ventas al 18%, unas páginas antes?
Vamos a hacer lo mismo, pero desglosando el impuesto y el
total final, utilizando alias para cada uno de ellos.
TVentas.ImpVta*0.18 As Impuesto
TVentas.ImpVta*1.18
.- O bien utilizar la suma de dos campos: el existente (ImpVta) y el alias que acabamos
de crear (Impuesto):
…
Private Sub cmdVtasImpto_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CVtasImpto"
Call eliminaConsulta(nomQuery)
Importante: recordad que para operar con exponentes debemos utilizar el símbolo (^),
siguiendo la estructura (valor^exponente). Para conseguir ese símbolo debemos localizar la
tecla que está a la derecha de la “P” y pulsar la combinación SHIFT+tecla, y a continuación
pulsar la barra espaciadora. Por ejemplo, para hallar el cubo de 25 escribiríamos: 25^3
Supongamos que necesitamos un campo donde se muestren, juntos, “apellido, nombre” de los
trabajadores.
6
Visítame en http://siliconproject.com.ar/neckkito/
Para conseguir eso debemos recurrir al concatenador ampersand (&), y construirnos la
estructura del campo como la deseamos, para después asignarle un alias.
…
Private Sub cmdApellNombre_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CApellNom"
Call eliminaConsulta(nomQuery)
También, para no tener que escribir cada vez el “largo” nombre de la tabla, he utilizado un
alias sobre la tabla.
El código “genérico” que utilizaremos para explicar estas funciones será el siguiente:
…
Private Sub cmdAbs_Click()
Dim miSql As String, nomQuery As String
nomQuery = "NombreConsulta"
Call eliminaConsulta(nomQuery)
7
Visítame en http://siliconproject.com.ar/neckkito/
negrita.
ABS()
Devuelve el VALOR ABSOLUTO de un número. En la tabla de
ejemplo no se van a producir variaciones en el resultado
porque no hay valores negativos, pero, si los hubiera,
quedarían convertidos en valores positivos.
SQR()
Devuelve la RAÍZ CUADRADA de un valor.
MOD()
Devuelve el RESTO DE LA DIVISIÓN de un valor entre otro valor.
ROUND()
La función Round() REDONDEA LOS DECIMALES DE UN VALOR AL NÚMERO DE DECIMALES
QUE INDICAMOS, siguiendo la estructura:
Round(<valor>,<nº de decimales>)
La siguiente SQL redondea los decimales del importe de ventas a un solo decimal.
COUNT()
Esta función devuelve la CUENTA de los registros.
Si queremos saber cuántos registros cumplen la condición de que las ventas sean superiores a
8
Visítame en http://siliconproject.com.ar/neckkito/
5000 euros nuestra SQL sería:
SUM()
Devuelve la SUMA de los valores seleccionados.
AVG()
Devuelve el PROMEDIO de los valores seleccionados.
VAR() / VARP()
La función Var() devuelve la VARIANZA DE UNA MUESTRA DE POBLACIÓN; la función Varp()
devuelve la VARIANZA DE UNA POBLACIÓN.
La SQL sería (ejemplo con Var(); con Varp() la estructura sería la misma):
STDEV() / STDEVP()
La función Stdev() devuelve la DESVIACIÓN ESTÁNDAR DE UNA MUESTRA DE POBLACIÓN; la
función Stdevp() devuelve la DESVIACIÓN ESTÁNDAR DE UNA POBLACIÓN.
La SQL sería (ejemplo con StDev(); con StDevp() la estructura sería la misma):
9
Visítame en http://siliconproject.com.ar/neckkito/
FIRST() / LAST()
First() devuelve el valor DEL PRIMER REGISTRO; Last() devuelve el valor DEL ÚLTIMO
REGISTRO.
---
MAX() / MIN()
Max() devuelve el valor MÁXIMO de un grupo de registros; Min() devuelve el valor MÍNIMO de
un grupo de registros.
La siguiente SQL nos muestra la venta mayor de las que se han realizado:
Sin embargo, es interesante saber que existe esta sistemática de trabajo con las SQL, y que
podemos utilizarlas.
UTILIZANDO “IN”
Planteemos el problema: queremos saber el detalle del importe de las ventas realizadas por los
clientes (hasta aquí ya deberíamos saber hacerlo), pero sólo de los clientes que están en las
poblaciones de Badajoz y Cádiz.
Bueno, bueno... primer problema que tenemos: las ventas están en una tabla y las poblaciones
10
Visítame en http://siliconproject.com.ar/neckkito/
están en otra.
Si quisiéramos realizar una SQL que nos filtrara los clientes de Badajoz y Cádiz, cogiendo su
identificador de cliente, escribiríamos:
¿Estamos de acuerdo?
Pues básicamente se trata de sustituir los valores por la consulta que nos proporciona esos
valores.
…
Private Sub cmdSubconsultas_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CSubconsulta"
Call eliminaConsulta(nomQuery)
Sólo llamar la atención sobre el hecho de que no debemos olvidarnos el paréntesis de cierre
del IN () de la consulta principal.
11
Visítame en http://siliconproject.com.ar/neckkito/
UTILIZANDO “ANY”/”SOME”
Los predicados ANY o SOME son sinónimos, por lo que
podemos emplear tanto uno como otro. Se utilizan como
comparadores de los resultados que devuelve la
subconsulta.
…
Private Sub cmdSubconsultas2_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CSubconsulta2"
Call eliminaConsulta(nomQuery)
UTILIZANDO “EXISTS”
Con el predicado EXISTS lo que obtenemos es un TRUE o FALSE; es decir, comprobamos si la
subconsulta nos dice Sí o No.
Por ejemplo, queremos saber qué clientes NO han realizado ninguna compra durante el año
2011. Será nuestra subconsulta la que nos dirá si sí han realizado compra o no, y la consulta
principal nos mostrará los resultados:
…
Private Sub cmdSubconsulta3_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CSubconsulta3"
Call eliminaConsulta(nomQuery)
12
Visítame en http://siliconproject.com.ar/neckkito/
…
Fijaos en que:
– Para saber “si el cliente existe” hemos tenido que indicar la
correspondencia del identificador de cliente, necesario para
que la SQL funcione
(& " Tclientes.IdCli=TVentas.IdCliVta))")
SELECT …
FROM tabla1 LEFT/RIGHT OUTER JOIN tabla2
ON <condición de relación entre campos de tablas>
¿Y qué es un “Outer Join”? Os pego lo que el propio Access dice sobre el tema:
<<La combinación externa (OUTER JOIN) se utiliza para recuperar registros de varias tablas mientras se conservan
los registros de una de las tablas, aun cuando en la otra no haya ningún registro que coincida. El motor de base de
datos de Access admite dos tipos de combinaciones externas: LEFT OUTER JOIN (izquierda) y RIGHT OUTER
JOIN (derecha). Imagine dos tablas situadas una junto a otra, una a la izquierda y otra a la derecha. La LEFT
OUTER JOIN selecciona todas las filas de la tabla derecha que cumplen los criterios de comparación relacionales,
además de seleccionar todas la filas de la tabla izquierda, aun cuando no existan coincidencias en la tabla derecha. La
RIGHT OUTER JOIN es sencillamente lo contrario de la LEFT OUTER JOIN: en ella se conservan todas las filas
de la tabla derecha>>
A ver si con un ejemplo clarificamos lo anterior. La finalidad de nuestra consulta: mostrar todos
los clientes dados de alta en nuestra BD (a través de TClientes) y la suma de las ventas
realizadas para cada uno de ellos.
¿Y qué pasa si hay algún cliente al que aún no se le ha vendido nada? Pues no hay problema,
porque:
13
Visítame en http://siliconproject.com.ar/neckkito/
…
Private Sub cmdOuterJoins_Click()
Dim miSql As String, nomQuery As String
nomQuery = "COuterJoins"
Call eliminaConsulta(nomQuery)
Como podemos apreciar, a “Rábanos Buenitos” aún no se le ha efectuado ninguna venta, por lo
que el cliente nos aparece, pero con un valor NULL en la columna “Ventas”.
Si no lo hiciéramos así obtendríamos un error. Supongamos que en nuestra SQL nos olvidamos
de agrupar por NomCli, de manera que la última línea de la SQL fuera:
14
Visítame en http://siliconproject.com.ar/neckkito/
Conclusión: si obtenemos este error debemos comprobar nuestro GROUP BY
Sólo nos queda comentar que podemos omitir la palabra OUTER y Access seguirá entendiendo
que queremos realizar una combinación externa. Es decir, que si en el anterior código
hubiéramos escrito:
Cuando realizamos una consulta en vista diseño entre dos tablas relacionadas Access utiliza la
combinación tipo 1 por defecto. Veámoslo:
.- Creamos una consulta en vista diseño sobre las tablas TClientes y TVentas.
Automáticamente se nos debería crear una relación entre ambas a través de los campos [IdCli]
e [IdCliVta]
15
Visítame en http://siliconproject.com.ar/neckkito/
.- Nos situamos sobre la línea de relación y, con mucho pulso, hacemos click con el botón de la
derecha. Nos saldrá un menú contextual con dos opciones:
SELECT …
FROM tabla1 INNER JOIN tabla2
ON <condición de relación entre campos de tablas>
Siguiendo con el ejemplo anterior, si convertimos la consulta que hemos hecho en una INNER
JOIN obtendríamos:
…
Private Sub cmdInnerJoin_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CInnerJoin"
Call eliminaConsulta(nomQuery)
16
Visítame en http://siliconproject.com.ar/neckkito/
miSql = "SELECT TClientes.IdCli, TClientes.NomCli, Sum(TVentas.ImpVta) As
Ventas" _
& " FROM TClientes INNER JOIN TVentas" _
& " ON TClientes.IdCli = TVentas.IdCliVta" _
& " GROUP BY TClientes.IdCli, TClientes.NomCli"
La estructura de una consulta de Unión sería, para que nos entendemos, la unión de dos
consultas SELECT a través de la operación UNION.
SELECT … FROM …
UNION
SELECT … FROM …
Por ejemplo, supongamos que queremos obtener una consulta que nos devuelva los clientes
con ventas superiores a 15000 euros y también los clientes con ventas inferiores a 2000,
descartando los valores intermedios, podríamos realizar la siguiente consulta de unión:
…
Private Sub cmdUnion_Click()
Dim miSql As String, nomQuery As String
17
Visítame en http://siliconproject.com.ar/neckkito/
nomQuery = "CUnion"
Call eliminaConsulta(nomQuery)
…
Private Sub cmdUnion2_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CUnion2"
Call eliminaConsulta(nomQuery)
Como vemos he tenido que crear un campo que me uniera el nombre del trabajador y su
apellido porque el nombre de la empresa corresponde sólo a un campo, no a dos; en definitiva,
lo que os comentaba de conseguir una estructura consistente.
Para saciar vuestra segura curiosidad, aquí tenéis capturado un fragmento de lo que devolvería
la anterior consulta:
18
Visítame en http://siliconproject.com.ar/neckkito/
Os copio aquí algunas indicaciones que da la propia ayuda de Access sobre este tipo de
consultas que creo que pueden seros útiles:
<<De forma predeterminada, no se devuelven registros duplicados cuando se usa la operación UNION; sin embargo,
puede incluir el predicado ALL para asegurarse de que se devuelven todos los registros. Además, de esta manera, la
consulta se ejecuta más rápidamente.
Todas las consultas de una operación UNION deben solicitar el mismo número de campos; sin embargo, no es
necesario que los campos sean del mismo tamaño o tipo de datos.
Use alias sólo en la primera instrucción SELECT, ya que en las demás se omiten. En la cláusula ORDER BY, haga
referencia a los campos por el nombre que se utilice en la primera instrucción SELECT.>>
Y, para acabar, tened en cuenta que las consultas de unión NO ADMITEN el uso de campos tipo
hipervínculo, objeto OLE o Datos Adjuntos. Si los intentáis utilizar el campo os saldrá con
#ERROR
CONSULTA “TRANSFORM”
Una SQL con la instrucción TRANSFORM es lo que en Access conocemos como “consulta de
referencias cruzadas”
TRANSFORM
<función de agregado>
SELECT … FROM …
GROUP BY …
PIVOT …
Vamos a ver cómo aplicamos lo anterior para construirnos una SQL. Lo haremos razonándolo
porque este tipo de consulta, para quienes la ven por primera vez, puede parecer muy
complicada, aunque no tiene por qué serlo.
Imaginemos que queremos ver la suma por clientes y por meses, correspondientes al año
2012. Quedémonos con este enunciado, pues será el hilo conductor para realizar la SQL.
Hemos dicho que queremos ver “la suma de las ventas”. Esto ya nos da el primer elemento de
la SQL. Y como contiene una función de agregado (suma) será lo primero que escribiremos en
la SQL. Así:
TRANSFORM
Sum(TVentas.ImpVta) As Ventas
19
Visítame en http://siliconproject.com.ar/neckkito/
Sigamos:
¿Cuál es el criterio de la vista que queremos obtener? Pues el criterio es “por clientes” y “por
meses”.
WHERE TVentas.FechVta>=#01-01-12#
GROUP BY TVentas.IdCliVta
Y vamos a por el segundo criterio. Queremos la información por meses. Y para sacar el mes de
una fecha utilizamos la función Datepart() -eso deberíamos saberlo de VB, pero si no lo
sabemos lo aprendemos aquí... sin problemas-. Y la función Datepart(), para que nos devuelva
el mes, tiene la siguiente sintaxis: Datepart('m',<campo con la fecha>).
PIVOT Datepart('m',TVentas.FechVta)
…
Private Sub cmdTransform_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CTransform"
Call eliminaConsulta(nomQuery)
20
Visítame en http://siliconproject.com.ar/neckkito/
AUTOCOMBINACIÓN
Supongamos que queremos obtener una información que pase por combinar elementos que
tenemos dentro de la propia tabla y que, de alguna manera, dependen los unos de los otros.
Para realizar la autocombinacion vamos a servirnos de la misma tabla pero, gracias a un alias,
vamos a tratarlas cómo si fueran dos tablas distintas.
Por ejemplo, vamos a ver una consulta que nos devolverá el empleado con su cargo junto con
el nombre del empleado del que depende, también con su puesto.
…
Private Sub cmdAutocombinacion_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CAutocombinacion"
Call eliminaConsulta(nomQuery)
Fijémonos cómo:
– Hemos utilizado dos alias sobre la misma tabla, de manera que “parece” que
manejamos dos tablas diferentes (TTrabLaboral AS Empl, TTrabLaboral AS Sup)
– Hemos seleccionado los campos que nos interesaban seleccionándolos como si fueran
campos de esas dos tablas diferentes (SELECT Empl.IdTrab, Empl.Cargo,
Sup.IdTrab, Sup.Cargo)
– Para obtener la relación hemos utilizado datos que tenemos en la misma tabla, y que
provienen de los campos [IdTrab] y [DependeDe] (WHERE
Empl.DependeDe=Sup.IdTrab)
21
Visítame en http://siliconproject.com.ar/neckkito/
SELF JOIN
Para conseguir un producto cartesiano de una tabla consigo misma podemos utilizar una
estructura SELF JOIN. Un producto cartesiano establece una relación de cada uno de los
elementos de la tabla por sí mismo y por el resto de elementos de la tabla.
Para poder poner un ejemplo de SELF JOIN vamos a tener que crearnos una nueva tabla, que
llamaremos TRepresentantes. Esta tabla nos recogerá los clientes y los responsables dentro del
departamento de ventas que se encargan de ellos (tranquilos: haremos el ejemplo con pocos
registros).
Teniendo en cuenta que en el campo [IdCliRepr] el tipo de datos viene dado por el asistente
para búsquedas, donde hemos seleccionado la tabla TClientes y como campo visible [NomCli[,
y que para el campo [IdTrabRepr] el tipo de datos se ha creado utilizando el asistente para
búsquedas, donde hemos seleccionado de la tabla TTrabPersonal y como campos visibles
[ApellTrab] y [NomTrabl] (por este orden).
Es decir, que nuestra empresa siempre asigna dos representantes para cada cliente, para
poderse cubrir las “vacaciones” (porque en nuestra empresa SÍ damos vacaciones )
Vamos a realizar la misma “operación” que en el apartado anterior; es decir, vamos a “dividir”
nuestra tabla en dos utilizando un alias.
El código para una combinación SELF JOIN sobre esta tabla podría ser:
22
Visítame en http://siliconproject.com.ar/neckkito/
…
Private Sub cmdSelfJoin_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CSelfJoin"
Call eliminaConsulta(nomQuery)
Y obtenemos:
Como podemos ver, a una “hipotética” tabla la hemos llamado “Uno”, y a la otra “Dos”, y las
hemos relacionado a través de (Uno.IdCliRepr = Dos.IdCliRepr). Si nos hubiéramos
quedado aquí (sin añadir el AND) tendríamos una SELF JOIN en toda regla. Es decir, que nos
saldría el “producto cartesiano” puro y duro. Para los incrédulos...
23
Visítame en http://siliconproject.com.ar/neckkito/
CLÁUSULA “HAVING”
La cláusula HAVING tiene un comportamiento muy parecido
al WHERE, pero trabaja con grupos de registros (WHERE no
puede trabajar con grupos de registros). Hablando para que
nos entendamos, WHERE nos muestra un conjunto de filas
que cumplen un criterio como campos individuales, y
HAVING nos muestra grupos de registros que cumplen un
criterio como grupo de registros.
Imaginemos que queremos obtener una consulta de los totales de ventas, pero que nos
muestre sólo aquellos totales que sean mayores que un límite que hemos establecido como
objetivo de ventas, que será de 8.500 euros.
Debemos crear pues una primera agrupación, que será la que nos calculará la suma de las
ventas agrupadas por cliente.
Con esta primera agrupación ya tenemos los totales de todas las ventas, pero ahora queremos
realizar un filtrado sobre ese grupo, de manera que sólo nos muestre aquellos registros (que,
recordemos, están formados por la agrupación por suma de registros individuales) que
cumplen nuestra condición.
Para ello deberíamos agregar dicho filtro sobre grupo, es decir, HAVING
HAVING Sum(TVentas.ImpVta)>=8500
…
Private Sub cmdHaving_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CHaving"
Call eliminaConsulta(nomQuery)
Como curiosidad, para rematar este apartado, os diré que, según Microsoft, una cláusula
HAVING puede contener hasta 40 expresiones vinculadas por operadores lógicos, como AND y
OR.
24
Visítame en http://siliconproject.com.ar/neckkito/
PARA FINALIZAR ESTE CAPÍTULO
Creo que con este capítulo ya tenemos abundante material
para poder realizar unas SQL “alucinantes” en nuestras BD's
Un saludo, y...
¡suerte!
25
Visítame en http://siliconproject.com.ar/neckkito/
CURSO DE SQL
CAPÍTULO 41
Índice de contenido
LAS CONSULTAS DE ACCIÓN........................................................................................................2
TRES Y... ¡ACCIÓN!......................................................................................................................2
CONSULTA DE DATOS ANEXADOS..........................................................................................3
ANEXAR EN UNA TABLA EXISTENTE (un único registro).................................................3
ANEXAR EN UNA TABLA EXISTENTE (todos los registros / conjunto de registros)...........4
ANEXAR HACIA UNA BD EXTERNA...................................................................................5
ANEXAR DESDE UNA BD EXTERNA..................................................................................6
CONSULTA DE ACTUALIZACIÓN.............................................................................................6
CONSULTA DE ELIMINACIÓN...................................................................................................7
CONSULTA PARA BÚSQUEDA DE REGISTROS DUPLICADOS............................................8
CONSULTAS PARAMETRIZADAS..................................................................................................9
PROCEDURES..................................................................................................................................10
PARA FINALIZAR ESTE CAPÍTULO.............................................................................................10
1
Visítame en http://siliconproject.com.ar/neckkito/
LAS CONSULTAS DE ACCIÓN
En este cuarto capítulo vamos a ver cómo ejecutar lo que se denominan consultas de acción.
Veamos un par de cosas comunes que aplicaremos a lo largo de todo este documento.
Las consultas de acción “operan” sobre los datos; es decir, los cambian, los actualizan, los
eliminan, los “crean” (en una nueva tabla, por ejemplo). Y, por ese motivo, son “peligrosas”.
Un error en alguna de nuestras consultas y nuestros datos... pluf.
Por este motivo nuestro amigo Access nos advierte y vuelve a advertir antes de ejecutar una
consulta de estas características. Es decir, que si yo intento ejecutar, por ejemplo, una consulta
para borrar registros (de lo más cool en cuanto a peligrosidad ) me encontraré con lo
siguiente:
Estas advertencias están muy bien cuando “no sabemos bien lo que hacemos”, pero, ¿y cuándo
lo tenemos más que claro? Pues dichos warnings se convierten en algo de lo más incómodo
(pueden llegar a salirnos tres warnings seguidos, a veces). Click, y click, y click para conseguir
ejecutar la consulta...
Lo anterior podemos evitarlo en nuestro código VB para Access añadiendo dos líneas de
código: una antes de la ejecución de la consulta y otra a continuación de la ejecución de la
consulta. Lo escribiríamos de la siguiente manera:
…
DoCmd.SetWarnings False
'Ejecución de la consulta
DoCmd.SetWarnings True
…
Con estas dos líneas se acabaron los avisos de Access... aunque si nos hemos equivocado...
“Houston, tenemos un problema”.
2
Visítame en http://siliconproject.com.ar/neckkito/
<DoCmd.SetWarnings False>) no se limita a deshabilitar los avisos para ese procedimiento en
concreto que estemos programando, sino que los deshabilita “en general”. Y ello implica que si
se produce algún error en cualquier parte Access no nos avisará, con lo que nuestro código no
funcionará, o no funcionará bien, y no sabremos por qué. Tened cuidado con
“olvidarse” de volver a habilitar los avisos.
Más cosas... Las consultas de acción se ejecutan directamente a través del código. Por ello
veréis que ya no nos hará falta recurrir al código de mdlProcesos que utilizábamos hasta
ahora. Es decir, no nos será necesario crearnos la consulta para poder ver los resultados.
La ejecución de una consulta SQL, utilizando nuestro código VB, se ejecutará a través de
DoCmd.RunSQL <nombreSQL>
CurrentDb.Execute <nombreSQL>
En general (ojo, en general, aunque hay excepciones) no debería darnos problemas utilizar
una sintaxis u otra al operar con consultas de selección o de acción.
Como siempre (pero por si acaso lo repito), los ejemplos de este capítulo se basarán en la
tabla que creamos en el capítulo 1.
Y, ahora sí, vamos a echar una ojeada a las consultas de acción en SQL.
Para desarrollar el ejemplo vamos a hacer un copiar-pegar manual de la tabla TClientes (pero
sólo la estructura, no los datos). Para ello copiamos dicha tabla y antes de pegarla con el
nombre de TClientes2 seleccionamos la “opción de pegado → Estructura solamente”.
3
Visítame en http://siliconproject.com.ar/neckkito/
…
Private Sub cmdDatosAnexados1_Click()
Dim miSql As String
DoCmd.SetWarnings False
DoCmd.RunSQL miSql
DoCmd.SetWarnings True
Incluyo el MsgBox al final porque si no es frustrante no saber si las cosas han ido bien o no, o
dudar de si se ha realizado el proceso o no.
¿Fácil, verdad?
…
Private Sub cmdDatosAnexadosTodos_Click()
Dim miSql As String
DoCmd.SetWarnings False
DoCmd.RunSQL miSql
DoCmd.SetWarnings True
Si lo que queremos no son todos los registros sino un conjunto de registros simplemente
deberíamos añadir un WHERE a nuestra SQL.
Para que quede más claro, por si acaso, por ejemplo anexaremos a esta tabla los registros de
los clientes cuyo CIF empiece por A.
El código sería:
4
Visítame en http://siliconproject.com.ar/neckkito/
…
Private Sub cmdDatosAnexadosAlgunos_Click()
Dim miSql As String
DoCmd.SetWarnings False
DoCmd.RunSQL miSql
DoCmd.SetWarnings True
Como podemos intuir, vamos a anexar en esta tabla los datos de nuestra tabla TClientes (sólo
los campos con el nombre y el NIF).
…
Private Sub cmdDatosAnexadosHaciaBDExterrna_Click()
Dim rutaBDExt As String, miSql As String
DoCmd.SetWarnings False
DoCmd.RunSQL miSql
DoCmd.SetWarnings True
5
Visítame en http://siliconproject.com.ar/neckkito/
Tened en cuenta que los nombres de campos deben ser idénticos. Si no lo fueran el código
nos diría que no se encuentra el campo XXX. Esto es válido también para el apartado
que se explica a continuación.
Es decir, que nuestro código nos debería quedar así, si queremos anexar los registros de
TClientesExt en TClientes2:
…
Private Sub cmdDatosAnexadosDesdeBDExterna_Click()
Dim rutaBDExt As String, miSql As String
DoCmd.SetWarnings False
DoCmd.RunSQL miSql
DoCmd.SetWarnings True
CONSULTA DE ACTUALIZACIÓN
Para realizar las consultas de actualización utilizaremos la instrucción UPDATE. La estructura de
una consulta de actualización es:
UPDATE nomTabla
SET nomCampo1 = <nuevoValor>,..., nomCampoN = <nuevoValor>
Es muy usual utilizar WHERE con este tipo de consultas para indicar qué registros son los que
deben ser utilizados. La cláusula WHERE se sitúa al final. Es decir:
UPDATE nomTabla
SET nomCampo1 = <nuevoValor>,..., nomCampoN = <nuevoValor>
WHERE <condición>
6
Visítame en http://siliconproject.com.ar/neckkito/
DoCmd.SetWarnings? ¡Hay que utilizarlos con mucho cuidado!
…
Private Sub cmdActualizaTClientes_Click()
Dim miSql As String
DoCmd.SetWarnings False
DoCmd.RunSQL miSql
DoCmd.SetWarnings True
Recordad que también podemos realizar cálculos para actualizar datos. Por ejemplo, el día que
metimos los datos en nuestra BD no estábamos muy “inspirados” y al dar de alta las ventas no
nos dimos cuenta que las metíamos “impuestos incluidos”. Lógicamente había que almacenar
los datos con “impuestos excluidos”.
Si, por ejemplo, habíamos aplicado una tasa del 18%, nuestra consulta de actualización
debería ser:
…
Private Sub cmdActualizaTVentas_Click()
Dim miSql As String
DoCmd.SetWarnings False
DoCmd.RunSQL miSql
DoCmd.SetWarnings True
Efectivamente, en este caso necesitaba que se actualizaran todos los registros, por lo que he
omitido el uso de WHERE
CONSULTA DE ELIMINACIÓN
Las instrucción que nos define una consulta de eliminación es DELETE.
Su estructura es:
7
Visítame en http://siliconproject.com.ar/neckkito/
Y, si queremos ser un poco selectivos (es decir, no realizar una matanza masiva), utilizamos
WHERE
En nuestra BD de ejemplo debemos tener por ahí una tabla llamada TClientes2. Vamos a
eliminar todos los clientes que tengan, en su nombre, alguna relación con la “carne”.
…
Private Sub cmdEliminaDeTClientes2_Click()
Dim miSql As String
DoCmd.SetWarnings False
DoCmd.RunSQL miSql
DoCmd.SetWarnings True
Dicho lo anterior vamos a ver cómo podemos confeccionar dicha SQL, pero antes, en nuestra
tabla TClientes2, vamos crear un nuevo registro con el nombre duplicado de un cliente, pero
con distinto NIF.
…
Private Sub cmdDuplicados_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CDuplicados"
8
Visítame en http://siliconproject.com.ar/neckkito/
Call eliminaConsulta(nomQuery)
CONSULTAS PARAMETRIZADAS
Podemos construir consultas en las cuales se solicite información al usuario para, a
continuación, mostrar los datos deseados. Esta solicitud de información se realiza a través de
lo que denominamos “parámetros”.
Supongamos que queremos saber las ventas que se han producido en nuestra empresa, pero a
veces necesitamos los datos con anterioridad a una fecha y dependiendo de un determinado
volumen de ventas.
Nuestros parámetros, en este caso, serían la fecha y el importe. Más allá la consulta sería una
simple consulta de selección.
…
Private Sub cmdCParametrizada_Click()
Dim miSql As String, nomSql As String
nomSql = "FiltroVentas"
Call eliminaConsulta(nomSql)
9
Visítame en http://siliconproject.com.ar/neckkito/
Fijaos que separamos los parámetros de la consulta utilizando punto y coma (;). Ojo: no hay
que olvidarse de ese punto y coma porque si no obtendremos error en los parámetros de la
SQL.
PROCEDURES
La cláusula PROCEDURE, según Access, <<define un
nombre y parámetros opcionales para una consulta>>.
Como siempre, la ayuda de Access a veces “se pasa” con la
explicación . A eso debemos añadir que esta cláusula ha
quedado obsoleta, debiéndose utilizar (siempre según
Access) la instrucción PROCEDURE.
No la voy a explicar porque, sinceramente, no tengo mucha idea de cómo hacerlo. En primer
lugar porque no la he utilizado nunca; en segundo lugar porque soy incapaz de encontrar un
ejemplo “práctico” para aplicar a nuestra BD de ejemplo, dado que al combinarla con VB esta
instrucción pierde un poco el sentido (siempre desde mi punto de vista).
Si además os digo que en todos los manuales o tutoriales de SQL que he visto, al hablar de
PROCEDURE, se dice que “no es común”, “es muy poco común”, “es muy poco utilizada”, y
comentarios similares... pues creo que tampoco nos perdemos gran cosa.
En definitiva, que así sabréis que existe “esto que llaman PROCEDURE”, y por eso lo dejo,
como mínimo, apuntado.
Desde mi punto de vista lo que hemos aprendido hasta el momento nos amplia nuestras
posibilidades de operar con Access, dado que SQL, combinado con VBA, nos permite realizar
acciones que con sólo las herramientas de Access quizá se hiciera complicado resolver, o quizá
nos sometiera a la utilización de procedimientos que, sin ser malos, pueden ser optimizados.
En el próximo capítulo comenzaremos un nuevo ciclo: ya no operaremos con datos, sino que
trabajaremos con el alma máter de Access: las tablas y su estructura.
¡Suerte!
10
Visítame en http://siliconproject.com.ar/neckkito/
CURSO DE SQL
CAPÍTULO 51
Índice de contenido
TRABAJAR CON TABLAS................................................................................................................2
DESEO UNA TABLA “A MEDIDA”.............................................................................................2
CREAR UNA TABLA.....................................................................................................................2
LA CLÁUSULA “CONSTRAINT”............................................................................................3
UNA PEQUEÑA ACLARACIÓN (PARA NO TENER QUE “RASCARNOS LA
CABEZA”).............................................................................................................................3
DEFINIR UN CAMPO QUE NO ADMITE DUPLICADOS: UNIQUE..............................3
DEFINIR UN CAMPO COMO CLAVE PRINCIPAL: PRIMARY KEY.............................4
DEFINIR UN CAMPO COMO REQUERIDO: NOT NULL...............................................5
DEFINIR UN CAMPO COMO AUTONUMÉRICO Y DEFINIR SU INTERVALO DE
INCREMENTO......................................................................................................................6
COMBINAR DEFINICIÓN DE PROPIEDADES................................................................8
DEFINIR UNA CLAVE EXTERNA: FOREING KEY.........................................................8
BORRAR UNA TABLA................................................................................................................10
CREAR ÍNDICES (con CREATE INDEX)..................................................................................10
ÍNDICES CON REGISTROS DUPLICADOS.........................................................................11
PROHIBIR VALORES NULOS EN EL ÍNDICE...............................................................12
IGNORAR VALORES NULOS EN EL ÍNDICE................................................................13
ÍNDICE CON REGISTROS NO DUPLICADOS....................................................................14
CREAR UN ÍNDICE CON CLAVE PRIMARIA................................................................15
ELIMINAR ÍNDICES...................................................................................................................15
MODIFICAR UNA TABLA..........................................................................................................15
AÑADIR CAMPOS..................................................................................................................16
BORRAR CAMPOS.................................................................................................................16
CREAR ÍNDICES (con ALTER TABLE)................................................................................17
CREAR UNA CLAVE PRINCIPAL....................................................................................17
CREAR UNA CLAVE EXTERNA......................................................................................17
MODIFICAR EL TIPO DE RELACIÓN........................................................................18
AÑADIR UNA REGLA DE VALIDACIÓN............................................................................20
ELIMINAR ÍNDICES..............................................................................................................20
PARA FINALIZAR EL CAPÍTULO (¡Y EL CURSO!)....................................................................21
1
Visítame en http://siliconproject.com.ar/neckkito/
TRABAJAR CON TABLAS
Veremos en este capítulo cómo podemos crearnos una tabla con SQL, definiendo sus campos,
cómo podemos definir también algunas de sus propiedades, cómo podemos crear claves
primarias, claves externas... Y también veremos cómo podemos modificar tablas: modificar o
eliminar columnas, eliminar índices...
teniendo en cuenta que utilizaremos <longitudCampo> en aquellos campos en los que tenga
sentido determinar una longitud. Si no indicamos la longitud el campo adoptará el valor por
defecto de Access.
Por ejemplo, vamos a crear la tabla TProductos con tres campos: [CodProd] (de tipo texto y de
longitud 5), [DescrProd] (de tipo texto y de longitud 25) e [ImportProd] (de tipo moneda).
…
Private Sub cmdCreaTProductos_Click()
On Error GoTo sol_err
Dim miSql As String
miSql = "CREATE TABLE TProductos (CodProd STRING (5), DescripProd STRING (25)," _
& " ImportProd CURRENCY)"
Creo_tabla:
CurrentDb.Execute miSql
MsgBox "La tabla 'TProductos' se ha creado correctamente", vbInformation, "OK"
Salida:
Exit Sub
sol_err:
If Err.Number = 3010 Then
DoCmd.DeleteObject acTable, "TProductos"
2 Algunos de los códigos que se utilizarán llevan control de errores. El error 3010 se produce cuando la tabla ya existe. Por eso, si
salta dicho error, el código borra la tabla existente y vuelve a crearla de nuevo en función de lo declarado en la SQL.
2
Visítame en http://siliconproject.com.ar/neckkito/
Resume Creo_tabla
Else
MsgBox "Se ha producido el error " & Err.Number & " -
" & Err.Description
Resume Salida
End If
End Sub
…
Nota: es posible que, tras ejecutar el código, no nos aparezca TProductos en la ventana de
base de datos o en el panel de navegación (según la versión de Access que utilicemos). Si
seleccionamos cualquier tabla que tengamos en la BD y pulsamos 'F5' se producirá una
actualización y nuestra tabla “aparecerá como por arte de magia”
LA CLÁUSULA “CONSTRAINT”
Para establecer limitaciones o definiciones en nuestros campos debemos utilizar la cláusula
CONSTRAINT. Avanzaremos que también la podemos utilizar para establecer relaciones con
otra tabla.
Por eso, en los códigos, os indicaré en color gris, como comentario de código, cómo sería la
SQL con esta utilización directa de las definiciones de las propiedades.
Lo importante es que lo veáis escrito de una manera u otra seamos capaces de entender “qué
dice” la SQL
3
Visítame en http://siliconproject.com.ar/neckkito/
…
Private Sub cmdUnique_Click()
On Error GoTo sol_err
Dim miSql As String
miSql = "CREATE TABLE TProductos (CodProd STRING (5) CONSTRAINT miIndice UNIQUE," _
& " DescripProd STRING (25), ImportProd CURRENCY)"
'----------Asignación directa------
' miSql = "CREATE TABLE TProductos (CodProd STRING UNIQUE, DescripProd STRING (25)," _
' & "ImportProd CURRENCY)"
'----------------------------------
Creo_tabla:
CurrentDb.Execute miSql
MsgBox "La tabla 'TProductos' se ha creado correctamente", vbInformation, "OK"
Salida:
Exit Sub
sol_err:
If Err.Number = 3010 Then
DoCmd.DeleteObject acTable, "TProductos"
Resume Creo_tabla
Else
MsgBox "Se ha producido el error " & Err.Number & " - " & Err.Description
Resume Salida
End If
End Sub
…
Fijaos que:
4
Visítame en http://siliconproject.com.ar/neckkito/
…
Private Sub cmdPrimaryKey_Click()
On Error GoTo sol_err
Dim miSql As String
miSql = "CREATE TABLE TProductos (CodProd STRING (5) CONSTRAINT miClave PRIMARY KEY," _
& " DescripProd STRING (25), ImportProd CURRENCY)"
'----------Asignación directa------
' miSql = "CREATE TABLE TProductos (CodProd STRING (5) PRIMARY KEY," _
' & " DescripProd STRING (25), ImportProd CURRENCY)"
'----------------------------------
Creo_tabla:
CurrentDb.Execute miSql
MsgBox "La tabla 'TProductos' se ha creado correctamente", vbInformation, "OK"
Salida:
Exit Sub
sol_err:
If Err.Number = 3010 Then
DoCmd.DeleteObject acTable, "TProductos"
Resume Creo_tabla
Else
MsgBox "Se ha producido el error " & Err.Number & " - " & Err.Description
Resume Salida
End If
End Sub
…
[CodProd] de tipo TEXTO y longitud 5 – Restringido - será mi clave, que será clave principal
En nuestra tabla TProductos definiremos una clave principal ([CodProd]) y exigiremos que se
deba rellenar el campo [DescripProd].
El código sería:
5
Visítame en http://siliconproject.com.ar/neckkito/
…
Private Sub cmdNotNull_Click()
On Error GoTo sol_err
Dim miSql As String
miSql = "CREATE TABLE TProductos (CodProd STRING (5) CONSTRAINT miClave PRIMARY KEY," _
& " DescripProd STRING (25) CONSTRAINT miNoNulo NOT NULL, ImportProd CURRENCY)"
'----------Asignación directa------
' miSql = "CREATE TABLE TProductos (CodProd STRING (5) PRIMARY KEY," _
' & " DescripProd STRING (25) NOT NULL, ImportProd CURRENCY)"
'----------------------------------
Creo_tabla:
CurrentDb.Execute miSql
MsgBox "La tabla 'TProductos' se ha creado correctamente", vbInformation, "OK"
Salida:
Exit Sub
sol_err:
If Err.Number = 3010 Then
DoCmd.DeleteObject acTable, "TProductos"
Resume Creo_tabla
Else
MsgBox "Se ha producido el error " & Err.Number & " - " & Err.Description
Resume Salida
End If
End Sub
…
No creo que haga ya falta insistir en la estructura del CONSTRAINT...NOT NULL, ¿verdad?
Por intuición ya deberíamos saber, pues, cómo podría ser nuestra SQL, aunque tiene un
“pequeño truco”. Sería la que aparece en el siguiente código:
6
Visítame en http://siliconproject.com.ar/neckkito/
…
Private Sub cmdAutonumerico_Click()
On Error GoTo sol_err
Dim miSql As String
miSql = "CREATE TABLE TProductos (IdProd AUTOINCREMENT(1,3) CONSTRAINT miClave PRIMARY KEY," _
& " CodProd STRING (5), DescripProd STRING (25), ImportProd CURRENCY)"
'----------Asignación directa------
' miSql = "CREATE TABLE TProductos (IdProd AUTOINCREMENT(1,3) PRIMARY KEY," _
' & " CodProd STRING (5), DescripProd STRING (25), ImportProd CURRENCY)"
'----------------------------------
Creo_tabla:
CurrentDb.Execute miSql
MsgBox "La tabla 'TProductos' se ha creado correctamente", vbInformation, "OK"
Salida:
Exit Sub
sol_err:
If Err.Number = 3010 Then
DoCmd.DeleteObject acTable, "TProductos"
Resume Creo_tabla
Else
MsgBox "Se ha producido el error " & Err.Number & " - " & Err.Description
Resume Salida
End If
End Sub
…
Si nos fijamos hemos definido el tipo de campo [IdProd] como AUTOINCREMENT (si
hubiéramos utilizado COUNTER funcionaría exactamente igual), y, entre paréntesis, le hemos
pasado dos valores. Supongo que alguien se preguntará: “¿Y qué significan?”.
7
Visítame en http://siliconproject.com.ar/neckkito/
COMBINAR DEFINICIÓN DE PROPIEDADES
Como apunte final a lo explicado hasta ahora debo deciros
que las anteriores propiedades pueden combinarse en una
misma SQL (por si había alguna duda).
…
Private Sub cmdTProductosCombinado_Click()
On Error GoTo sol_err
Dim miSql As String
miSql = "CREATE TABLE TProductos (IdProd COUNTER (1,5) CONSTRAINT miClave PRIMARY KEY," _
& " CodProd STRING (5) CONSTRAINT miIndice UNIQUE NOT NULL," _
& " DescripProd STRING (25) CONSTRAINT miIndice2 UNIQUE, ImportProd CURRENCY)"
'----------Asignación directa------
' miSql = "CREATE TABLE TProductos (IdProd COUNTER (1,5) PRIMARY KEY," _
' & " CodProd STRING (5)UNIQUE NOT NULL, DescripProd STRING (25) UNIQUE," _
' & " ImportProd CURRENCY)"
'----------------------------------
Creo_tabla:
CurrentDb.Execute miSql
MsgBox "La tabla 'TProductos' se ha creado correctamente", vbInformation, "OK"
Salida:
Exit Sub
sol_err:
If Err.Number = 3010 Then
DoCmd.DeleteObject acTable, "TProductos"
Resume Creo_tabla
Else
MsgBox "Se ha producido el error " & Err.Number & " - " & Err.Description
Resume Salida
End If
End Sub
…
Como podéis observar el proceso es tan simple como añadir la definición de las propiedades
una tras otra.
Por ejemplo,
3 Recordad que, en SQL, para un campo autonumérico AUTOINCREMENT y COUNTER son sinónimos. En el ejemplo anterior he
utilizado AUTOINCREMENT, y en el ejemplo que sigue he utilizado COUNTER.
8
Visítame en http://siliconproject.com.ar/neckkito/
Si nos fijamos en la tabla TPedidos diríamos que:
• Id es la clave principal
• NumMes es la clave externa, porque nos relaciona la tabla con una tabla externa, que
es TMeses.
…
Private Sub cmdForeingKey_Click()
Dim miSql As String
miSql = "CREATE TABLE TPedidos (Id LONG CONSTRAINT miClave PRIMARY KEY," _
& " NumMes LONG, Cliente STRING (25), ImpPedido CURRENCY," _
& " CONSTRAINT miClaveExt FOREIGN KEY (NumMes) REFERENCES TMeses)"
CurrentDb.Execute miSql
MsgBox "La tabla 'TPedidos' se ha creado correctamente", vbInformation, "OK"
End Sub
…
Para eliminar toda duda la SQL, con nombres de campo diferentes, nos debería haber quedado
así:
…
miSql = "CREATE TABLE TPedidos (Id LONG CONSTRAINT miClave PRIMARY KEY," _
& " NumMes2 LONG, Cliente STRING (25), ImpPedido CURRENCY," _
& " CONSTRAINT miClaveExt FOREIGN KEY (NumMes2) REFERENCES TMeses (NumMes))"
…
4 ¿Por qué el código no lleva control de errores? Porque desde el momento en que establecemos relaciones no podemos borrar la
tabla porque Access no nos dejará: nos dirá que no se puede borrar la tabla porque existen relaciones entre tablas. El proceso
sería, pues, primero eliminar la relación y después borrar la tabla. Como aún no sabemos cómo eliminar relaciones (¡pero lo
veremos en breve!) omito el control de errores, por ahora.
9
Visítame en http://siliconproject.com.ar/neckkito/
BORRAR UNA TABLA
Así como podemos crear una tabla con SQL también la
podemos borrar. Para ello utilizaremos la instrucción DROP.
…
Private Sub cmdBorraTProductos_Click()
On Error GoTo sol_err
Dim miSql As String
CurrentDb.Execute miSql
MsgBox "La tabla 'TProductos' se ha eliminado correctamente", vbInformation, "OK"
Salida:
Exit Sub
sol_err:
If Err.Number = 3376 Then
MsgBox "La tabla 'TProductos' no se puede eliminar porque no existe", _
vbCritical, "TABLA INEXISTENTE"
Else
MsgBox "Se ha producido el error " & Err.Number & " - " & Err.Description
End If
Resume Salida
End Sub
…
Como vemos en el código, si la tabla no existiera nos saltaría el error 3376. El código gestiona
dicho error a través del control de errores.
Así pues, podemos, con ayuda de SQL, crear un índice (o varios) en una tabla.
Vamos a crearnos la tabla TProductos con el código para crear una BD más simple que hemos
aprendido prácticamente a principio de este capítulo; es decir, TProductos sólo con los campos
(sin ningún tipo de restricciones).
10
Visítame en http://siliconproject.com.ar/neckkito/
podemos crear un índice sobre uno o más campos, ¿verdad? ).
…
Private Sub cmdCreaIndice_Click()
Dim miSql As String
CurrentDb.Execute miSql
MsgBox "Índices creados satisfactoriamente", vbInformation, "OK"
End Sub
…
Alguien podría pensar: “¿Y qué hemos conseguido con lo anterior?”. OK. En la tabla TProductos
yo he introducido varios registros, de la manera siguiente:
Conclusión: que al haber convertido en índices los dos campos se produce, automáticamente,
una ordenación de la siguiente manera:
¿Lo vemos?
Pues ahora vamos a cambiar la ordenación del índice sobre el campo [DescripProd].
11
Visítame en http://siliconproject.com.ar/neckkito/
Aprovecharemos para ver cómo declaro explícitamente también la ordenación sobre el campo
[CodProd]. Nuestro código quedaría así:
…
Private Sub cmdCreaIndice2_Click()
Dim miSql As String
CurrentDb.Execute miSql
MsgBox "Índices creados satisfactoriamente", vbInformation, "OK"
End Sub
…
Y si abro la tabla TProductos (¡es necesario borrarla y volverla a crear antes de realizar el
proceso!) los resultados son los siguientes:
Como observamos, el campo [CodProd] muestra una ordenación ascendente porque así lo
hemos indicado en la SQL, a través de ASC, mientras que [DescripProd] muestra una
ordenación descendente porque hemos indicado que así fuera a través de DESC.
12
Visítame en http://siliconproject.com.ar/neckkito/
…
Private Sub cmdCreaIndiceDisallowNull_Click()
Dim miSql As String
CurrentDb.Execute miSql
MsgBox "Índices creados satisfactoriamente", vbInformation, "OK"
End Sub
…
y no puedo añadir más registros hasta que no introduzca información en el campo [CodProd].
…
Private Sub cmdCreaIndiceIgnoreNull_Click()
Dim miSql As String
13
Visítame en http://siliconproject.com.ar/neckkito/
CurrentDb.Execute miSql
MsgBox "Índices creados satisfactoriamente",
vbInformation, "OK"
End Sub
…
Por ejemplo, en TProductos queremos que el campo [CodProd] sea índice sin duplicados.
Deberíamos programar el siguiente código:
…
Private Sub cmdCreaIndiceSinDuplicados_Click()
Dim miSql As String
CurrentDb.Execute miSql
MsgBox "Índice creado satisfactoriamente", vbInformation, "OK"
End Sub
…
…
Private Sub cmdCreaIndiceSinDuplicados2_Click()
Dim miSql As String
CurrentDb.Execute miSql
MsgBox "Índice creado satisfactoriamente", vbInformation, "OK"
End Sub
…
14
Visítame en http://siliconproject.com.ar/neckkito/
CREAR UN ÍNDICE CON CLAVE PRIMARIA
Si queremos crear un índice asignando una clave principal
(ojo, sólo puede existir un único índice que sea clave
principal) seguiremos la estructura que ya conocemos...
…
Private Sub cmdCreaIndicePrimary_Click()
Dim miSql As String
CurrentDb.Execute miSql
MsgBox "Índice creado satisfactoriamente", vbInformation, "OK"
End Sub
…
¿Fácil, no?
ELIMINAR ÍNDICES
Para eliminar un índice debemos utilizar la estructura:
Vamos a suponer que hemos creado el índice miIndice sobre la tabla TProductos utilizando
cualquiera de los métodos explicados anteriormente. Vamos a eliminar ese índice a través del
siguiente código:
…
Private Sub cmdBorraIndice_Click()
Dim miSql As String
CurrentDb.Execute miSql
MsgBox "Índice eliminado correctamente", vbInformation, "OK"
End Sub
…
Y listo.
15
Visítame en http://siliconproject.com.ar/neckkito/
como índices.
AÑADIR CAMPOS
La estructura para añadir un campo sería:
Supongamos que en nuestra tabla TMeses queremos añadir el campo [Estacion], de tipo texto
con una longitud máxima de 10 caracteres. Nuestro código debería ser así:
…
Private Sub cmdModifAñadeCampos_Click()
Dim miSql As String
CurrentDb.Execute miSql
MsgBox "El campo se ha creado correctamente", vbInformation, "OK"
End Sub
…
BORRAR CAMPOS
¡Caramba! Nos hemos equivocado y debemos borrar el campo [Estacion] que acabamos de
crear. ¿Cómo lo hacemos?
…
Private Sub cmdModifBorraCampos_Click()
Dim miSql As String
CurrentDb.Execute miSql
MsgBox "El campo se ha borrado correctamente", vbInformation, "OK"
End Sub
…
16
Visítame en http://siliconproject.com.ar/neckkito/
CREAR ÍNDICES (con ALTER TABLE)
Al igual que hemos hecho con los campos podemos
modificar los índices de las tablas. De hecho, si os fijáis, es
como “otro sistema paralelo” a lo que comentábamos en
apartados anteriores utilizando, en aquel caso, “CREATE
INDEX”
…
Private Sub cmdModifCreaClavePrincipal_Click()
Dim miSql As String
CurrentDb.Execute miSql
MsgBox "Clave principal creada correctamente", vbInformation, "OK"
End Sub
…
Vamos a asegurarnos que creamos desde cero la tabla TPedidos, simple y llana (si ya la
tuviéramos creada la borramos), eso sí, con una clave principal. Para crearla podemos ejecutar
la siguiente SQL:
…
miSql = "CREATE TABLE TPedidos (Id LONG CONSTRAINT miClave PRIMARY KEY," _
& " NumMes LONG, Cliente STRING (25), ImpPedido CURRENCY)"
…
Vamos a crear una clave externa con el campo [NumMes] entre las tablas TMeses y TPedidos.
Es decir:
17
Visítame en http://siliconproject.com.ar/neckkito/
…
Private Sub cmdModifCreaClaveExterna_Click()
Dim miSql As String
miSql = "ALTER TABLE TPedidos ADD CONSTRAINT miClaveExt FOREIGN KEY (NumMes)" _
& " REFERENCES TMeses(NumMes)"
CurrentDb.Execute miSql
MsgBox "La clave externa se ha creado correctamente", vbInformation, "OK"
End Sub
…
Os recuerdo que para comprobar la “efectividad” de nuestro código basta con abrir la ventana
relaciones y mostrar estas dos tablas: debería aparecernos la relación.
¿Alguien se ha perdido? Espero que esta imagen sirva para refrescar memorias:
También podemos definir estas dos propiedades de la relación en nuestra SQL, realizando una
pequeña modificación en la estructura. Es decir:
18
Visítame en http://siliconproject.com.ar/neckkito/
Sin embargo, si intentamos ejecutar un código utilizando
DoCmd.RunSQL o CurrentDb.Execute no hacemos más que
obtener errores, o bien de la cláusula CONSTRAINT o bien
de la propia instrucción SQL (y eso lo sé por experiencia
propia... je, je...).
…
Private Sub cmdModifCreaClaveExterna_Click()
Dim miSql As String
miSql = "ALTER TABLE TPedidos ADD CONSTRAINT miClaveExt FOREIGN KEY (NumMes)" _
& " REFERENCES TMeses(NumMes) ON UPDATE CASCADE"
CurrentProject.Connection.Execute miSql
…
Private Sub cmdModifCreaClaveExterna_Click()
Dim miSql As String
miSql = "ALTER TABLE TPedidos ADD CONSTRAINT miClaveExt FOREIGN KEY (NumMes)" _
& " REFERENCES TMeses(NumMes) ON DELETE CASCADE"
CurrentProject.Connection.Execute miSql
…
miSql = "ALTER TABLE TPedidos ADD CONSTRAINT miClaveExt FOREIGN KEY (NumMes)" _
& " REFERENCES TMeses(NumMes) ON UPDATE CASCADE ON DELETE CASCADE"
…
19
Visítame en http://siliconproject.com.ar/neckkito/
AÑADIR UNA REGLA DE VALIDACIÓN
Podemos modificar el campo de una tabla para validar las
entradas de los usuarios. Para ello utilizaríamos la
estructura:
…
Private Sub cmdCreaReglaValidacion_Click()
Dim miSql As String
CurrentProject.Connection.Execute miSql
MsgBox "Regla de validación creada correctamente", vbInformation, "OK"
End Sub
…
Nota: si, una vez ejecutada la SQL, abrimos TVentas en vista diseño y sacamos las
propiedades del campo [ImpVta] veremos que no hay ninguna regla de validación especificada.
Eso no debe preocuparnos: si intentamos escribir un registro con una venta en negativo nos
saltará un aviso de que ese valor no cumple con la regla de validación.
ELIMINAR ÍNDICES
El proceso de eliminar índices sería muy parecido a lo que ya conocemos con ADD, pero
utilizando, en su lugar, DROP.
Para practicar un poco eliminaremos, de manera manual, la clave principal de la tabla TMeses.
Una vez eliminada la clave principal de esa tabla la volvemos a crear a través de una SQL,
dándole nombre al índice
Eso ya deberíamos saber cómo hacerlo, pero para “refrescar memorias” os indico aquí cómo
sería la SQL
20
Visítame en http://siliconproject.com.ar/neckkito/
…
miSql = "ALTER TABLE TMeses ADD CONSTRAINT miSuperClavePpal PRIMARY KEY(NumMes)"
…
…
Private Sub cmdModifBorraIndices_Click()
Dim miSql As String
CurrentDb.Execute miSql
MsgBox "Clave principal eliminada correctamente", vbInformation, "OK"
End Sub
…
Si abrimos, tras su ejecución, la tabla TMeses, veremos que nuestra clave principal ha
desaparecido.
Siguiendo el símil, hemos visto “los principales monumentos en nuestro viaje”, pero conocer
SQL a fondo... eso sólo lo conseguiremos si nos “quedamos a vivir” en la ciudad.
Tampoco debemos perder de vista que este curso está orientado a trabajar en Access lo cual
nos implica, entre otras, dos cosas:
La primera, que hay que tener presente que SQL es utilizado en otros SGBD 6, y operaciones
que funcionan en unos no funcionan en otros. No nos volvamos “excesivamente locos”
probando y probando algo que no nos funciona sin cercionarnos de que, efectivamente, eso sí
funciona en nuestro SGBD.
Segunda, que nuestro entorno de trabajo es Access, y, más en concreto, Access y VBA para
21
Visítame en http://siliconproject.com.ar/neckkito/
Access. Eso nos da la ventaja de que podemos trabajar con muchas herramientas que se
complementan o se sustituyen unas a otras. Para clarificar lo que quiero decir, recordemos que
tenemos las consultas como objeto en Access, fácilmente manipulables a nivel visual.
Si tenemos problemas con la programación de alguna SQL
quizá podríamos plantearnos el utilizar una consulta-objeto
de Access para realizar la misma función, por ejemplo.
Espero que este manual os haya sido de utilidad. Para quejas y demás poneos en contacto con
mi editor (¡Anda, pero si no tengo editor! :P).
Un saludo, y...
¡suerte!
22
Visítame en http://siliconproject.com.ar/neckkito/