sábado, 10 de marzo de 2012

De que sirve

De que sirve una palabra si no hay nadie que la oiga
De que sirve el dinero si no hay nadie con quien compartirlo
De que sirven las esperanzas si no hay nadie que las alimente
De que sirve la luz si tu ausencia es oscuridad
De que sirve vencer al mundo si ante ti estoy derrotado
De que sirve todo lo que logre si nunca existirá el motivo
De que sirve dar todo por amor, si el amor es cruel
De que sirve...
De que sirve...
De que sirve lo hoy escrito si tal vez nadie llegue a leerlo.

José Angel Villalobos Sambrano.

xxxxxxxxxxxxxxxxx

Nunca entregues realidades
a quien vive en las fantasías,
porque incluso la mas fuerte
de las realidades sucumbe ante
una de esas fantasías!!

José Angel Villalobos Sambrano

xxxxxxxxxxx

Mi consuelo entre tanta soledad
es recordar tu bella sonrisa,
es imaginar tu cabello cuando
lo roza la brisa, son tus lindos
ojos que brillan cual estrellas
en el anochecer dejando con cada
mirada la luz que alumbra mi vida
cual sol alumbra a la tierra
en cada amanecer!!

José Angel Villalobos Sambrano

xxxxxxxxxxxxxxxxxx

Algunas veces creo ser el viento
y llego hasta a tí, roso tu cara,
tus labios, tu pelo, tu cuerpo,
y al darme cuenta que estoy aqui
pierdo la libertad que mis sueños
despiertos me proporcionan.

José Angel Villalobos Sambrano

Amor no correspondido

Cuando estas tan cerca de mí,
por momentos imagino que me perteneces
mi corazón comienza a latir y mi amor
por ti florece, tu sonrisa es mi ilusión
tu alegría mi felicidad, pero no correspondes
a mi amor y yo solo tengo soledad.

Imaginar que serás para otro, me hace
naufragar en un mar tan profundo, en el
cual me puedo ahogar, me duele que no
exista la esperanza, mas aún que no me la
logres dar, dejando mi amor atrapado
no dejandolo volar.

Mi amor no morirá aunque no le correspondas
el siempre aparecerá como lo hace en el agua
la onda cuando una piedra rompe su calma,
como tu clavas esta pena en mi alma.

José Angel Villalobos Sambrano

La mente

En mi mente hay un perfecto arreglo de ideas,
en donde estoy? en donde estuve? a donde voy?;
algunas ideas confusas por momentos estropean
mi razón, trato de escapar de ellas y el resueltado es peor
porque son reflejo de mi realidad, son un conjunto de
imagenes imborrables, aún en mi estado de perfecto
entendimiento de mis acciones ante la realidad,
el misterio de la mente humana es algo por encima
de cualquier razonamiento.

José Angel Villalobos Sambrano

Palabras & Acciones

PALABRAS

Son un mundo inanimado
Son como el viento al pasar
Son composición de promesas futuras
Son tu vocablo para hablar
Son una arreglo de silabas
Son lo que puedes decir sin sentir
Son palabras ...

ACCIONES

Ellas siempre hablan de ti
Ellas te hacen quien eres
Ellas te hacen notar
Ellas no se pueden borrar
Ellas son mas que palabras !!!


José Angel Villalobos Sambrano

Frenesí en la habitación

Cada momento es único, tu cuerpo y mi cuerpo lo saben,
esa pasión que se desborda y nos lleva a las redes del placer
recorro  tu cuerpo poco a poco y voy descubriendo cada
uno de los secretos que este guarda, y el sonido de nuestras
calientes respiración se juntan y forman una melodía
excitante, melodía que no quiero parar de escuchar,
mientras nuestros cuerpos se unen formando uno solo,
y el ardiente sudor es protagonista en la habitación, y somos
tu y yo esclavos de tan desbordante pasión.

José Angel Villalobos Sambrano

fantasía o verdad?

Que importa si es realidad, que importa si es fantasía
lo unico cierto es que me siento vivo, mucho antes
camine por lo incierto y pense nunca encontrar salidas,
quizás ahora camino por lo cierto y son muchas las salidas
y no lo sé, así de misteriosa es esta vida, inevitable es
preguntar será luz? será oscuridad?, será calma?
será tempestad?, será alegría? será tristeza?,
será verdad? será falsedad? de cualquier forma
solo me basta estar vivo para comprobar si es
fantasía o si es verdad.

José Angel Villalobos Sambrano

Frustración

Te calcome el alma, acelera
todo los nervios de tu cuerpo,
como si estuvieses en la desesperación
por instantes pierdes el control,
y es dificil razonar, es sin duda la
frustración que se apodera de ti
y no te deja pensar.

José Angel Villalobos Sambrano

Un instante en el Jarillo

Me falta un poco el aire, pero
la naturaleza me suple de él,
explendoroso es el paisaje,
en lontananza puedo ver
su infinita belleza.

Miles de piezas que juntas
forman el momento perfecto,
las aves y el verdor de la
vegetación son los únicos
protagonistas, el sol aún
no aparece, pero ya siento
su presencia.

Más allá de las palabras es
solo el momento, tan perfecto
como la creación, cerca estan
las voces de los que me acompañan
y la neblina se apodera del lugar.

José Angel Villalobos Sambrano

Dia de las madres

Eres amor y ternura
Eres esperanza y bondad
Eres la palabra segura en los
momentos de oscuridad
Eres dedicación y sacrificio
Eres experiencia y verdad
Eres bella mujer de este mundo
tu eres mamá!!!

José Angel Villalobos Sambrano

Enamorado de ti

Los sentimientos se hacen tan fuertes
no los puedos controlar me hacen debil
y vulnerable ante ti, y aun así deseo
continuar.

Siento perder mi poder de decidir
cada vez que estas a mi lado,
definitivamente estoy de ti enamorado.

Hoy que entiendo que no eres para mi,
solo hay dolor en mi corazón, me pierdo
en la oscuridad, no encuentro respuestas
siento perder la razón.

Inspiración para mi

En cada instante te pienso, es algo que no
puedo evitar, ocupas los rincones de mi mente
sin que te pueda tocar, mientras espero me perturba
el ruido que causa el silencio, pero si he de continuar
no hay duda que lo hago por ti!
Tal vez son varios tus nombres pero inspiración
eres para mi!, solo espero no equivocarme,
solo espero contigo ser feliz.

José Angel Villalobos Sambrano

Realidad

Son muchas verdades, son muchas mentiras
este es el mundo real, donde la gente no vive
sino sobrevive, inventando todos los días
un problema diferente, un motivo para complicar
sus vidas mucho mas de lo que por naturaleza ya es,
amigos, compañeros, familia y demás todos en un
mundo donde la justificación de un momento feliz
son un conjunto de momentos tristes pasados, yo
en el centro de este mundo contemplando con
distintas emociones el pasar del tiempo y mirando
como se desvanecen los sueños entre los
vientos de la realidad.

José Angel Villalobos Sambrano

xxxxxxxxxxxx

Mas allá de mis lamento estan mis aspiraciones,
hoy me aguanto lo que siento,  sin duda
sentir no da soluciones, si me duele no te miento,
y mis palabras lo suponen, me estoy muriendo
por dentro, pero aguantar y seguir es sin duda
la mejor de las opciones!!!

José Angel Villalobos Sambrano

Miro

Miro  al horizonte y que miro?
miro la incertidumbre de no saber a donde ir,
miro la desesperanza   crecer cada día mas,
miro que todo los caminos que transito me
llevan al mismo lugar, y al definir ese lugar
encuentro que es donde no quiero estar,

Miro que esfuerzos quedan atrás y se
esfuman como el humo en el aire, miro
ilusiones convertidas en desilusiones,
miro a la soledad como a mi unica
compañera, miro a la tristeza a los ojos
y me provoca llorar y no puedo, miro
como resultado el fracaso y me da miedo,
miro... miro... que el mundo ni la vida
estan contra mí, pero que de todos modo
hay una vida y un mundo al cual debo vencer!!

José Angel Villalobos Sambrano

Si me preguntas te lo dire

Llega al más grande de los volcanes, se sumerge
en su ardiente lava sin quemarse,
es capaz de subir el everest hasta lo mas
alto y permanecer ahí desnuda sin congelarse

Es capaz de sumergirse en el más profundo de
los mares, y mirar por horas su belleza, respirar
entre sus aguas sin ahogarse.

Atraviesa la atmosfera y admira la belleza del
universo sin asfixiarse

Es capaz de encontrarse en medio de la selva
luchar contra leones sin acobardarse,
atraviesa la mas grande tormenta llena de
vientos y rayos sin paralizarse

Solo ella es tan libre, tan unica como para
lograrlo todo, sin me preguntas su nombre
te lo dire...

José Angel  Villalobos Sambrano

Mira a través de mis ojos

Mira a través de mis ojos dime tu que ves?,
dime si hay maldad, dime si hay bondad!

Mira a través de mis ojos, dime si hay verdad!
dime si hay falsedad!

Mira a través de mis ojos, dime de que soy capaz,
dime en que puedo cambiar,
dime si existo a través de ellos o soy un simple
espejismo que se puede esfumar!

Mira a través de mis ojos hoy tienes la oportunidad
aqui ante ti y mirandote no hay nadie más, dime
si al mirarlos miras la alegría en el futuro o miras
la tempestad!

Mira a través de mis ojos antes que una lagrima
pueda brotar, mira amada mia, que esto es cierto
tan cierto como que el sol saldrá!!

José Angel Villalobos Sambrano

Un instante

Aqui estoy comtemplandote en silencio,
muchas veces te miro pasar
tan bella y tan radiante y no me atrevo
ni una sola palabra murmurarte
se congela todo mi cuerpo cuando
te acercas a mi, y aunque no quiera
toda mi atención se concentra en ti.


José Angel Villalobos Sambrano

jueves, 8 de marzo de 2012

Introducción SQL (DML)

DML (lenguaje de manipulación de datos)
Inserción de datos

La adición de datos a una tabla se realiza mediante la instrucción INSERT. Su sintaxis fundamental es:

INSERT INTO tabla [(listaDeCampos)]
VALUES (valor1 [,valor2 ...])

La tabla representa la tabla a la que queremos añadir el registro y los valores que siguen a VALUES son los valores que damos a los distintos campos del registro. Si no se especifica la lista de campos, la lista de valores debe seguir el orden de las columnas según fueron creados (es el orden de columnas según las devuelve el comando DESCRIBE).

La lista de campos a rellenar se indica si no queremos rellenar todos los campos. Los campos no rellenados explícitamente con la orden INSERT, se rellenan con su valor por defecto (DEFAULT) o bien con NULL si no se indicó valor alguno. Si algún campo tiene restricción de tipo NOT NULL, ocurrirá un error si no rellenamos el campo con algún valor.

Por ejemplo, supongamos que tenemos una tabla de clientes cuyos campos son: dni, nombre, apellido1, apellido2, localidad y dirección; supongamos que ese es el orden de creación de los campos de esa tabla y que la localidad tiene como valor por defecto Palencia y la dirección no tiene valor por defecto. En ese caso estas dos instrucciones son equivalentes:


INSERT INTO clientes
VALUES('11111111','Pedro','Gutiérrez', 'Crespo',DEFAULT,NULL);

INSERT INTO clientes(dni,nombre,apellido1,apellido2)
VALUES('11111111','Pedro','Gutiérrez', 'Crespo');


Son equivalentes puesto que en la segunda instrucción los campos no indicados se rellenan con su valor por defecto y la dirección no tiene valor por defecto. La palabra DEFAULT fuerza a utilizar ese valor por defecto. El uso de los distintos tipos de datos debe de cumplir los requisitos ya comentados en temas anteriores.

Relleno de registros a partir de filas de una consulta


Hay un tipo de consulta, llamada de adición de datos, que permite rellenar datos de una tabla copiando el resultado de una consulta. Ese relleno se basa en una consulta SELECT que poseerá los datos a añadir. Lógicamente el orden de esos campos debe de coincidir con la lista de campos indicada en la instrucción INDEX. Sintaxis:

INSERT INTO tabla (campo1, campo2,...)
SELECT campoCompatibleCampo1, campoCompatibleCampo2,...
FROM tabla(s)
[...otras cláusulas del SELECT...]


Ejemplo:

INSERT INTO clientes2004 (dni, nombre, localidad, direccion)
SELECT dni, nombre, localidad, direccion
FROM clientes
WHERE problemas=0;


Actualización de registros


La modificación de los datos de los registros lo implementa la instrucción UPDATE. Sintaxis:


UPDATE tabla
SET columna1=valor1 [,columna2=valor2...]
[WHERE condición]


Se modifican las columnas indicadas en el apartado SET con los valores indicados. La cláusula WHERE permite especificar qué registros serán modificados.Ejemplos:

UPDATE clientes SET provincia='Ourense'
WHERE provincia='Orense';


UPDATE productos SET precio=precio*1.16;


El primer dato actualiza la provincia de los clientes de Orense para que aparezca como Ourense. El segundo UPDATE incrementa los precios en un 16%. La expresión para el valor puede ser todo lo compleja que se desee:

UPDATE partidos SET fecha= NEXT_DAY(SYSDATE,'Martes')
WHERE fecha=SYSDATE;


Incluso se pueden utilizar subconsultas:


UPDATE empleados
SET puesto_trabajo=(SELECT puesto_trabajo
FROM empleados
WHERE id_empleado=12)
WHERE seccion=23;


Esta consulta coloca a todos los empleados de la sección 23 el mismo puesto de trabajo que el empleado número 12. Este tipo de actualizaciones sólo son válidas si el subselect devuelve un único valor, que además debe de ser compatible con la columna que se actualiza. Hay que tener en cuenta que las actualizaciones no pueden saltarse las reglas de integridad que posean las tablas.

Borrado de registros


Se realiza mediante la instrucción DELETE:


DELETE [FROM] tabla
[WHERE condición]


Es más sencilla que el resto, elimina los registros de la tabla que cumplan la condición indicada. Ejemplos:


DELETE FROM empleados
WHERE seccion=23;


DELETE FROM empleados
WHERE id_empleado IN (SELECT id_empleado FROM errores_graves);


Hay que tener en cuenta que el borrado de un registro no puede provocar fallos de integridad y que la opción de integridad ON DELETE CASCADE, hace que no sólo se borren los registros indicados en el SELECT, sino todos los relacionados.

Comando MERGE

Sin duda alguna el comando más poderoso del lenguaje de manipulación de Oracle es MERGE. Este comando sirve para actualizar los valores de los registros de una tabla a partir de valores de registros de otra tabla o consulta. Permite pues combinar los datos de dos tablas a fin de actualizar la primera Supongamos que poseemos una tabla en la que queremos realizar una lista de localidades con su respectiva provincia. 


Las localidades están ya rellenadas, nos faltan las provincias. Resulta que tenemos otra tabla llamada clientes en la que tenemos datos de localidades y provincias, gracias a esta tabla podremos rellenar los datos que faltan en la otra. La situación se muestra en la ilustración siguiente.          
  
La sintaxis del comando MERGE es:

MERGE INTO tabla alias
USING (instrucción SELECT) alias
ON (condición de unión)
WHEN MATCHED THEN
UPDATE SET col1=valor1 [col2=valor2]
WHEN NOT MATCHED THEN
INSERT (listaDeColumnas)
VALUES (listaDeValores)

MERGE compara los registros de ambas tablas según la condición indicada en el apartado ON. Compara cada registro de la tabla con cada registro del SELECT. Los apartados de la sintaxis significan lo siguiente:

  1.  tabla es el nombre de la tabla que queremos modificar
  2.  USING. En esa cláusula se indica una instrucción SELECT tan compleja como queramos que muestre una tabla que contenga los datos a partir de los cuales se modifica la tabla
  3.  ON. permite indicar la condición que permite relacionar los registros de la tabla con los registros de la consulta SELECT
  4.  WHEN MATCHED THEN. El UPDATE que sigue a esta parte se ejecuta cuandol a condición indicada en el apartado ON sea cierta para los dos registros actuales.
  5.  WHEN NOT MATCHED THEN. El INSERT que sigue a esta parte se ejecuta para cada registro de la consulta SELECT que no pudo ser relacionado con ningún registro de la tabla.

Para el ejemplo descrito antes la instrucción MERGE sería:

MERGE INTO localidades l
USING (SELECT * FROM clientes) c
ON (l.localidad=clientes.localidad)
WHEN MATCHED THEN
UPDATE SET l.provincia=c.provincia
WHEN NOT MATCHED THEN
INSERT (localidad, provincia)
VALUES (c.localidad, c.provincia);

El resultado es la siguiente tabla de localidades:


Transacciones 

Como se ha comentado anteriormente, una transacción está formada por una serie de instrucciones DML. Una transacción comienza con la primera instrucción DML que se ejecute y finaliza con alguna de estas circunstancias:
  1. Una operación COMMIT o ROLLBACK
  2.  Una instrucción DDL (como ALTER TABLE por ejemplo)
  3.  Una instrucción DCL (como GRANT)
  4.  El usuario abandona la sesión
  5.  Caída del sistema

Hay que tener en cuenta que cualquier instrucción DDL o DCL da lugar a un COMMIT implícito, es decir todas las instrucciones DML ejecutadas hasta ese instante pasan a ser definitivas.

COMMIT
La instrucción COMMIT hace que los cambios realizados por la transacción sean definitivos, irrevocables. Sólo se debe utilizar si estamos de acuerdo con los cambios, conviene asegurarse mucho antes de realizar el COMMIT ya que las instrucciones ejecutadas pueden afectar a miles de registros. Además el cierre correcto de la sesión da lugar a un COMMIT, aunque siempre conviene ejecutar explícitamente esta instrucción a fin de asegurarnos de lo que hacemos.

ROLLBACK
Esta instrucción regresa a la instrucción anterior al inicio de la transacción, normalmente el último COMMIT, la última instrucción DDL o DCL o al inicio de sesión. Anula definitivamente los cambios, por lo que conviene también asegurarse de esta operación. Un abandono de sesión incorrecto o un problema de comunicación o de caída del sistema dan lugar a un ROLLBACK implícito.

SAVEPOINT
Esta instrucción permite establecer un punto de ruptura. El problema de la combinación ROLLBACK/COMMIT es que un COMMIT acepta todo y un ROLLBACK anula todo. SAVEPOINT permite señalar un punto intermedio entre el inicio de la transacción y la situación actual. Su sintaxis es:

...instrucciones DML...
SAVEPOINT nombre
....instrucciones DML...

Para regresar a un punto de ruptura concreto se utiliza ROLLBACK TO SAVEPOINT seguido del nombre dado al punto de ruptura. Cuando se vuelve a un punto marcado, las instrucciones que siguieron a esa marca se anulan definitivamente. estado de los datos durante la transacción.

Si se inicia una transacción usando comandos DML hay que tener en cuenta que:

  1. Se puede volver a la instrucción anterior a la transacción cuando se desee
  2.  Las instrucciones de consulta SELECT realizadas por el usuario que inició la transacción muestran los datos ya modificados por las instrucciones DML
  3.  El resto de usuarios ven los datos tal cual estaban antes de la transacción, de hecho los registros afectados por la transacción aparecen bloqueados hasta que la transacción finalice. Esos usuarios no podrán modificar los valores de dichos registros.
Tras la transacción todos los usuarios ven los datos tal cual quedan tras el fin de transacción. Los bloqueos son liberados y los puntos de ruptura borrados.


Introducción SQL (Comando SELECT 5ta parte)

Subconsultas

Se trata de una técnica que permite utilizar el resultado de una tabla SELECT en otra consulta SELECT. Permite solucionar problemas en los que el mismo dato aparece dos veces. La sintaxis es:

SELECT listaExpresiones
FROM tabla
WHERE expresión operador
(SELECT listaExpresiones
FROM tabla);


Se puede colocar el SELECT dentro de las cláusulas WHERE, HAVING o FROM. El operador puede ser >,<,>=,<=,!=, = o IN. Ejemplo:

SELECT nombre_empleado, paga
FROM empleados
WHERE paga <
(SELECT paga FROM empleados
WHERE nombre_empleado='Martina');


Lógicamente el resultado de la subconsulta debe incluir el campo que estamos analizando. Se pueden realizar esas subconsultas las veces que haga falta:

SELECT nombre_empleado, paga
FROM empleados
WHERE paga <
(SELECT paga FROM empleados
WHERE nombre_empleado='Martina')
AND paga >
(SELECT paga FROM empleados WHERE nombre_empleado='Luis');


La última consulta obtiene los empleados cuyas pagas estén entre lo que gana Luis y lo que gana Martina.

Una subconsulta que utilice los valores >,<,>=,... tiene que devolver un único valor, de otro modo ocurre un error. Pero a veces se utilizan consultas del tipo: mostrar el sueldo y nombre de los empleados cuyo sueldo supera al de cualquier empleado del departamento de ventas.

La subconsulta necesaria para ese resultado mostraría los sueldos del departamento de  ventas. Pero no podremos utilizar un operador de comparación directamente ya que compararíamos un valor con muchos valores. La solución a esto es utilizar instrucciones especiales entre el operador y la consulta. Esas instrucciones son:




Ejemplo:

SELECT nombre, sueldo
FROM empleados
WHERE sueldo >= ALL (SELECT sueldo FROM empleados)

Esa consulta obtiene el empleado que más cobra. Otro ejemplo:

SELECT nombre FROM empleados
WHERE dni IN (SELECT dni FROM directivos)

En ese caso se obtienen los nombres de los empleados cuyos dni están en la tabla de directivos.

Combinaciones especiales

UNIONES

La palabra UNION permite añadir el resultado de un SELECT a otro SELECT. Para ello  ambas instrucciones tienen que utilizar el mismo número y tipo de columnas. Ejemplo:

SELECT nombre FROM provincias
UNION
SELECT nombre FROM comunidades;

El resultado es una tabla que contendrá nombres de provincia y de comunidades. Es decir,  UNION crea una sola tabla con registros que estén presentes en cualquiera de las consultas. Si están repetidas sólo aparecen una vez, para mostrar los duplicados se utiliza UNION ALL en lugar de la palabra UNION.

INTERSECCIONES

De la misma forma, la palabra INTERSECT permite unir dos consultas SELECT de modo que el resultado serán las filas que estén presentes en ambas consultas.

DIFERENCIA

Con MINUS también se combinan dos consultas SELECT de forma que aparecerán los registros del primer SELECT que no estén presentes en el segundo.

Se podrían hacer varias combinaciones anidadas (una unión cuyo resultado se intersectará con otro SELECT por ejemplo), en ese caso es conveniente utilizar paréntesis para indicar qué combinación se hace primero:

(SELECT....
....
UNION
SELECT....
...
)
MINUS
SELECT.... /* Primero se hace la unión y luego la diferencia*/


Introducción SQL (Comando SELECT 4ta parte)

Agrupaciones


Es muy común utilizar consultas en las que se desee agrupar los datos a fin de realizar cálculos en vertical, es decir calculados a partir de datos de distintos registros. Para ello se utiliza la cláusula GROUP BY que permite indicar en base a qué registros se realiza la agrupación. Con GROUP BY la instrucción SELECT queda de esta forma:

SELECT listaDeExpresiones
FROM listaDeTablas
[JOIN tablasRelacionadasYCondicionesDeRelación]
[WHERE condiciones]
[GROUP BY grupos]
[HAVING condiciones de grupo]
[ORDER BY columnas];


En el apartado GROUP BY, se indican las columnas por las que se agrupa. La función de este apartado es crear un único registro por cada valor distinto en las columnas del grupo. Si por ejemplo agrupamos en base a las columnas tipo y modelo en una tabla de existencias, se creará un único registro por cada tipo y modelo distintos:


SELECT tipo,modelo
FROM existencias
GROUP BY tipo,modelo;


Si la tabla de existencias sin agrupar es:


























Es decir es un resumen de los datos anteriores. Los datos n_almacen y cantidad no están disponibles directamente ya que son distintos en los registros del mismo grupo. Sólo se pueden utilizar desde funciones (como se verá ahora). Es decir esta consulta es errónea:

SELECT tipo,modelo, cantidad
FROM existencias GROUP BY tipo,modelo;

SELECT tipo,modelo, cantidad
*
ERROR en línea 1:
ORA-00979: no es una expresión GROUP BY

Funciones de cálculo con grupos 


Lo interesante de la creación de grupos es las posibilidades de cálculo que ofrece. Para ello se utilizan funciones que permiten trabajar con los registros de un grupo son:














Todos esos valores se calculan para cada elemento del grupo, así la expresión:


SELECT tipo,modelo, cantidad, SUM(Cantidad)
FROM existencias
GROUP BY tipo,modelo;


Obtiene este resultado:











condiciones HAVING
A veces se desea restringir el resultado de una expresión agrupada, por ejemplo con:


SELECT tipo,modelo, cantidad, SUM(Cantidad)
FROM existencias
WHERE SUM(Cantidad)>500
GROUP BY tipo,modelo;


Pero Oracle devolvería este error:


WHERE SUM(Cantidad)>500
*
ERROR en línea 3:
ORA-00934: función de grupo no permitida aquí


La razón es que Oracle calcula primero el WHERE y luego los grupos; por lo que esa condición no la puede realizar al no estar establecidos los grupos. Por ello se utiliza la cláusula HAVING, que se efectúa una vez realizados los grupos. Se usaría de esta forma:

SELECT tipo,modelo, cantidad, SUM(Cantidad)
FROM existencias
GROUP BY tipo,modelo
HAVING SUM(Cantidad)>500;


Eso no implica que no se pueda usar WHERE. Esta expresión sí es válida:


SELECT tipo,modelo, cantidad, SUM(Cantidad)
FROM existencias
WHERE tipo!='AR'
GROUP BY tipo,modelo
HAVING SUM(Cantidad)>500;


En definitiva, el orden de ejecución de la consulta marca lo que se puede utilizar con WHERE y lo que se puede utilizar con HAVING:

Pasos en la ejecución de una instrucción de agrupación por parte del gestor de bases de
datos:

1> Seleccionar las filas deseadas utilizando WHERE. Esta cláusula eliminará columnas en base a la condición indicada
2> Se establecen los grupos indicados en la cláusula GROUP BY
3> Se calculan los valores de las funciones de totales (COUNT, SUM, AVG,...)
4> Se filtran los registros que cumplen la cláusula HAVING
5> El resultado se ordena en base al apartado ORDER BY.

Introducción SQL (Comando SELECT 3ra parte)

Funciones Condicionales

CASE

Es una instrucción incorporada a la versión 9 de Oracle que permite establecer condiciones de salida (al estilo if-then-else de muchos lenguajes). Sintaxis:

CASE expresión WHEN valor1 THEN resultado1
[ WHEN valor2 THEN resultado2 ....
...
ELSE resultadoElse
]
END

El funcionamiento es el siguiente:

1> Se evalúa la expresión indicada
2> Se comprueba si esa expresión es igual al valor del primer WHEN, de ser así se 
devuelve el primer resultado (cualquier valor excepto nulo)
3> Si la expresión no es igual al valor 1, entonces se comprueba si es igual que el segundo. De ser así se escribe el resultado 3. De no ser así se continua con el siguiente WHEN
4> El resultado indicado en la zona ELSE sólo se escribe si la expresión no vale ningún valor de los indicados. Ejemplo:

SELECT
CASE cotizacion WHEN 1 THEN salario*0.85
WHEN 2 THEN salario * 0.93
WHEN 3 THEN salario * 0.96
ELSE salario
END
FROM empleados;

DECODE

Similar a la anterior pero en forma de función. Se evalúa una expresión y se colocan a continuación pares valor, resultado de forma que si se la expresión equivale al valor, se obtiene el resultado indicado. Se puede indicar un último parámetro con el resultado a efectuar en caso de no encontrar ninguno de los valores indicados. Sintaxis:

DECODE(expresión, valor1, resultado1
[,valor2, resultado2,...]
[,valorPordefecto])

Ejemplo:

SELECT
DECODE(cotizacion,1, salario*0.85, 2,salario * 0.93, 3,salario * 0.96,salario)
FROM empleados;

Este ejemplo es idéntico al utilizado para la instrucción CASE.

Obtener datos de múltiples tablas 

Es más que habitual necesitar en una consulta datos que se encuentran distribuidos en varias tablas. Las bases de datos relacionales se basan en que los datos se distribuyen en tablas que se pueden relacionar mediante un campo. Ese campo es el que permite integrar los datos de las tablas. Por ejemplo si disponemos de una tabla de empleados cuya clave es el dni y otra tabla de tareas que se refiere a tareas realizadas por los empleados, es seguro (si el diseño está bien hecho) que en la tabla de tareas aparecerá el dni del empleado para saber qué empleado realizó la tarea.

Producto cruzado o cartesiano de tablas

En el ejemplo anterior si quiere obtener una lista de los datos de las tareas y los empleados, se podría hacer de esta forma:

SELECT cod_tarea, descripcion_tarea, dni_empleado, nombre_empleado
FROM tareas,empleados;

La sintaxis es correcta ya que, efectivamente, en el apartado FROM se pueden indicar varias tareas separadas por comas. Pero eso produce un producto cruzado, aparecerán todos los registros de las tareas relacionados con todos los registros de empleados. El producto cartesiano a veces es útil para realizar consultas complejas, pero en el caso normal no lo es. necesitamos discriminar ese producto para que sólo aparezcan los registros de las tareas relacionadas con sus empleados correspondientes. A eso se le llama asociar (join) tablas.

Asociando tablas

La forma de realizar correctamente la consulta anterior (asociado las tareas con los empleados que la realizaron sería:

SELECT cod_tarea, descripcion_tarea, dni_empleado, nombre_empleado
FROM tareas,empleados
WHERE tareas.dni_empleado = empleados.dni;

Nótese que se utiliza la notación tabla.columna para evitar la ambigüedad, ya que el mismo nombre de campo se puede repetir en ambas tablas. Para evitar repetir continuamente el nombre de la tabla, se puede utilizar un alias de tabla:

SELECT a.cod_tarea, a.descripcion_tarea, b.dni_empleado, b.nombre_empleado
FROM tareas a,empleados b
WHERE a.dni_empleado = b.dni;

Al apartado WHERE se le pueden añadir condiciones encadenándolas con el operador AND. Ejemplo:

SELECT a.cod_tarea, a.descripcion_tarea
FROM tareas a,empleados b
WHERE a.dni_empleado = b.dni AND b.nombre_empleado='Javier';

Finalmente indicar que se pueden enlazar más de dos tablas a través de sus campos relacionados. Ejemplo:

SELECT a.cod_tarea, a.descripcion_tarea, b.nombre_empleado, c.nombre_utensilio
FROM tareas a,empleados b, utensilios_utilizados c
WHERE a.dni_empleado = b.dni AND a.cod_tarea=c.cod_tarea;

Relaciones sin Igualdad

A las relaciones descritas anteriormente se las llama relaciones en igualdad (equijoins), ya
que las tablas se relacionan a través de campos que contienen valores iguales en dos tablas. A veces esto no ocurre, en las tablas:

















En el ejemplo anterior podríamos averiguar la categoría a la que pertenece cada empleado,pero estas tablas poseen una relación que ya no es de igualdad. La forma sería:

SELECT a.empleado, a.sueldo, b.categoria
FROM empleados a, categorias b
WHERE a.sueldo between b.sueldo_minimo and b.sueldo_maximo;

Obtener registros no relacionados

En el ejemplo visto anteriormente de las tareas y los empleados. Podría ocurrir que un empleado no hubiera realizado una tarea todavía, con lo que habría empleados que no aparecerían en la consulta al no tener una tarea relacionada.

La forma de conseguir que salgan todos los registros de una tabla aunque no estén relacionados con las de otra es realizar una asociación lateral o unión externa (también llamada outer join). En esas asociaciones, el signo (+) indica que se desean todos los registros de la tabla estén o no relacionados. Sintaxis:

SELECT tabla1.columna1, tabla1.columna2,....
tabla2.columna1, tabla2.columna2,...
FROM tabla1, tabla2
WHERE tabla1.columnaRelacionada(+)=tabla2.columnaRelacionada

Eso obtiene los registros relacionados entre las tablas y además los registros no relacionados de la tabla2. Se podría usar esta otra forma:

SELECT tabla1.columna1, tabla1.columna2,....
tabla2.columna1, tabla2.columna2,...
FROM tabla1, tabla2
WHERE tabla1.columnaRelacionada=tabla2.columnaRelacionada(+)

En ese caso salen los relacionados y los de la primera tabla que no estén relacionados con ninguno de la primera.

Sintaxis SQL 1999

En la versión SQL de 1999 se ideó una nueva sintaxis para consultar varias tablas. La 
razón fue separar las condiciones de asociación respecto de las condiciones de selección de 
registros. La sintaxis completa es:

SELECT tabla1.columna1, tabl1.columna2,...
tabla2.columna1, tabla2.columna2,... FROM tabla1
[CROSS JOIN tabla2]|
[NATURAL JOIN tabla2]|
[JOIN tabla2 USING(columna)]|
[JOIN tabla2 ON (tabla1.columa=tabla2.columna)]|
[LEFT|RIGHT|FULL OUTER JOIN tabla2 ON
(tabla1.columa=tabla2.columna)]

Se describen sus posibilidades

CROSS JOIN
Utilizando la opción CROSS JOIN se realiza un producto cruzado entre las tablas indicadas

NATURAL JOIN
Establece una relación de igualdad entre las tablas a través de los campos que tengan el
mismo nombre en ambas tablas:

SELECT * FROM piezas
NATURAL JOIN existencias;

En el ejemplo anterior se obtienen los registros de piezas relacionados en existencias a través de los campos que tengan el mismo nombre en ambas tablas.

JOIN USING
Permite establecer relaciones indicando qué campo (o campos) común a las dos tablas hay que utilizar:

SELECT * FROM piezas
JOIN existencias USING(tipo,modelo);

JOIN ON
Permite establecer relaciones cuya condición se establece manualmente, lo que permite realizar asociaciones más complejas o bien asociaciones cuyos campos en las tablas no tienen el mismo nombre:

SELECT * FROM piezas
JOIN existencias ON(piezas.tipo=existencias.tipo AND
piezas.modelo=existencias.modelo);

relaciones externas
La última posibilidad es obtener relaciones laterales o externas (outer join). Para ello se utiliza la sintaxis:

SELECT * FROM piezas
LEFT OUTER JOIN existencias
ON(piezas.tipo=existencias.tipo AND
piezas.modelo=existencias.modelo);

En este consulta además de las relacionadas, aparecen las piezas no relacionadas en existencias. Si el LEFT lo cambiamos por un RIGHT, aparecerán las existencias no presentes en piezas. La condición FULL OUTER JOIN produciría un resultado en el que aparecen los registros no relacionados de ambas tablas.