Anuncios en tutorial de programación PLSQL

viernes, 30 de diciembre de 2016

Diferencias entre restricciones PLSQL (cláusula CONSTRAINT) a nivel de tabla y a nivel de columna

Diferencias entre restricciones PLSQL (cláusula CONSTRAINT) a nivel de tabla y a nivel de columnaResulta de perogrullo decir que una restricción PLSQL (cláusula CONSTRAINT) a nivel de columna sólo aplica a la columna sobre la que se ha definido, mientras que una restricción a nivel de tabla puede incluir todas las columnas de dicha tabla. Esta es la diferencia básica en PL/SQL, pero también conviene señalar que cualquier restricción a nivel de columna puede definirse también a nivel de tabla, sin embargo, no todas las restricciones a nivel de tabla pueden definirse a nivel de columna.

Ojo, no estoy diciendo que todas las restricciones deban definirse a nivel de tabla, simplemente estoy diciendo que es posible hacerlo. De hecho, mi opinión es que, siempre que se pueda expresar una restricción utilizando una CONSTRAINT PLSQL a nivel de columna, debemos hacerlo de esta manera. Una razón evidente es que una restricción a nivel de columna es sintácticamente más clara ya que resulta obvio que aplica a sólo una columna, mientras que si utilizamos una CONSTRAINT a nivel de tabla para definir la misma restricción, deberemos prestar más atención al código PL/SQL para comprender lo que hace. Pero esta no es la única razón, las hay todavía de mayor peso.

Antes de empezar con el ejemplo, creo que resulta conveniente mencionar que, a nivel de tiempos de ejecución, las restricciones a nivel de tabla y a nivel de columna son idénticas. Es decir, no hay diferencias en los tiempos de ejecución al emplear una u otra opción.

A continuación os expongo un caso mucho más indicativo de por qué deben utilizarse las restricciones a nivel de columna cuando esto es posible. Una restricción NOT NULL se implementa técnicamente en las bases de datos Oracle con una restricción de tipo CHECK. Así, por ejemplo, si creamos la siguiente tabla:

SQL> CREATE TABLE ejemplo
2    ( a INT NOT NULL,
3      b INT CHECK(b IS NOT NULL),
4      c INT,
5      CONSTRAINT c_chk CHECK(c IS NOT NULL)
6    );

Table created.

Podremos comprobar de una manera muy sencilla que las tres restricciones aparecen definidas de la misma manera en el diccionario de datos de la base de datos Oracle.

SQL> SELECT constraint_type,
2           search_condition
3    FROM   user_constraints
4    WHERE  table_name = 'EJEMPLO';

C SEARCH_CONDITION
— ————————————————
C "A" IS NOT NULL
C b IS NOT NULL
C c IS NOT NULL

Por lo tanto, podemos ver que las tres restricciones, aunque han sido creadas de forma distinta, todas se han generado como una restricción de tipo CHECK (el valor C de la columna CONSTRAINT_TYPE es la inicial de CHECK).

No obstante, si una columna es NOT NULL, debemos utilizar siempre la restricción NOT NULL en lugar de una restricción CHECK que realice el chequeo de que la columna es NOT NULL. La razón es que el optimizador PLSQL de las bases de datos Oracle reconoce la existencia de las restricciones NOT NULL sobre una columna, mientras que no es capaz de reconocer la existencia de una restricción CHECK sobre la misma columna. Seguro que ahora muchos os estaréis preguntando, ¿y qué más da que el optimizador sea capaz de identificar si una columna es NOT NULL?

Ciertamente no da lo mismo, imaginad que definimos un índice sobre la columna A de nuestra tabla EJEMPLO, en este caso el optimizador PL/SQL será capaz de utilizar dicho índice para ejecutar un COUNT(*). Sin embargo, si reemplazamos dicho índice y lo definimos sobre las columnas B o C, en ninguno de los casos el optimizador podrá utilizar dichos índices para ejecutar el COUNT(*). La razón es bien sencilla, en el primero de los casos el optimizador PLSQL sabía que la columna A era NOT NULL y que el índice sobre dicha columna apuntaba a todos y cada uno de los registros de la tabla EJEMPLO, por lo que era posible utilizar el índice para contar el número de registros de la misma. Sin embargo, al utilizar las otras dos columnas, el optimizador no es capaz de llegar a la misma conclusión porque la restricción CHECK no le proporciona la misma información que una restricción NOT NULL directa, concluyendo que los índices sobre las columnas B o C podrían no apuntar a todos los registros de la tabla, ya que las columnas con valor NULL no se incluyen en el índice.

En conclusión, este hecho demuestra que siempre es conveniente ser lo más específico posible y utilizar las restricciones a nivel de columna en lugar de a nivel de tabla cuando esto sea posible. De esta manera estaremos aportando más información al optimizador PLSQL.

Artículos relacionados: Cláusula CONSTRAINT para mejorar el rendimiento de las consultas PL/SQL.

3 comentarios:

F_decea dijo...

Gracias por el aporte. Interesante ; )

Juan Angel Jimenez Chaves dijo...

Hola Jose Luís,.

Me gustaría agradecerte tu labor y preguntarte, ¿Conoces alguna empresa de formación donde poder realizar un curso avanzado de PL SQL con garantías?
Y a parte de tu blog, algun otro portal en español para aprender sobre esta tecnología?

gracias

José Luis Pérez dijo...

Hola Juan Ángel,

No conozco ninguna empresa de formación con cursos de PLSQL avanzado. Oracle seguro que imparte cursos y seguro que es la mejor opción. Son caros pero los pocos que he hecho han merecido la pena.

En cuanto a otros blogs en español, mira a ver si encuentras alguno aquí:

http://www.oracle.com/technetwork/es/testcontent/index-321433-esa.html