Mostrando entradas con la etiqueta SQL. Mostrar todas las entradas
Mostrando entradas con la etiqueta SQL. Mostrar todas las entradas

sábado, 27 de junio de 2020

MySQL. agrupar por fecha y contar incluido los ceros cuando no hay datos para una fecha



La idea la encontré en stack overflow "MySQL group by date and count including missing dates".
Consiste en generar tantos números como días se quiera. En el ejemplo se generan 10 mil filas. Y como se toma como referencia la fecha actual, son 10 mil días hacia atrás. Eso son más de 27 años.

create view datetable as
select
date_format(adddate(now(),-(a.a + (10 * b.a) + (100 * c.a) + (1000 * d.a))),'%Y-%m-%d') AS date
from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4
union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4
union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4
union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4
union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as d
; 
Entonces, la idea es realizar un LEFT JOIN con esta vista para así obtener todas las filas incluidas las no relacionadas, y condicionar para el rango de fechas deseado. Por ejemplo, a continuación con una tabla de usuarios.
select 
    datetable.date,
    count(users.id) users
from
    datetable
    left join users on datetable.date = date_format(users.createdAt,'%Y-%m-%d')
where
    datetable.date 
        between date_format('2020-06-20','%Y-%m-%d') 
        and date_format('2020-06-30','%Y-%m-%d')
group by
    datetable.date;
+------------+-------+
| date       | users |
+------------+-------+
| 2020-06-20 |     0 |
| 2020-06-21 |     0 |
| 2020-06-22 |     0 |
| 2020-06-23 |     0 |
| 2020-06-24 |     0 |
| 2020-06-25 |     0 |
| 2020-06-26 |   207 |
| 2020-06-27 |     0 |
+------------+-------+
Todos los usuarios fuerondatos de alta el 2020-06-26 por eso se ve que ese día tiene los 207 usuarios y el resto de días cero. Aunque en el rango se indica entre el 20 y 30 de junio. La sentencia se ejecuta el 27 de junio que es la fecha actual que toma de referencia en la vista. Por ello, no se ve datos para el 28, 29, 30.
Entendiendo la idea se puede adaptar al problema a resolver.




miércoles, 1 de agosto de 2018

MySQL: Generar un número aleatorio



Para generar un número aleatorio entre un rango [mínimo, máximo], es decir inclusivo: n >= mínimo, n <= máximo.
FLOOR(RAND() * (máximo - mínimo + 1)) + mínimo;

Probado en MySQL 5.7

martes, 1 de septiembre de 2015

Condición LIKE en Oracle SQL


Para condicionar en vez de utilizar un igual «=» en el que se comprueba carácter a carácter si son iguales:
('Francisco' = 'Francisco') es verdadero
('Fran     ' = 'Francisco') es falso

Con LIKE se puede condicionar utilizando comodines para realizar búsquedas como:

--Nombre de los empleados que su segunda letra, del nombre, sea una «a» minúscula.
SELECT first_name
FROM employees
WHERE first_name LIKE '_a%';

Comodines (wildcard)
Guión bajo «_» indica un carácter.
Porcentaje «%» indica cero o n caracteres.

--Nombre de los empleados que su nombre empiece por «S» y termine en «n».
SELECT first_name
FROM employees
WHERE first_name LIKE 'S%n';

Cuando tenemos la necesidad de indicar que buscamos en la cadena de caracteres uno de los caracteres comodines («_», «%»), especificamos un carácter de escape.

--Email de los empleados que contengan un guión bajo.
SELECT email
FROM employees
WHERE email LIKE '%@_%' ESCAPE '@';

En el ejemplo se ha utilizado como carácter de escape la arroba «@», podría ser otro carácter. Si coincide el carácter que especificamos fijo en la búsqueda y el de escape, simplemente se lo repite.

SELECT email
FROM employees
WHERE email LIKE '%__%' ESCAPE '_';

Si la comparación es de igualdad lo mejor es utilizar simplemente un igual «=»; en caso de solo una parte de la cadena, como por ejemplo que empiece por «A» lo mejor es utilizar la función SUBSTR y no un LIKE.

Más información: web Oracle

jueves, 29 de enero de 2015

JOINS con Oracle SQL


Voy a resumir rápidamente las diferentes formas de realizar una unión —JOIN, OUTER JOIN— de tablas en una sentencia SELECT. Aunque lo especificado en esta entrada se realiza utilizando Oracle, el lenguaje SQL es un estándar y por ello puede ser utilizado (suele haber pequeñas diferencias, por lo que hay que probar) en diferentes sistemas de gestión de bases de datos. Añado que, a lo largo de la entrada me refiero a «tabla» pero según el contexto puede ser en su lugar: vistas, subconsultas; y cuando me refiero a «campo» es el nombre de la columna; «fila» es una tupla; esto por familiarizar con diferentes formas de expresar para quienes se inician.

Utilizaré dos tipos de tablas para poner los ejemplos, es decir, unas inventadas por mí para ilustrar rápidamente y, las del esquema de ejemplo HR de Oracle que viene instalado o se puede crear desde Oracle, o buscando en internet los scripts.

Las tablas inventadas son las siguientes:


CROSS JOIN
Es el producto cartesiano, es decir, la relación de todas las filas de la tabla Emp con todas las filas de la tabla Dep y a su vez con todas las filas de la tabla Loc. Esto hay que conocerlo porque nos puede dar una pista de cuando nos salen más filas de las esperadas ya que no hemos especificado la condición de unión de las tablas según su relación.

En este pequeño ejemplo en el que en Emp hay 4 filas, Dep 3 filas y Loc 2 filas, obtenemos como resultado 24 filas = 4x3x2.

La sentencia escrita en dos formas:
SELECT emp.nombre, emp.depid, dep.depid, dep.nombre, loc.nombre
FROM emp, dep, loc; 
SELECT emp.nombre, emp.depid, dep.depid, dep.nombre, loc.nombre
FROM emp CROSS JOIN dep CROSS JOIN loc;
Si realizamos similar prueba con las tablas del esquema HR la sentencia sería:
SELECT first_name, department_name, city
FROM employees, departments, locations;
Dando como resultado 66447 filas = 107(Employees) x 27(Departments) x 23(Locations)

NATURAL JOIN
Lo que realiza es una unión por los campos de igual nombre, así que, hay que tener cuidado con esto pues hay quien lo utiliza para escribir menos y confía en que se realiza la unión por los campos clave. Pero, además puede estar realizando la unión por otros campos en los que coincide el nombre de las columnas. 

Empecemos con un ejemplo de las tablas de HR en el que deseamos el nombre de los empleados y el de su departamento.
SELECT first_name, department_name
FROM employees NATURAL JOIN departments;
Puede que pensemos que lo que se está haciendo es la unión por el campo con el que se relacionan las tablas, que es el número de departamento, la sentencia siguiente:
SELECT first_name, department_name
FROM employees, departments
WHERE employees.department_id = departments.department_id;
Pero, en realidad no lo es y nos da como resultado 32 filas, ya que en realidad la sentencia que está realizando sería:
SELECT first_name, department_name, department_id
FROM employees, departments
WHERE employees.department_id = departments.department_id
AND employees.manager_id = departments.manager_id;
En realidad ésta sentencia nos da los empleados que tienen el mismo jefe, tanto como jefe de empleado como jefe de departamento. Debido a que en las tablas Employees y Departments existen dos campos (nombre de columna) en los que coincide el nombre: manager_id y department_id. Si intentamos especificar en la Select uno de estos campos dará error si le anteponemos un nombre de tabla pues esta sentencia es específicamente para tratarlos como igual, así que no hay por qué diferenciar.

En el caso de las tablas que he inventado no obtendremos ninguna fila pues en las tres hay un campo que se llama: nombre. Y claro está que ningún valor coincide.

JOIN o simple join o inner join
Es la unión típica en la que se especifica el campo o campos que relacionan las tablas involucradas. Esto es, un campo primary key con uno foreign key. Los cuales surgen de una correcta modelización y paso al modelo relacional.

En el ejemplo se puede ver que salen únicamente las tuplas (filas) relacionadas. Es decir, Ana como no tiene un departamento no se muestra en el listado. Supongamos que aunque María sí esté en el departamento 20, el departamento 20 no tenga asignada una localidad, entonces tendremos como resultado solo dos filas en donde María no se listará.

Otra forma de escribir la misma sentencia es con la palabra JOIN y la cláusula USING:
SELECT emp.nombre, depid, dep.nombre, loc.nombre
FROM emp JOIN dep USING(depid)
                    JOIN loc USING(locid);
Es una forma en la que debemos tener en cuenta que: los nombres de los campos utilizados en la cláusula USING deben ser iguales en ambas tablas, y no puede anteponerse el nombre de ninguna tabla como podemos ver al utilizarlo en la parte de SELECT con el campo: depid, de igual modo si lo utilizamos en otra parte de la sentencia. Como podemos ver la especificación se hace escribiendo todo en el FROM; en el WHERE irán todas las condiciones restantes que no tienen que ver con la relación de las tablas. 

Lo que estamos diciendo es que Emp se une con Dep usando el campo depid y, a esa unión la unimos con la tabla Loc usando el campo locid. Repito: los nombres tienen que ser iguales pues de caso contrario no se puede realizar esta sintaxis. También, hay que tener en cuenta que si realizamos la unión por más de un campo se especifican separados por comas dentro del USING. Por ejemplo en el caso visto antes de los empleados que su jefe es el mismo que el jefe del departamento en el que trabajan se podría escribir de la siguiente forma.
SELECT first_name, department_name
FROM employees JOIN departments USING(department_id, manager_id);

Y obtendríamos las 32 filas mencionadas. Pero, debemos tomar en cuenta que aunque obtenemos los mismos resultados, por buenas prácticas debemos separar las condiciones de relación de las tablas (campos clave con campos ajenos) del resto de condiciones, en sentencias más grandes facilita el mantenimiento y la comprensión. Es decir, la sentencia sería:
SELECT first_name, department_name
FROM employees JOIN departments USING(department_id)
WHERE employees.manager_id = departments.manager_id;
Continuando con las tablas de HR la sentencia en la que se listan los empleados con su nombre, el nombre del departamento y la ciudad, tenemos:
SELECT first_name, department_name, city
FROM employees JOIN departments USING(department_id)
            JOIN locations USING(location_id);
El total de empleados es 107, pero se listan 106 pues hay uno que no tiene departamento. Y  hay que recordad que solo se listan las filas relacionadas.

Además, del JOIN y la cláusula USING, tenemos a JOIN con la cláusula ON en la que escribimos la condición de unión similar a como se haría en el WHERE. Ésta forma nos permite trabajar con campos en los que no coincidan el nombre en ambas tablas, porque igual se debe especificar y en caso de hacer referencia a uno de ellos sí hay que anteponer el nombre de la tabla; además, tiene la misma ventaja de separar las condiciones de unión del resto de condiciones del WHERE haciendo más legible la sentencia, por lo que es la opción que yo recomendaría. A continuación las sentencias que listan a los empleados de ambos ejemplos que utilizo.
SELECT emp.nombre, emp.depid, dep.nombre, loc.nombre
FROM emp JOIN dep ON(emp.depid = dep.depid)
                    JOIN loc ON(dep.locid = loc.locid);
SELECT first_name, department_name, city
FROM employees JOIN departments ON(employees.department_id = departments.department_id)
            JOIN locations ON(departments.location_id = locations.location_id);
OUTER JOIN
Son útiles para mostrar filas que no están relacionadas, además de las relacionadas. En el ejemplo sencillo en el que Ana no se muestra, supongamos que queremos listar todos los empleados independientemente de si están o no relacionados. 
Con LEFT JOIN (LEFT OUTER JOIN) lo que indicamos es que la tabla a la izquierda es de la que quiero todas las filas independientemente de que sus filas se relacionen. El segundo LEFT JOIN es necesario pues a la primera unión vamos a relacionarla con la tercera tabla (Loc) y si es a la izquierda donde se encuentra la información que queremos listar se relacione o no. Así que, el que sea LEFT JOIN es porque tal y como se ha escrito está a la izquierda, pues si lo ponemos en otro orden y queremos los mismos resultados hay que tener en cuenta hacia qué lado está lo que queremos listar aunque no esté relacionado. Supongamos que queremos lo mismo pero escribimos las tablas en el orden inverso. Entonces en éste caso la tabla de empleados estará a la derecha por lo que la sentencia sería con RIGHT JOIN (RIGHT OUTER JOIN):
Ahora queremos todos los departamentos, que tal como podemos comprobar con los datos existe el 30 que no se relaciona. Y vamos a escribir la sentencia dejando a la tabla dep en el centro simplemente para ilustrar que hay que escribir los JOIN en función del orden en el que escribimos.
Como se puede ver se lista el departamento 30 que no tiene localidad y Ana no se muestra. Antes de que exista el estándar de 1999, que es el que utiliza la palabra JOIN, utilizando la forma antigua con WHERE se escribiría de la siguiente forma:
En éste caso se coloca un signo más entre paréntesis al campo de la tabla que queremos rellene o no tome en cuenta. Como queríamos todas las filas de Dep colocamos el símbolo a Emp y Loc. Para el caso de las tablas de HR, manteniendo el supuesto de que queremos todos los departamentos además de los datos relacionados, que son 106 filas, la sentencia en la que obtendríamos 122 filas sería:
SELECT first_name, department_name, cityFROM employees RIGHT JOIN departments ON(employees.department_id = departments.department_id)LEFT JOIN locations ON(departments.location_id = locations.location_id); 
SELECT first_name, department_nameFROM employees, departments, locationsWHERE employees.department_id(+) = departments.department_id       AND departments.location_id = locations.location_id(+);
Por último, ahora suponemos que queremos listar todos los empleados, departamentos y localidades estén o no relacionados. Entonces se nos puede ocurrir poner el símbolo (+) a ambos lados del igual. Pero, esto no se permite. Con esta sintaxis anterior al estándar del 99, se tenía que idear otra forma. Así que, sumamos otra ventaja al estándar del 99 que lo permite con FULL JOIN (FULL OUTER JOIN).
SELECT first_name, department_name, cityFROM employees FULL JOIN departments ON(employees.department_id = departments.department_id)FULL JOIN locations ON(departments.location_id = locations.location_id); 
En el caso de las tablas de HR obtenemos 139 filas. Y en nuestro pequeño ejemplo:
Como se ve en la imagen están las 3 filas que se relacionan, la empleada que no tiene departamento, el departamento que no tiene localidad y la localidad que no se relaciona, teniendo así las 6 filas que se listan. A partir de aquí, podemos mezclar por ejemplo al suponer que queremos todos los empleados y departamentos pero las ciudades nos basta con las que se relacionan, entonces tendríamos:
SELECT emp.nombre, emp.depid, dep.nombre, loc.nombre
FROM emp FULL JOIN dep ON(emp.depid = dep.depid)
                    LEFT JOIN loc ON(dep.locid = loc.locid);


Realizado con:—Oracle Database 10g
—Aplicación desde terminal SQLPLUS

jueves, 29 de marzo de 2012

ORDER BY. Oracle.

Diagrama de ORDER BY

Para ordenar las filas devueltas por una select utilizamos la cláusula ORDER BY, la cual va al final de toda la SELECT.
SELECT       ename, sal,comm,sal+comm total
FROM           emp
ORDER BY  ename;
Significaría que muestre ordenado por el campo «ename» en orden ascendente.

Salida de select de ejemplo

Se puede ordenar por más de un campo, e indicar individualmente si ascendentemente (ASC) o descendentemente (DESC). Por defecto el orden es ascendente.
SELECT      ename, sal,comm,sal+comm total
FROM          emp
ORDER BY sal ASC, total DESC, 1 ASC;
Salida de select de ejemplo
Se ordena primero por el campo «sal» en orden ascendente y en caso de similares «1250» se ordena por el siguiente campo especificado «total —alias de sal+comm—» en orden descendente . Y en caso de iguales, se ordenará por la tercera opción que es «1 —corresponde al campo "ename" que es el primero» en orden ascendente (ej: cuando sal es 3000 y total null).
Se puede utilizar para hacer referencia a la columna por la cual se quiere ordenar: el nombre, el alias o el orden que ocupa en la select. No se puede utilizar expresiones (ej: sal+com, to_char(fecha,'mm')).

Los campos de la cláusula ORDER BY tienen que ser campos pertenecientes a los objetos especificados en el FROM (tablas, vistas, subconsultas), es decir, se puede ordenar por un campo que no necesariamente tiene por qué ser seleccionado. Por ejemplo, podríamos ordenar por «ename» y la SELECT ser: «sal,comm+sal» (excluyendo a «ename»).

Además de ordenar por los campos que tienen datos, se puede especificar si  queremos los nulos al inicio (FIRST) o al final (LAST) de todo. Por defecto cuando es descendente los nulos van al inicio, y cuando es ascendente los nulos van al final.
SELECT      ename, sal,comm,sal+comm total
FROM          emp
ORDER BY total DESC NULLS LAST;
Salida de select de ejemplo

En caso de utilizar los operadores de conjunto: INTERSECT, MINUS, UNION, UNION ALL, se escribe una sola  cláusula ORDER BY que se coloca al final del todo y solo una.
SELECT ename
FROM    emp
MINUS
SELECT UPPER(first_name)
FROM   employees
ORDER BY ename;
A la primer select se le restan los elementos que coinciden con la segunda select («JAMES») y al resultado de todo se lo ordena. Se utiliza la función UPPER para transformar los datos que provienen de la tabla «employees» a mayúsculas.
En caso de querer filtrar por el número de fila ROWNUM de una ordenación. Hay que saber lo que se hace. Por ejemplo queremos a los tres que ganan más.

ROWNUM nos indica el número de la fila y no cambiará aunque cambiemos el orden.

Así que si pensamos en obtener los tres que ganan más. Y pensamos en la siguiente SELECT:

Si comparamos con la SELECT  en la que vemos a todos, notamos que no es lo que queremos.

Una alternativa es primero ordenarlos en una subconsulta y a esas filas filtrarlas por el ROWNUM.

Si se quiere optimizar, es recomendable evitar ordenar los datos para evitar el darle ese trabajo extra a la base de datos. Hacerlo únicamente cuando estemos obligados a eso. Analizarlo.
Por ejemplo, con tan solo catorce filas se puede ver cómo el coste aumenta, de realizar una SELECT («ename,sal») sin ordenar, y la misma ordenando (por «sal»). No pensar en que si se ordena por un campo indexado va a ir más rápido.


Se ha utilizado:
—Windows XP SP3
—Oracle Data Base 11.2.0.1
—SQL*PLUS 11.2.0.1
—Tablas de los esquemas SCOTT (emp) y HR(employees)

martes, 19 de julio de 2011

Error al activar autotrace

SP2-0611


Al intentar activar desde sqlplus el informe de estadísticas da los mensajes siguiente.


SQL> set autotrace on
SP2-0618: No se ha podido encontrar el identificador de sesión. Compruebe si el rol PLUSTRACE está a
SP2-0611: Error al activar el informe STATISTICS

En otras ocaciones algo similar
SP2-0613: Unable to verify PLAN_TABLE format or existence
SP2-0611: Error enabling EXPLAIN report

Los pasos a seguir son 3:

1. Ejecutar el script $ORACLE_HOME/sqlplus/admin/plustrce.sql como usuario SYS
2. Ejecurar el script $ORACLE_HOME/rdbms/admin/utlxplan.sql como el user que ejecuta el autotrace
3. Otorgar el privilegio PLUSTRACE al user que ejecuta el autotrace.

Ejemplo:

1.*
conn sys/contraseña@orcl as sysdba
start %ORACLE_HOME%/sqlplus/admin/plustrce.sql

2.
conn hr/hr@orcl
start %ORACLE_HOME%/rdbms/admin/utlxplan.sql

3.
conn sys/contraseña@orcl as sysdba
grant plustrace to hr;


¡Listo! Al volver a iniciar una sesión con el usuario HR, hacer un «set autotrace on» y no saldrá el error.

* Al ejecutar los scripts es posible ver los mensajes sobre lo que realiza. Es normal por ejemplo que dé error al intentar eliminar un rol que no existe, posteriormente se ve que lo crea.

Realizado en:
—Windows XP
—Oracle 10.2.0.1
ORACLE_HOME es una variable de entorno que contiene la ruta del HOME de Oracle. Ej. C:\Oracle\product\10.2\db_1

sábado, 16 de julio de 2011

Activar/desactivar disparadores Oracle

Si queremos activar o desactivar todos los triggers asociados a las tablas de un esquema, tendríamos que programarlo. Un ejemplo de ello es el post sobre «Activar/desactivar todos los triggers de todas la tablas».

Para activar o desactivar un trigger, necesitamos conocer su nombre, además, tener el privilegio adecuado:

—Si es nuestro (el usuario con el que iniciamos sesión): CREATE TRIGGER, lleva implícito el poder eliminar, modificar código y estado de nuestros disparadores.
—No es nuestro trigger: necesitamos ALTER ANY TRIGGER.
—Si es un trigger sobre base de datos ADMINISTER DATABASE TRIGGER.

Por ejemplo:
alter trigger hr.secure_employees disable; 
alter trigger hr.secure_employees enable;

«Si utilizamos una herramienta gráfica como SQL Developer, esta tarea se puede hacer como se indica en la imagen.»
Si queremos ver su estado podemos consultarlo:
select   statusfrom     all_triggerswhere  trigger_name='SECURE_EMPLOYEES';
Si queremos desactivar/activarlos todos los triggers de una tabla:
alter table hr.employees enable all triggers; 
alter table hr.employees disable all triggers;

«Si utilizas SQL Developer, se puede realizar la activación/desactivación de todos los triggers como se indica en la imagen.»
Otros enlaces:
Consultar información sobre los disparadores.
Mas información en Oracle: enabling and disabling triggers.

Información de los disparadores. Oracle.

Si utilizas SQL Developer simplemente puedes ir a la pestaña "Código"
«Si utilizas SQL Developer simplemente puedes ir a la pestaña "Código"»

Para consultar información de los disparadores (triggers), utilizamos vistas del diccionario de datos como:

USER_TRIGGERS trigger pertenecientes al esquema del usuario actual.
ALL_TRIGGERS triggers sobre tablas accesibles por el usuario actual. (Si el usuario posee el privilegio CREATE ANY TRIGGER podrá ver todos los triggers de la base de datos.)
DBA_TRIGGERS todos los disparadores de la base de datos.

Tienen las mismas columnas, excepto USER_TRIGGERS la columna «owner».

Al describir por ejemplo ALL_TRIGGERS; columnas que nos daran información como: propietario, nombre del disparador, tipo, evento, propietario de la tabla, nombre de la tabla/vista, tipo de objeto base (tabla/vista), estado (enabled, disabled), código, etc.
Salida de: desc all_triggers

Solo tenemos que realizar la consulta de nuestro interes, por ejemplo:
Si estamos conectados con el usuario HR, y queremos ver los triggers que tienen las tablas pertenecientes al usuario HR (nuestro usuario); la siguiente select muestra el nombre del trigger y el propietario de éste (que sin permisos no se podría borrar dicho trigger al no pertenecernos, aunque este sobre nuestra tabla).
select   owner,trigger_name,table_name  
from    all_triggers 
where  table_owner='HR';
OWNER
-----  
TRIGGER_NAME
------------------  
TABLE_NAME
---------------
HR
SECURE_EMPLOYEES
EMPLOYEES
HR
UPDATE_JOB_HISTORY
EMPLOYEES
JP
TRIJP
EMPLOYEES
HR
TRIHR
EMPLOYEES

Si queremos ver el código del trigger, tenemos el cuerpo -solo- (trigger_body) en las vistas mencionadas; pero mejor aún si lo consultamos en ALL_SOURCE (similares: USER_SOURCE, DBA_SOURCE), donde está todo el código, no solo el cuerpo (además código de procedimientos, funciones, paquetes, disparadores).
select   text 
from    all_source 
where  name='SECURE_EMPLOYEES'  
      and owner='HR';
TEXT
------------------------------------------------------
TRIGGER secure_employees
BEFORE INSERT OR UPDATE OR DELETE ON employees
BEGIN
secure_dml;
END secure_employees;


Otros enlaces:
Web Oracle. Vistas: user_triggers, all_triggers, dba_triggers y otras más.

lunes, 27 de junio de 2011

Consultar qué tablas pertenecen a un usuario en Oracle

Vista de SQL Developer en el que muestra las tablas de HR
«Vista de SQL Developer en el que muestra las tablas de HR»

Podríamos decirlo de otro modo: ¿Cómo conocer qué tablas tiene un esquema? Recordar que usuario y esquema en Oracle van asociados. Usuario es el propietario y esquema es la agrupación lógica de los objetos pertenecientes a un usuario. Tienen el mismo nombre. Suelo decir que esquema es el «cajón» donde están los objetos de un usuario.

Por ejemplo: conectados como el usuario HR, la siguiente consulta nos muestra el nombre de las tablas del esquema HR:
select    table_name
from     user_tables;
TABLE_NAME
------------------------------
COUNTRIES
DEPARTMENTS
EMPLOYEES
JOBS
JOB_HISTORY
LOCATIONS
REGIONS

Si queremos ver las tablas de un esquema distinto, lo hacemos sobre ALL_TABLES y condicionamos para el propietario que deseemos. Necesitaremos tener acceso a todas las tablas para poder verlas (privilegio SELECT ANY TABLE), o permiso sobre la tabla en cuestión y solo veremos esas tablas.
select   table_name
from    ALL_TABLES
where  owner='HR';
En la vista ALL_TABLES tendremos la información de las tablas pertenecientes al usuario con el que hemos iniciado sesión y de las tablas sobre las que tiene algún permiso explícito. Para usar DBA_TABLES tendremos que tener un rol DBA y se podrá ver la descripción de todas la tablas de la base de datos.

viernes, 24 de junio de 2011

Oracle: Precedencia de operadores.

Tanto en el lenguaje SQL, como en el lenguaje PLSQL. La precedencia de operadores es la siguiente:

Tabla: operador, operación

Lo aconsejable es utilizar paréntesis para ver explícitamente lo que se quiere y facilite el entender.

Para más información en: Oracle

jueves, 23 de junio de 2011

Ver select de una vista en sqlplus

Si tenemos alguna vista de la cual queremos conocer la SELECT que tiene, entonces consultamos en alguna de las vistas del diccionario de datos como:
—USER_VIEWS (información sobre vistas del usuario)
—ALL_VIEWS (información sobre todas las vistas a las que se tiene permiso)
—DBA_VIEWS (información sobre todas las vistas de la base de datos).

Podemos describir por ejemplo ALL_VIEWS por ver la información que nos da.
respuesta al mandato desc

Lo que nosotros queremos es saber el código fuente (la SELECT) que tiene la vista. Así que consultamos el campo «TEXT», condicionando para la vista de nuestro interés y de quién. Recordar escribir en mayúscula el nombre de la vista y el nombre del propietario.
select    text 
from     all_views 
where   view_name='EMP_DETAILS_VIEW' 
     and  owner='HR';
Si no se visualiza toda la select de la vista, escribir: 
set long 2000
Esto nos mostrará 2000 caracteres de la columna que es de tipo «long». Si queremos ver más caracteres, ponemos una cifra mayor.

Salida de la select de ejemplo

domingo, 8 de mayo de 2011

Modificar estado constraint en Oracle

Diagrama sentencia ALTER TABLE

Con modificar una constraint no nos referimos a cambiarle el tipo, condición, columnas, etc. (para ello eliminarla y volver a crearla), nos referimos a desactivar, activar u obligar UNA constraint (restricción) de UNA tabla, en una base de datos Oracle.

Utilizaremos la  instrucción ALTER TABLE. Existe diferente maneras de escribirlo dependiendo el tipo de constraint (como se puede apreciar en la imagen), de un modo general como está a continuación:
  • Una constraint desactivada (disabled, not validated) no realiza la comprobación para la que fue creada.
alter table nombre_tabla
disable constraint nombre_constraint;
  • Una constraint activada (enabled, validated) podremos activarla si la información existente cumple la restricción. Una vez activada, toda la información debe cumplir la restricción.
alter table nombre_tabla
enable constraint nombre_constraint;
  • Una constraint enforce o también conocida como obligatoria (enabled, not validated) la podemos activar aunque los datos existentes no cumplan la restricción. Pero los nuevos datos o modificaciones deben cumplir con la restricción.
alter table nombre_tabla
enforce constraint nombre_constraint;
nombre_tabla es el nombre de la tabla o sinónimo (nombre alternativo de un objeto -tabla-) al cual el usuario tiene acceso. Si la tabla pertenece a un usuario distinto del nuestro, se debe especificar el nombre del propietario (propietario.nombre_tabla) además de tener el privilegio ALTER TABLE sobre ella.

Otros enlaces:
Consultar información sobre las constraints de una tabla.
—Procedimiento que se encarga  de activar/desactivar todas las constraints de todas las tablas de un usuario.
—Web de Oracle sobre ALTER TABLE

Información de las constraints de una tabla. Oracle.

Para conocer mediante una consulta SQL algunos datos de las restricciones  (constraintsutilizando vistas del diccionario de datos de Oracle conociendo solo el nombre de la tabla podemos hacer la siguiente SELECT, en la que nos indica el propietario, nombre de la tabla, nombre de la columna que tiene la restricción, nombre de la constraint, tipo de constraint, la condición que deben cumplir las constraints tipo CHECK y el estado.

Un ejemplo mostrando información de las constraints donde la tabla se llama EMP.

select
         owner,
         table_name,
         column_name,
         constraint_name,
         constraint_type,
         search_condition,
         status
from
         all_constraints
  join all_cons_columns
  using(owner,table_name,constraint_name)
where
         table_name='EMP';

Información de las constraints

Owner es el nombre del esquema en el que se encuentra la tabla. Tipo de constraint sobre tabla puede ser: PRIMARY KEY (P), FOREIGN KEY (R), UNIQUE (U), CHECK (C). El nombre de una constraint es único por esquema.



Basándonos en la SELECT anterior, podemos modificar la cláusula WHERE para filtrar por los datos que nos interesan. Recordar que la información está en mayúsculas, así que en las condiciones del WHERE al preguntar por valores, utilizar mayúsculas.


Describir las vistas, para ver qué otra información nos dan y así modificar la SELECT para obtener lo que buscamos. En ALL_CONS_COLUMNS básicamente tenemos la información de qué columnas son las afectadas por la constraint. En ALL_CONSTRAINTS tenemos información sobre su estado (estatus, validate), constraints a las que se hace referencia en caso de una foreign key (r_constraint_name,r_owner), regla de eliminación (delete_rule), índice asociado a la constraint (index_name, index_owner), etc.

Otra alternativa a las vistas ALL_CONSTRAINTS y ALL_CONS_COLUMNS son: USER_CONSTRAINTS y USER_CONS_COLUMNS, en las que la información que nos mostraran se limita a las constraints pertenecientes al usuario con el que nos hemos conectado.


–Web de Oracle sobre la vista ALL_CONSTRAINTS y sobre ALL_CONS_COLUMNS

Privilegio para hacer referencia a tabla

Descripción gráfica foreign key

Cuando queremos crear una constraint foreign key en una tabla «tabla_o», que haga referencia a una tabla «tabla_r» que no pertenece al «usuario_o» propietario de «tabla_o», es decir, la tabla «tabla_r» a la que se hace referencia se encuentra en un esquema distinto al de «tabla_o», se necesita tener el privilegio explícito, es decir, que el «usuario_o» propietario de «tabla_o» debe tener explícito el permiso para poder hacer referencia a «tabla_r», ya que no es suya.

El «usuario_r» propietario de la tabla «tabla_r» o un usuario con privilegios para realizar el otorgamiento debe dar el permiso al «usuario_o» (propietario de «tabla_o»), ejecutando:
grant references on tabla_r to usuario_o;
Y si lo queremos quitar entonces ejecutamos:
revoke references on tabla_r from usuario_o cascade constraints;
Esta última instrucción quita el privilegio al «usuario_o» y elimina las foreign key que hacían referencia a «tabla_r».

sábado, 19 de febrero de 2011

Instalar Oracle Data Base Enterprise Edition 10.2 en Ubuntu 10.10

Logo Ubuntu y Oracle

Cómo he instalado Oracle 10g en Ubuntu 10.10.

Actualizar el sistema
Activar los socios de canonical para instalar otro software:

aplicaciones-centro de software de ubuntu
editar-origenes de software
otro software
activar socios de canonical

En el terminal escribimos:
sudo apt-get update
sudo apt-get upgrade

Librerias a instalar
sudo apt-get install gcc libaio1 lesstif2 lesstif2-dev make rpm libc6 sun-java6-jre
Es posible tener algún error, por una mezcla de librerías realizada por Oracle, por eso aunque sea en 32 bits instalé las de 64 bits
sudo apt-get install gcc-multilib libc6-dev-i386 libc6-dev-i386 libc6-i386 ia32-libs

Verificar la existencia de los siguientes grupos (si no existen, crearlos).


grupos:
oinstall
dba
nobody
usuario:
usuario (mi usuario)
logear como root
sudo -s
creando los grupos

/usr/sbin/groupadd oinstall
/usr/sbin/groupadd dba

Agregamos el usuario al los grupos
/usr/sbin/usermod  -G oinstall,dba,oper usuario


Crearemos unos enlaces simbólicos, como root.

El instalador espera que los binarios de basename, awk... esten en /bin y no en /usr/bin
sudo ln -s /usr/bin/awk /bin/awk
sudo ln -s /usr/bin/rpm /bin/rpm
sudo ln -s /lib/libgcc_s.so.1 /lib/libgcc_s.so
sudo ln -s /usr/bin/basename /bin/basename

Preparar los directorios donde se va a instalar Oracle.

mkdir -p /punto_montaje/app/oracle
chown -R usuario:oinstall /punto_montaje/app/oracle
chmod -R 775 /punto_montaje/app/oracle

Por ejemplo:
mkdir -p /app/oracle
chown -R usuario:oinstall /app/oracle
chmod -R 775 /app/oracle
mkdir /app/oracle/oradata
chown usuario:oinstall /app/oracle/oradata
chmod 775 /app/oracle/oradata

mkdir /app/oracle/flash_recovery_area
chown usuario:oinstall /app/oracle/flash_recovery_area
chmod 775 /app/oracle/flash_recovery_area

Modificar ficheros.

  • Añadir al archivo .bashrc que se encuentra en el home del usuario
    gedit .bashrc
# Añadido para Instalación Oracle 10.2.0
umask 022
ORACLE_BASE=/home/app/oracle;export ORACLE_BASE
ORACLE_HOME=/home/app/oracle/product/10.2.0/db_1;
export ORACLE_HOME
ORACLE_HOSTNAME=VMUbuntu
export ORACLE_HOSTNAME
ORACLE_SID=orcl;export ORACLE_SID
ORACLE_TERM=xterm;export ORACLE_TERM
ORACLE_OWNER=oracle;export ORACLE_OWNER
NLS_LANG=SPANISH_SPAIN.WE8ISO8859P1; export NLS_LANG
CLASSPATH=${CLASSPATH}:${ORACLE_HOME}/jdbc/lib/classes12.zip
LD_LIBRARY_PATH=${ORACLE_HOME}/lib; export LD_LIBRARY_PATH
DISABLE_HUGETLBFS=1; export DISABLE_HUGETLBFS
TEMP=/tmp; export TEMP
TMPDIR=/tmp; export TMP
PATH=$PATH:/home/app/oracle/product/10.2.0/db_1/bin; export PATH
# Añadido para Instalacion Oracle 10.2.0

  • Añadir al fichero /etc/sysctl.conf
#añadido para instalacion oracle 10g
kernel.shmall = 2097152
kernel.shmmax = 2147483648
kernel.shmmni = 4096
kernel.sem = 250 32000 100 128
net.core.rmem_default = 262144
net.core.rmem_max = 262144
net.core.wmem_default = 262144
net.core.wmem_max = 262144
fs.file-max = 65536
net.ipv4.ip_local_port_range = 1024 65000
#añadido para instalacion oracle 10g

  • Añadir al fichero /etc/security/limits.conf
  •  
     gedit /etc/security/limits.conf
#añadido para instalacion oracle 10g Oracle
oracle soft nproc 2047
oracle hard nproc 16384
oracle soft nofile 1024
oracle hard nofile 65536

  • Añadir al fichero /etc/pam.d/login
  •  gedit /etc/pam.d/login
#añadido para instalacion oracle
session required /lib/security/pam_limits.so

  • Añadir al fichero /etc/profile
  •  gedit /etc/profile
umask 022
#oracle
if [ $USER = "usuario" ]; then
if [ $SHELL = "/bin/ksh" ]; then
ulimit -p 16384
ulimit -n 65536
else
ulimit -u 16384 -n 65536
fi
fi
export ORACLE_BASE=/home/app/oracle
export ORACLE_HOME=/home/app/oracle/product/10.2.0/db_1
export ORACLE_SID=orcl
export PATH=$PATH:$ORACLE_HOME/bin
En un terminal definimos la variable de entorno que indica el nombre del equipo. El nombre será utilizado para conectar via http con OEM, isqlplus:

ORACLE_HOSTNAME=VMUbuntu
export ORACLE_HOSTNAME

Instalar

Para que no dé problemas al instalar Oracle en Ubuntu porque no es un sistema operativo "certificado" tenemos dos alternativas.

Crear un fichero
/etc/redhat-release
sudo gedit /etc/redhat-release

Agregar la línea:
Red Hat Enterprise Linux AS release 3 (Taroon)

Podéis descargar el software Oracle Database 10g Release 2 (10.2.0.1.0) Enterprise/Standard Edition for Linux x86 desde la página oficial de Oracle. (es necesario logearse, sino tenéis cuenta hacer un registro sencillo).
 
Descomprimir los archivos, asegurarse que tienen permisos de ejecución y ejecutar el instalador.

Por ejemplo lo he descomprimido en /tmp
así que:

cd /tmp/Oracle_10.2.0.1.0_Linux32/
chmod 775 -R ../Oracle_10.2.0.1.0_Linux32/

Durante la instalación da un mensaje de error, se le da a continuar. (Cuando encuentre como corregir ese mensaje actualizaré este post. sqlplus, OEM se inician)

Se abrirá el instalador gráfico e ir indicando donde van a instalar, si desean crear una base de datos, contraseña a los usuarios. Y al finalizar indicará como queda configurada la conexión.

URL de iSQL*Plus:
http://VMUbuntu:5562/isqlplus

URL de DBA de iSQL*Plus:
http://VMUbuntu:5562/isqlplus/dba

URL Enterprise Manager 10g Database Control:
http://VMUbuntu:1158/em

Después de instalar Oracle 10g

  • Para administrar (crear, borrar, editar) listeners y otras herramientas de red, como conectarte a una base de datos externa (Asistente de configuración de red):
netca
  • Para administrar tus bases de datos (crear, borrar, etc.) (Asistente de configuración de Base de Datos):
dbca
  • Para iniciar o parar el database control (Oracle Enterprise Manager):
emctl start dbconsole
emctl stop dbconsole
  • Para iniciar o parar el servicio web de iSQL*Plus:
isqlplusctl start
isqlplusctl stop
  • Para iniciar o parar listeners:
lsnrctl start
lsnrctl stop
  • Para entrar a la consola de SQL*Plus:
sqlplus

Para prevenir un error "Failed to auto-start Oracle Net Listene using /ade/vikrkuma_new/oracle/bin/tnslsnr." Editar el fichero /etc/oratab y remplazar una N por una Y
orcl:/home/app/oracle/product/10.2.0/db_1:Y

Iniciar la base de datos oracle manualmente.
lsnrctl start
dbstart
Parar la base de datos oracle manualmente.
dbshut
lsnrctl stop

Fuentes: