{"id":368,"date":"2011-11-14T08:00:19","date_gmt":"2011-11-14T13:00:19","guid":{"rendered":"http:\/\/www.latindevelopers.com\/ivancp\/?p=368"},"modified":"2011-11-21T09:45:24","modified_gmt":"2011-11-21T14:45:24","slug":"simulando-secuencias-en-mysql","status":"publish","type":"post","link":"https:\/\/www.latindevelopers.com\/ivancp\/2011\/11\/simulando-secuencias-en-mysql\/","title":{"rendered":"Simulando secuencias en MySQL"},"content":{"rendered":"<p><img data-attachment-id=\"249\" data-permalink=\"https:\/\/www.latindevelopers.com\/ivancp\/2011\/04\/show-table-status-mejorado\/logo-mysql-170x115\/\" data-orig-file=\"https:\/\/www.latindevelopers.com\/ivancp\/wp-content\/uploads\/logo-mysql-170x115-e1302270861102.png\" data-orig-size=\"100,67\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}\" data-image-title=\"Logo mysql\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/www.latindevelopers.com\/ivancp\/wp-content\/uploads\/logo-mysql-170x115-e1302270861102.png\" data-large-file=\"https:\/\/www.latindevelopers.com\/ivancp\/wp-content\/uploads\/logo-mysql-170x115-e1302270861102.png\" loading=\"lazy\" class=\"alignright size-full wp-image-249\" title=\"Logo mysql\" src=\"http:\/\/www.latindevelopers.com\/ivancp\/wp-content\/uploads\/logo-mysql-170x115-e1302270861102.png\" alt=\"\" width=\"100\" height=\"67\" \/>Quienes hemos usado PostgresSQL solemos fastidiarnos con el c\u00f3digo que hay que escribir para tener un campo auto-num\u00e9rico, pero tambi\u00e9n hemos llegado a extra\u00f1ar esa caracter\u00edstica cuando usamos MySQL.<\/p>\n<p>Como sabemos MySQL, usa la propiedad AUTO_INCREMENT para campos num\u00e9ricos que usamos en claves primarias.<\/p>\n<p><strong>Pero en que situaciones podemos necesitar una secuencia?<\/strong> pues les doy algunas ideas:<\/p>\n<ul>\n<li>Cuando queremos tener mas de un campo auto-num\u00e9rico en una tabla.<\/li>\n<li>Cuando necesitamos un contador general que podemos utilizar en mas de una tabla.<\/li>\n<li>No se me ocurren mas, pero estoy seguro que en alg\u00fan momento podemos darle un uso.<\/li>\n<\/ul>\n<p><strong>Manos a la obra:<\/strong><\/p>\n<p>Necesitaremos una tabla para guardar el valor actual de la secuencia:<\/p>\n<pre lang=\"mysql\">create table _sequence\r\n(\r\n\tseq_name varchar(50) not null primary key,\r\n\tseq_val int unsigned not null\r\n);\r\n<\/pre>\n<p>Vamos a necesitar tambi\u00e9n una funci\u00f3n para obtener el valor siguiente de la secuencia, incluyendo casos como:<\/p>\n<ul>\n<li>Si no existe la secuencia, crearla (para qu\u00e9 complicarnos). <\/li>\n<li>Actualizar el nuevo valor para la siguiente llamada<\/li>\n<\/li>\n<p>&nbsp;<\/p>\n<p>He aqu\u00ed la funci\u00f3n <code>getNextSeq<\/code> que recibe como par\u00e1metro, el nombre de la secuencia:<\/p>\n<pre lang=\"mysql\">\/*Funcion que devuelve el siguiente valor de una secuencia*\/\r\ndelimiter \/\/\r\ndrop function if exists getNextSeq\/\/\r\n \r\ncreate function getNextSeq(sSeqName varchar(50)) returns int unsigned\r\nbegin\r\n    declare nLast_val int;\r\n\r\n    set nLast_val =  (select seq_val \r\n                          from _sequence \r\n                          where seq_name = sSeqName);\r\n    if nLast_val is null then\r\n        set nLast_val = 1;\r\n        insert into _sequence (seq_name,seq_val) \r\n        values (sSeqName,nLast_Val);\r\n    else\r\n        set nLast_val = nLast_val + 1;\r\n        update _sequence set seq_val = nLast_val \r\n        where seq_name = sSeqName;\r\n    end if;\r\n\r\n    return nLast_val;\r\nend\/\/\r\n \r\ndelimiter ;<\/pre>\n<p>&nbsp;<\/p>\n<p>Ahora necesitamos (a manera de mantenimiento) un procedimiento para modificar el valor de una secuencia:<\/p>\n<pre lang=\"mysql\">\/*Procedimiento que crea\/establece el valor de una secuencia*\/\r\ndelimiter \/\/\r\ndrop procedure if exists sp_setSeqVal\/\/\r\n\r\ncreate procedure sp_setSeqVal(sSeqName varchar(50), nVal int unsigned)\r\nbegin\r\n    if (select count(*) from _sequence where seq_name = sSeqName) = 0 then\r\n        insert into _sequence (seq_name,seq_val) \r\n        values (sSeqName,nVal);\r\n    else\r\n        update _sequence set seq_val = nVal \r\n        where seq_name = sSeqName;\r\n    end if;\r\nend\/\/\r\n\r\ndelimiter ;\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Es todo!<\/strong>, ahora s\u00f3lo necesitamos hacer algunas pruebas, para ello vamos a crear una tabla en la cual vamos a tener dos campos auto-generados con nuestra secuencia.<\/p>\n<pre lang=\"mysql\">create table multiple_autonums\r\n(\r\n   id int not null primary key auto_increment,\r\n   seq_1 int, -- Secuencia 1\r\n   seq_2 int, -- Secuencia 2\r\n   unique(seq_1),\r\n   unique(seq_2)\r\n);<\/pre>\n<p>Para que la magia ocurra debemos crear tambi\u00e9n un trigger antes de insertar:<\/p>\n<pre lang=\"mysql\">\/*trigger ejecutado antes de insertar que obtiene\r\n  los siguientes valores de las secuencias*\/\r\n\r\ndelimiter \/\/\r\ndrop trigger if exists multiple_autonums_ai\/\/\r\n\r\ncreate trigger multiple_autonums_bi before insert on multiple_autonums\r\nfor each row\r\nbegin\r\n   set new.seq_1 = getNextSeq(\"seq_1\");\r\n   set new.seq_2 = getNextSeq(\"seq_2\");\r\nend\/\/\r\n\r\ndelimiter ;\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Hagamos algunas pruebas<\/p>\n<pre lang=\"mysql\">-- insertando valores para ver que pasa.\r\ninsert into multiple_autonums (id) values (null),(null),(null);\r\n\r\n-- Resultado de la primera inserci\u00f3n\r\nselect * from multiple_autonums;\r\n+----+-------+-------+\r\n| id | seq_1 | seq_2 |\r\n+----+-------+-------+\r\n|  1 |     1 |     1 |\r\n|  2 |     2 |     2 |\r\n|  3 |     3 |     3 |\r\n+----+-------+-------+\r\n3 rows in set (0.00 sec)\r\n\r\n-- Modificando las secuencias\r\ncall sp_setSeqVal(\"seq_1\",47);\r\ncall sp_setSeqVal(\"seq_2\",9786);\r\n\r\n-- Insertando nuevamente los valores\r\ninsert into multiple_autonums (id) values (null),(null),(null);\r\n\r\n-- Viendo que ha pasado\r\nselect * from multiple_autonums;\r\n+----+-------+-------+\r\n| id | seq_1 | seq_2 |\r\n+----+-------+-------+\r\n|  1 |     1 |     1 |\r\n|  2 |     2 |     2 |\r\n|  3 |     3 |     3 |\r\n|  4 |    48 |  9787 |\r\n|  5 |    49 |  9788 |\r\n|  6 |    50 |  9789 |\r\n+----+-------+-------+\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Que les pareci\u00f3? <\/p>\n<p>Me acabo de dar cuenta que hay algunas condiciones que no he tomado en cuenta, pero de todas formas sirve. Incluso pueden modificar las funciones para hacer mas complejo el calculo del valor siguiente, se me ocurre por ejemplo que podemos generar numeros de facturas al estilo: [serie]-[numero] ejem:  001-00485<\/p>\n<p>Espero les sirva.<\/p>\n<div class=\"sharedaddy sd-sharing-enabled\"><div class=\"robots-nocontent sd-block sd-social sd-social-icon-text sd-sharing\"><h3 class=\"sd-title\">Compartelo:<\/h3><div class=\"sd-content\"><ul><li class=\"share-facebook\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-facebook-368\" class=\"share-facebook sd-button share-icon\" href=\"https:\/\/www.latindevelopers.com\/ivancp\/2011\/11\/simulando-secuencias-en-mysql\/?share=facebook\" target=\"_blank\" title=\"Haz clic para compartir en Facebook\"><span>Facebook<\/span><\/a><\/li><li class=\"share-twitter\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-twitter-368\" class=\"share-twitter sd-button share-icon\" href=\"https:\/\/www.latindevelopers.com\/ivancp\/2011\/11\/simulando-secuencias-en-mysql\/?share=twitter\" target=\"_blank\" title=\"Haz clic para compartir en Twitter\"><span>Twitter<\/span><\/a><\/li><li><a href=\"#\" class=\"sharing-anchor sd-button share-more\"><span>M\u00e1s<\/span><\/a><\/li><li class=\"share-end\"><\/li><\/ul><div class=\"sharing-hidden\"><div class=\"inner\" style=\"display: none;\"><ul><li class=\"share-email\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"\" class=\"share-email sd-button share-icon\" href=\"https:\/\/www.latindevelopers.com\/ivancp\/2011\/11\/simulando-secuencias-en-mysql\/?share=email\" target=\"_blank\" title=\"Haz clic para enviar por correo electr\u00f3nico a un amigo\"><span>Correo electr\u00f3nico<\/span><\/a><\/li><li class=\"share-print\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"\" class=\"share-print sd-button share-icon\" href=\"https:\/\/www.latindevelopers.com\/ivancp\/2011\/11\/simulando-secuencias-en-mysql\/\" target=\"_blank\" title=\"Haz clic para imprimir\"><span>Imprimir<\/span><\/a><\/li><li class=\"share-end\"><\/li><li class=\"share-linkedin\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-linkedin-368\" class=\"share-linkedin sd-button share-icon\" href=\"https:\/\/www.latindevelopers.com\/ivancp\/2011\/11\/simulando-secuencias-en-mysql\/?share=linkedin\" target=\"_blank\" title=\"Haz clic para compartir en LinkedIn\"><span>LinkedIn<\/span><\/a><\/li><li class=\"share-end\"><\/li><\/ul><\/div><\/div><\/div><\/div><\/div>","protected":false},"excerpt":{"rendered":"<p>Quienes hemos usado PostgresSQL solemos fastidiarnos con el c\u00f3digo que hay que escribir para tener un campo auto-num\u00e9rico, pero tambi\u00e9n hemos llegado a extra\u00f1ar esa caracter\u00edstica cuando usamos MySQL. Como sabemos MySQL, usa la propiedad AUTO_INCREMENT para campos num\u00e9ricos que &hellip; <a href=\"https:\/\/www.latindevelopers.com\/ivancp\/2011\/11\/simulando-secuencias-en-mysql\/\">Sigue leyendo <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n<div class=\"sharedaddy sd-sharing-enabled\"><div class=\"robots-nocontent sd-block sd-social sd-social-icon-text sd-sharing\"><h3 class=\"sd-title\">Compartelo:<\/h3><div class=\"sd-content\"><ul><li class=\"share-facebook\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-facebook-368\" class=\"share-facebook sd-button share-icon\" href=\"https:\/\/www.latindevelopers.com\/ivancp\/2011\/11\/simulando-secuencias-en-mysql\/?share=facebook\" target=\"_blank\" title=\"Haz clic para compartir en Facebook\"><span>Facebook<\/span><\/a><\/li><li class=\"share-twitter\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-twitter-368\" class=\"share-twitter sd-button share-icon\" href=\"https:\/\/www.latindevelopers.com\/ivancp\/2011\/11\/simulando-secuencias-en-mysql\/?share=twitter\" target=\"_blank\" title=\"Haz clic para compartir en Twitter\"><span>Twitter<\/span><\/a><\/li><li><a href=\"#\" class=\"sharing-anchor sd-button share-more\"><span>M\u00e1s<\/span><\/a><\/li><li class=\"share-end\"><\/li><\/ul><div class=\"sharing-hidden\"><div class=\"inner\" style=\"display: none;\"><ul><li class=\"share-email\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"\" class=\"share-email sd-button share-icon\" href=\"https:\/\/www.latindevelopers.com\/ivancp\/2011\/11\/simulando-secuencias-en-mysql\/?share=email\" target=\"_blank\" title=\"Haz clic para enviar por correo electr\u00f3nico a un amigo\"><span>Correo electr\u00f3nico<\/span><\/a><\/li><li class=\"share-print\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"\" class=\"share-print sd-button share-icon\" href=\"https:\/\/www.latindevelopers.com\/ivancp\/2011\/11\/simulando-secuencias-en-mysql\/\" target=\"_blank\" title=\"Haz clic para imprimir\"><span>Imprimir<\/span><\/a><\/li><li class=\"share-end\"><\/li><li class=\"share-linkedin\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-linkedin-368\" class=\"share-linkedin sd-button share-icon\" href=\"https:\/\/www.latindevelopers.com\/ivancp\/2011\/11\/simulando-secuencias-en-mysql\/?share=linkedin\" target=\"_blank\" title=\"Haz clic para compartir en LinkedIn\"><span>LinkedIn<\/span><\/a><\/li><li class=\"share-end\"><\/li><\/ul><\/div><\/div><\/div><\/div><\/div>","protected":false},"author":1,"featured_media":249,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spay_email":""},"categories":[7,10,22],"tags":[12,30],"jetpack_featured_media_url":"https:\/\/www.latindevelopers.com\/ivancp\/wp-content\/uploads\/logo-mysql-170x115-e1302270861102.png","jetpack_shortlink":"https:\/\/wp.me\/p1tEO5-5W","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.latindevelopers.com\/ivancp\/wp-json\/wp\/v2\/posts\/368"}],"collection":[{"href":"https:\/\/www.latindevelopers.com\/ivancp\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.latindevelopers.com\/ivancp\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.latindevelopers.com\/ivancp\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.latindevelopers.com\/ivancp\/wp-json\/wp\/v2\/comments?post=368"}],"version-history":[{"count":9,"href":"https:\/\/www.latindevelopers.com\/ivancp\/wp-json\/wp\/v2\/posts\/368\/revisions"}],"predecessor-version":[{"id":401,"href":"https:\/\/www.latindevelopers.com\/ivancp\/wp-json\/wp\/v2\/posts\/368\/revisions\/401"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.latindevelopers.com\/ivancp\/wp-json\/wp\/v2\/media\/249"}],"wp:attachment":[{"href":"https:\/\/www.latindevelopers.com\/ivancp\/wp-json\/wp\/v2\/media?parent=368"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.latindevelopers.com\/ivancp\/wp-json\/wp\/v2\/categories?post=368"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.latindevelopers.com\/ivancp\/wp-json\/wp\/v2\/tags?post=368"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}