{"id":347,"date":"2023-09-03T18:21:31","date_gmt":"2023-09-03T16:21:31","guid":{"rendered":"http:\/\/eines-informatiques.recursos.uoc.edu\/gestion-de-datos\/?page_id=347"},"modified":"2025-03-09T18:35:07","modified_gmt":"2025-03-09T16:35:07","slug":"1-15-triggers-procedimientos-y-funciones","status":"publish","type":"page","link":"http:\/\/eines-informatiques.recursos.uoc.edu\/gestion-de-datos\/es\/1-15-triggers-procedimientos-y-funciones\/","title":{"rendered":"1.15. <em>Triggers<\/em>, procedimientos y funciones"},"content":{"rendered":"<p>La mayor\u00eda de bases de datos relacionales ofrecen la posibilidad de almacenar subprogramas. Se denominan funciones, procedimientos y <em>triggers<\/em> o disparadores, y son muy \u00fatiles para automatizar tareas y guardar instrucciones SQL que se tienen que utilizar frecuentemente. Son objetos que contienen c\u00f3digo SQL, c\u00f3mo breves <em>scripts<\/em> de c\u00f3digo SQL, que pueden aceptar par\u00e1metros y declarar variables.<\/p>\n<p>Se asigna un nombre al subprograma y se ejecuta para que quede almacenado en la base de datos. Despu\u00e9s lo podemos invocar o <em>llamar<\/em> por su nombre porque se ejecute el c\u00f3digo almacenado en los subprogramas.<\/p>\n<ul>\n<li><strong>Procedimiento<\/strong> almacenado. Es un objeto que se crea con la sentencia <code>CREATE PROCEDURE<\/code> y se invoca con la sentencia <code>CALL<\/code>. Los procedimientos pueden aceptar par\u00e1metros y no hacen ning\u00fan retorno, es decir, no devuelven ning\u00fan valor.<\/li>\n<li><strong>Funci\u00f3n<\/strong> almacenada. Es un objeto que se crea con la sentencia <code>CREATE FUNCTION<\/code> y se invoca con la sentencia <strong><code>SELECT <\/code><\/strong>o dentro de una expresi\u00f3n. Las <strong>funciones<\/strong> pueden aceptar par\u00e1metros y devuelven siempre un valor. Este valor devuelto puede ser un valor nulo y en este caso se comportar\u00eda como un procedimiento.<\/li>\n<li><strong><em>Trigger<\/em><\/strong>. Es un objeto que se crea con la sentencia <code>CREATE TRIGGER<\/code> y tiene que estar asociado a una tabla. Un <em>trigger<\/em> se activa, se dispara, cuando ocurre un evento de inserci\u00f3n, actualizaci\u00f3n o borrado, sobre la tabla a la que est\u00e1 asociado.<\/li>\n<\/ul>\n<p>Veamos algunos ejemplos:<\/p>\n<div class=\"featured featured-grey\"><\/p>\n<h3>Procedimientos<\/h3>\n<ol>\n<li>Creamos un procedimiento en la base de datos <strong>catalogo <\/strong>para contar el n\u00famero de genes diferentes de la tabla <strong>refGene<\/strong>, que denominamos <strong>numGenes<\/strong>.<\/li>\n<\/ol>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">CREATE PROCEDURE numGenes()\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\nSELECT COUNT(distinct name2) FROM refGene;<\/pre>\n<p>Este procedimiento no tiene par\u00e1metros () y muestra por pantalla el n\u00famero de genes diferentes que encontramos en el campo <strong>name2 <\/strong>de la tabla <strong>refGene<\/strong>. Al ejecutar el c\u00f3digo, el procedimiento se almacena en la base de datos como un objeto m\u00e1s, como las tablas, y no se ejecuta la consulta <strong><code>SELECT <\/code><\/strong>que contiene hasta que lo llamemos.<\/p>\n<p>Para llamar el procedimiento <strong>numGenes <\/strong>escribimos:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">CALL numGenes();<\/pre>\n<p>Si queremos ver los procedimientos almacenados a la base de datos <strong>catalogo <\/strong>escribimos:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">SHOW PROCEDURE STATUS WHERE db = 'catalogo';<\/pre>\n<p>Si queremos eliminar un procedimiento creado escribimos:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">DROP PROCEDURE IF EXISTS numGenes;<\/pre>\n<ol start=\"2\">\n<li>Ahora vamos a utilizar variables, el resultado del <strong>SELECT<\/strong> lo guardaremos en la variable local <strong>gens<\/strong> que tenemos que declarar y de la cual debemos definir el tipo de datos.<\/li>\n<\/ol>\n<p>Como en el procedimiento hay sentencias que acaban en \u00ab;\u00bb primero asignaremos un nuevo delimitador. Escribimos:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">\u00a0DELIMITER \/\/<\/pre>\n<p>Ahora MySQL interpretar\u00e1 que el final de las sentencias SQL es el s\u00edmbolo \/\/<\/p>\n<p>Crearemos un nuevo procedimiento llamado <strong>numGenes2<\/strong>.<\/p>\n<p>Para declarar la variable <strong>gens<\/strong> necesitamos poner <code>BEGIN<\/code> antes de <code>DECLARE<\/code> y acabar con <code>END<\/code>.<\/p>\n<p>Al declarar las variables locales es necesario especificar qu\u00e9 tipo de dato van a guardar, INT, CHAR, VARCHAR, etc. En este caso es un INT.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">DECLARE gens INT;<\/pre>\n<p>Para guardar el resultado del SELECT en la variable local <strong>gens<\/strong> hacemos:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">INTO gens.<\/pre>\n<p>Para mostrar el contenido de la variable <strong>gens<\/strong> hacemos:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">SELECT gens;<\/pre>\n<p>Vemos todo el c\u00f3digo para crear el nuevo procedimiento usando variables:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">CREATE PROCEDURE numGenes2()\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0        \r\nBEGIN\r\nDECLARE gens INT;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0              \r\nSELECT COUNT(distinct name2)\r\nINTO gens\r\nFROM refGene;\u00a0\u00a0\r\nSELECT gens;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0            \r\nEND \/\/<\/pre>\n<p>Volvemos a cambiar el delimitador para poder usar \u00ab;\u00bb al finalizar la sentencia <code>DELIMITER<\/code> ;<\/p>\n<p>Invocamos el procedimiento:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">\u00a0CALL numGenes2();<\/pre>\n<ol start=\"3\">\n<li>Ahora pasaremos un par\u00e1metro al procedimiento y lo utilizaremos en la condici\u00f3n <code>WHERE<\/code> de la consulta <code>SELECT<\/code>.<\/li>\n<\/ol>\n<p>Creamos un nuevo procedimiento llamado <strong>numTrans<\/strong> que nos servir\u00e1 para contar el n\u00famero de transcritos seg\u00fan el tipo de transcrito que le pasamos como par\u00e1metro.<\/p>\n<p>Al igual que las variables locales, es necesario especificar a los par\u00e1metros qu\u00e9 tipo de datos esperan, INT, CHAR, VARCHAR\u2026 En este caso, <code>CHAR(50)<\/code>.<\/p>\n<p>El par\u00e1metro lo ponemos junto al nombre del procedimiento entre par\u00e9ntesis <code>numTrans(transcritType CHAR(50))<\/code>.<\/p>\n<p>Asignamos otra vez un delimitador \/\/:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">DELIMITER \/\/<\/pre>\n<p>Veamos el c\u00f3digo:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">CREATE PROCEDURE numTrans ( transcritType CHAR(50))\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\nBEGIN\r\nDECLARE numT INT;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0                     \r\nSELECT COUNT(*) INTO numT FROM refGene \r\nWHERE name LIKE transcritType;\u00a0\u00a0\r\nSELECT numT;\r\nEND \/\/<\/pre>\n<p>Cambiamos otra vez el delimitador:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">DELIMITER ;<\/pre>\n<p>Invocamos el procedimiento pas\u00e1ndole el par\u00e1metro NR:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">CALL numTrans('%NR%');<\/pre>\n<p>Ahora invocamos el procedimiento pas\u00e1ndole el par\u00e1metro NM:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">CALL numTrans('%NM%');<\/pre>\n<p>Al usar el comod\u00edn % nos aseguramos que no perdemos ning\u00fan registro con el contenido del par\u00e1metro.<\/p>\n<ol start=\"4\">\n<li>En vez de declarar una variable local dentro de un procedimiento, tambi\u00e9n podemos utilizar un par\u00e1metro como variable de salida. Indicamos que es un par\u00e1metro de salida con la cl\u00e1usula <strong><code>OUT<\/code><\/strong>. Por defecto, los par\u00e1metros son solo de entrada, pero tambi\u00e9n los podemos indicar con la cl\u00e1usula <strong><code>IN<\/code><\/strong>.<\/li>\n<\/ol>\n<p>Asignamos un delimitador \/\/:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">DELIMITER \/\/<\/pre>\n<p>Creamos un nuevo procedimiento llamado <strong>numTrans2<\/strong> que nos servir\u00e1 tambi\u00e9n para contar el n\u00famero de transcritos seg\u00fan el tipo de transcrito que le pasamos como par\u00e1metro, y con un segundo par\u00e1metro que nos servir\u00e1 para guardar el resultado de la consulta.<\/p>\n<p>Veamos el c\u00f3digo:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">CREATE PROCEDURE numTrans2(IN transcritType CHAR(50), OUT numT INT)\u00a0\u00a0\u00a0      \r\nBEGIN\r\nSELECT COUNT(*) INTO numT FROM refGene \r\nWHERE name LIKE transcritType;   \r\nEND \/\/<\/pre>\n<p>Cambiamos el delimitador:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">DELIMITER ;<\/pre>\n<p>Invocamos el procedimiento pas\u00e1ndole los dos par\u00e1metros. Usamos una variable definida por el usuario con @ llamada @transcritos para guardar el valor que devuelve el <strong>SELECT<\/strong> del procedimiento:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">CALL numTrans2('%NR%', @transcrits);<\/pre>\n<p>Hacemos un <strong>SELECT<\/strong> de la variable @transcritos que contiene el n\u00famero de transcritos:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">SELECT @transcrits;<\/pre>\n<p>\n<\/div>\n<div class=\"featured featured-grey\"><\/p>\n<h3>Funciones<\/h3>\n<p>Las funciones devuelven un valor, as\u00ed que, para llamar una funci\u00f3n almacenada, en vez de hacer <code>CALL<\/code> hacemos directamente <code>SELECT nombre_de_la_funci\u00f3n<\/code> y nos muestra el valor que devuelve la funci\u00f3n.<\/p>\n<p>Asignamos un delimitador \/\/:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">DELIMITER \/\/<\/pre>\n<p>Creamos una nueva funci\u00f3n llamada <strong>numTrans3<\/strong> que nos servir\u00e1 tambi\u00e9n para contar el n\u00famero de transcritos seg\u00fan el tipo de transcrito que le pasamos como par\u00e1metro.<\/p>\n<p>En las funciones tenemos que indicar, despu\u00e9s del nombre y de los par\u00e1metros, el tipo de dato que devuelve la funci\u00f3n, en este caso un INT, y escribimos:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">RETURNS INT<\/pre>\n<p>Al final de la funci\u00f3n le indicamos la variable que queremos devolver, en este caso:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">RETURN numT;<\/pre>\n<p>Veamos el c\u00f3digo \u00edntegro de la funci\u00f3n:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">CREATE FUNCTION numTrans3 (transcritType CHAR(50)) RETURNS INT\u00a0\u00a0\u00a0\r\nBEGIN\r\nDECLARE numT INT;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\nSELECT COUNT(*) INTO numT FROM refGene \r\nWHERE name LIKE transcritType;          \r\nRETURN numT;\r\nEND \/\/<\/pre>\n<p>Cambiamos el delimitador:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">DELIMITER ;<\/pre>\n<p>Invocamos la funci\u00f3n pas\u00e1ndole el par\u00e1metro, en este caso les pasamos el par\u00e1metro NR:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">SELECT numTrans3('%NR%');<\/pre>\n<p>Si pasamos a la funci\u00f3n el par\u00e1metro NM:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">SELECT numTrans3('%NM%');<\/pre>\n<p>Si queremos ver las funciones almacenadas a la base de datos <strong>catalogo <\/strong>escribimos la sentencia:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">SHOW FUNCTION STATUS WHERE db = 'catalogo';<\/pre>\n<p>Si queremos eliminar una funci\u00f3n almacenada, escribimos:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">DROP FUNCTION IF EXISTS numTrans3;<\/pre>\n<p>\n<\/div>\n<div class=\"featured featured-grey\"><\/p>\n<h3><em>Triggers<\/em><\/h3>\n<p>Un <em>trigger<\/em> es un objeto almacenado en la base de datos que est\u00e1 asociado con una tabla y que se activa cuando ocurre un evento sobre la tabla.<\/p>\n<p>Los eventos que pueden ocurrir sobre la tabla son:<\/p>\n<ul>\n<li><strong><code>INSERT<\/code><\/strong>. El <em>trigger<\/em> se activa cuando se inserta una nueva fila sobre la tabla asociada.<\/li>\n<li><strong><code>UPDATE<\/code><\/strong>. El <em>trigger<\/em> se activa cuando se actualiza una fila sobre la tabla asociada.<\/li>\n<li><strong><code>DELETE<\/code><\/strong>. El <em>trigger <\/em>se activa cuando se elimina una fila sobre la tabla asociada.<\/li>\n<\/ul>\n<p>El <em>trigger<\/em> se puede activar o disparar antes (<strong><code>BEFORE<\/code><\/strong>) del evento o despu\u00e9s (<strong><code>AFTER<\/code><\/strong>) del evento.<\/p>\n<p>Como ejemplos vamos a crear dos <em>triggers<\/em> asociados a la tabla <em>genes<\/em> de nuestra base de datos <strong>catalogo<\/strong>:<\/p>\n<p>Un <em>trigger<\/em> con el nombre de <strong>trig_check_genes_before_insert <\/strong>que se asocia a la tabla <strong>genes<\/strong>. Se activa antes de una operaci\u00f3n de inserci\u00f3n. Si el nuevo valor del campo inicio que se quiere insertar es negativo, se guarda como 0. Si el nuevo valor del campo <strong>final <\/strong>que se quiere insertar es menor que el valor del campo <strong>inicio<\/strong>, se guarda el valor del campo <strong>inicio<\/strong>.<\/p>\n<p>Un <em>trigger<\/em> con el nombre de <strong>trig_check_genes_before_update<\/strong> que se asocia a la tabla <strong>genes<\/strong>. Se activa antes de una operaci\u00f3n de modificaci\u00f3n. Si el nuevo valor del campo <strong>inicio <\/strong>que se quiere modificar es negativo, se guarda como 0. Si el valor del campo <strong>final <\/strong>del registro que se quiere modificar es menor que el nuevo valor que queremos actualizar del campo <strong>inicio <\/strong>se guarda como 1.<\/p>\n<p>Creamos el <em>trigger<\/em> <strong>trig_check_genes_before_insert<\/strong><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">DELIMITER \/\/\r\nCREATE TRIGGER trig_check_genes_before_insert\u00a0\u00a0\u00a0\u00a0\u00a0 \r\nBEFORE INSERT\r\nON genes FOR EACH ROW\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\nBEGIN IF NEW.inicio &lt; 0 THEN SET NEW.inicio = 0;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\nELSEIF NEW.inicio &gt; NEW.final THEN SET NEW.final = NEW.inicio;\u00a0\u00a0\u00a0\u00a0\u00a0 \r\nEND IF;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0           \u00a0\r\nEND\/\/<\/pre>\n<p>Al ejecutar este c\u00f3digo de creaci\u00f3n del <em>trigger,<\/em> <strong>trig_check_genes_before_insert<\/strong> queda almacenado en nuestra base de datos, y solo actuar\u00e1, se activar\u00e1 cuando el usuario ejecute una sentencia de inserci\u00f3n, por ejemplo:<\/p>\n<p>Cambiamos el delimitador:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">DELIMITER ;<\/pre>\n<p>Realizamos operaciones de inserci\u00f3n en la tabla genes para que se dispare el <em>trigger <\/em><strong>trig_check_genes_before_insert<\/strong>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">INSERT INTO genes (nombre, cromosoma, hebra, inicio, final, proteina, especie) VALUES ('WASH7P', 'chrX', '+', -2527305, 2575270,'NR_033380', 'H. Sapiens');\r\n\r\nINSERT INTO genes (nombre, cromosoma, hebra, inicio, final, proteina, especie) VALUES ('WASH7P2', 'chrX', '+', 252730599, 2575270,'NR_033381', 'H. Sapiens');<\/pre>\n<p>La variable compuesta <strong><code>NEW<\/code><\/strong> que utilizamos en el <em>trigger<\/em> almacena todos los valores que insertamos en cada operaci\u00f3n <strong><code>INSERT<\/code><\/strong>. De esta forma podemos usarla en el <em>trigger<\/em> sin conocer <em>a priori<\/em> qu\u00e9 valores se van a insertar.<\/p>\n<p>En nuestros ejemplos la variable<strong> NEW.inicio<\/strong> contiene en el primer <strong><code>INSERT<\/code><\/strong> el valor -2527305 y en el segundo <strong><code>INSERT<\/code><\/strong> la variable <strong>NEW.inicio <\/strong>contiene el valor 252730599 y la variable<strong> NEW.fina<\/strong>l contiene el valor <code>2575270<\/code><\/p>\n<p>En el primer <strong>INSERT <\/strong>se cumple <code>NEW.inicio &lt; 0<\/code>, esta condici\u00f3n dispara el <em>trigger<\/em> y en el campo <strong>inicio<\/strong> se guarda el valor 0.<\/p>\n<p>En el segundo <strong>INSERT<\/strong> se cumple <code>NEW.inicio &gt; NEW.final<\/code>, esta condici\u00f3n dispara el <em>trigger<\/em> y en el campo <strong>final<\/strong> se guarda el valor <code>252730599<\/code>.<\/p>\n<p>Ahora creamos el <em>trigger<\/em> <strong>trig_check_genes_before_update<\/strong>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">DELIMITER \/\/\r\nCREATE TRIGGER trig_check_genes_before_update \r\nBEFORE UPDATE ON genes \r\nFOR EACH ROW \r\nBEGIN \r\nIF NEW.inicio &lt; 0 THEN SET NEW.inicio = 0;\r\nELSEIF NEW.inicio &gt; OLD.final THEN SET NEW.inicio = 1; \r\nEND IF; \r\nEND \/\/<\/pre>\n<p>Al ejecutar este c\u00f3digo de creaci\u00f3n del <em>trigger<\/em>, <strong>trig_check_genes_before_update <\/strong>queda almacenado en nuestra base de datos, y solo actuar\u00e1, se activar\u00e1 cuando el usuario ejecute una sentencia de actualizaci\u00f3n, por ejemplo:<\/p>\n<p>Cambiamos el delimitador:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">DELIMITER ;<\/pre>\n<p>Realizamos operaciones de modificaci\u00f3n en la tabla genes para que se dispare el <em>trigger <\/em><strong>trig_check_genes_before_update<\/strong>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"droide\">UPDATE genes SET inicio = 228748314 WHERE nombre = 'MYC';\r\n\r\nUPDATE genes SET inicio = -47643 WHERE nombre = 'cbt';<\/pre>\n<p>En este caso, la variable compuesta <strong>NEW<\/strong> que utilizamos en el <em>trigger<\/em> almacena el nuevo valor que queremos actualizar en la sentencia <strong>UPDATE<\/strong>. En el primer <strong>UPDATE<\/strong> la variable <code>NEW.inicio<\/code> contiene el valor <code>228748314<\/code> y en el segundo <strong>UPDATE<\/strong> la variable <code>NEW.inicio<\/code> contiene el valor &#8211;<code>47643<\/code>.<\/p>\n<p>En cambio, la variable compuesta <strong>OLD<\/strong> almacena todos los valores viejos ya almacenados en la tabla del registro que se quiere actualizar. En el primer <strong>UPDATE<\/strong>, la variable <code>OLD.final<\/code> contiene el valor almacenado en el campo final del registro con clave primaria <strong>&#8216;MYC&#8217; <\/strong>en la tabla <strong>genes<\/strong>, y en el segundo <strong>UPDATE<\/strong>, la variable <code>OLD.final<\/code> contiene el valor almacenado en el campo final del registro con clave primaria <strong>&#8216;cbt&#8217;<\/strong>.<\/p>\n<p>En el primer <strong>UPDATE<\/strong> se cumple <code>NEW.inicio &gt; OLD.final<\/code>, esta condici\u00f3n dispara el <em>trigger<\/em> y en el campo inicio se guarda el valor 1.<\/p>\n<p>En el segundo <strong>UPDATE <\/strong>se cumple <code>NEW.inicio &lt; 0<\/code> , esta condici\u00f3n dispara el <em>trigger<\/em> y en el campo inicio se guarda el valor 0.<\/p>\n<p>En las operaciones <strong>DELETE<\/strong> solo se utiliza la variable compuesta <strong>OLD<\/strong> capaz de almacenar todos los valores del registro que se quiere eliminar y acceder a ellos con el formato <code>OLD.nombre_campo<\/code>.<\/p>\n<p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>La mayor\u00eda de bases de datos relacionales ofrecen la posibilidad de almacenar subprogramas. Se denominan funciones, procedimientos y triggers o disparadores, y son muy \u00fatiles para automatizar tareas y guardar instrucciones SQL que se tienen que utilizar frecuentemente. Son objetos que contienen c\u00f3digo SQL, c\u00f3mo breves scripts de c\u00f3digo SQL, que pueden aceptar par\u00e1metros y [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":[],"acf":[],"_links":{"self":[{"href":"http:\/\/eines-informatiques.recursos.uoc.edu\/gestion-de-datos\/es\/wp-json\/wp\/v2\/pages\/347"}],"collection":[{"href":"http:\/\/eines-informatiques.recursos.uoc.edu\/gestion-de-datos\/es\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"http:\/\/eines-informatiques.recursos.uoc.edu\/gestion-de-datos\/es\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"http:\/\/eines-informatiques.recursos.uoc.edu\/gestion-de-datos\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/eines-informatiques.recursos.uoc.edu\/gestion-de-datos\/es\/wp-json\/wp\/v2\/comments?post=347"}],"version-history":[{"count":19,"href":"http:\/\/eines-informatiques.recursos.uoc.edu\/gestion-de-datos\/es\/wp-json\/wp\/v2\/pages\/347\/revisions"}],"predecessor-version":[{"id":1019,"href":"http:\/\/eines-informatiques.recursos.uoc.edu\/gestion-de-datos\/es\/wp-json\/wp\/v2\/pages\/347\/revisions\/1019"}],"wp:attachment":[{"href":"http:\/\/eines-informatiques.recursos.uoc.edu\/gestion-de-datos\/es\/wp-json\/wp\/v2\/media?parent=347"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}