{"id":711,"date":"2019-06-06T14:28:51","date_gmt":"2019-06-06T18:58:51","guid":{"rendered":"http:\/\/gregorgonzalez.com.ve\/blog\/?p=711"},"modified":"2019-06-06T14:37:32","modified_gmt":"2019-06-06T19:07:32","slug":"limit-en-oracle","status":"publish","type":"post","link":"https:\/\/gregorgonzalez.com.ve\/blog\/limit-en-oracle\/","title":{"rendered":"Limit en Oracle"},"content":{"rendered":"<p>Al venir de otros manejadores de base de datos, como por ejemplo Mysql, Postgres, SQLite, ya conocemos la forma de limitar registros con la clausula LIMIT, dicha clausula no existe en Oracle (tampoco en SQLServer) y siempre ha sido una pol\u00e9mica entre los usuarios por lo importante que es.<\/p>\n<p>C\u00f3mo ya estamos acostumbrados, lo consideramos como parte del est\u00e1ndar pero no lo es, no se contempla entre los est\u00e1ndares de SQL, as\u00ed que es com\u00fan que otros manejadores no tengan esta opci\u00f3n.<\/p>\n<p>La primera vez que necesit\u00e9 esta opci\u00f3n con Oracle, dur\u00e9 varias horas buscando la alternativa adecuada. Hay varias maneras de limitar pero su comportamiento es distinto.<\/p>\n<p>Ejemplo, tenemos una simple tabla Libros con dos columnas id y titulo. Para limitar los registros en un select, podemos usar la clausula ROWNUM, la cual genera un conteo de los registros, le asigna un n\u00famero al resultado y luego lo utilizamos.<\/p>\n<p>&nbsp;<\/p>\n<p><strong>Simple Limit<\/strong><\/p>\n<pre class=\"lang:plsql decode:true\">SELECT * FROM libros WHERE ROWNUM &lt;= 3;<\/pre>\n<p>Con la anterior consulta limitamos a 3 registros, algo simple y r\u00e1pido pero tiene un detalle a la hora de ordenar, ya que ROWNUM ocurre antes del ordenamiento. Esto significa que tomar\u00e1 registros aleatorios, ejecutar\u00e1 el l\u00edmite y luego ordenar\u00e1 lo resultante. Esto es completamente al rev\u00e9s en otros manejadores, donde ordena primero y luego ejecuta el l\u00edmite.<\/p>\n<p>&nbsp;<\/p>\n<p><strong>Limit con ordenamiento (Problema)<\/strong><\/p>\n<pre class=\"lang:plsql decode:true \">SELECT * FROM libros \r\nWHERE ROWNUM &lt;= 3\r\nORDER BY titulo ASC;<\/pre>\n<p>Ya uses ASC o DESC, siempre traer\u00e1 los mismos registros, es decir, en otros manejadores el order by, te trae o los primeros 3 registros de la tabla o los 3 \u00faltimos registros de la tabla pero en Oracle no, en Oracle te trae los mismos registros siempre y luego los ordena.<\/p>\n<p>Para evitar este inconveniente se debe usar el conteo ROWNUM despu\u00e9s y la \u00fanica forma es utilizando subquery donde la consulta superior se encargar\u00e1 de ordenar:<\/p>\n<p>&nbsp;<\/p>\n<p><strong>Limit y con ordenamieto similar a Mysql, Postgres<\/strong><\/p>\n<pre class=\"lang:plsql decode:true\">SELECT * FROM (\r\n  SELECT a.* FROM libros a\r\n  ORDER BY titulo ASC\r\n) WHERE ROWNUM BETWEEN 1 AND 3;<\/pre>\n<p>El anterior utiliza between pero tambi\u00e9n podemos usar las comunes \u00abmayor igual\u00bb y \u00abmenor igual\u00bb:<\/p>\n<pre class=\"lang:plsql decode:true \">SELECT * FROM (\r\n  SELECT a.* FROM libros a\r\n  ORDER BY a.titulo ASC\r\n) WHERE ROWNUM &gt;=1 AND ROWNUM &lt;=3;<\/pre>\n<p>&nbsp;<\/p>\n<p><strong>Compleja pero r\u00e1pida<\/strong><\/p>\n<p>En internet se encontrar\u00e1 muchas m\u00e1s formas, anidadas, complejas y la m\u00e1s optimizada por la velocidad es esta:<\/p>\n<pre class=\"lang:plsql decode:true \">SELECT * FROM (\r\n  SELECT a.*, ROWNUM AS num FROM (\r\n    SELECT * FROM libros ORDER BY titulo ASC\r\n  ) a WHERE ROWNUM &lt;= 3\r\n) WHERE num &gt;= 1<\/pre>\n<p>Aunque no me agrada tanta anidaci\u00f3n, cuando trabajas con millones de registros, es la m\u00e1s r\u00e1pida.<\/p>\n<p>&nbsp;<\/p>\n<p><strong>Limitando con Offset<\/strong><\/p>\n<p>Otra forma implementada a partir de Oracle 12C R1 (12.1), es la clausula OFFSET, algo m\u00e1s familiar y que nos permite realizar paginaci\u00f3n f\u00e1cilmente:<\/p>\n<pre class=\"lang:plsql decode:true\">SELECT * FROM libros\r\nORDER BY titulo\r\nOFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;<\/pre>\n<p>Donde indica que despu\u00e9s de las primeras 20 filas, tomar\u00e1 las siguientes 10. Bastante \u00fatil y aunque el offset es familiar, el fetch next only es algo completamente nuevo y difiere de los dem\u00e1s manejadores, por lo tanto debemos acostumbrarnos que en Oracle todo es y seguir\u00e1 siendo diferente en comparaci\u00f3n con los dem\u00e1s, complicando la estandarizaci\u00f3n de nuestras consultas.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Al venir de otros manejadores de base de datos, como por ejemplo Mysql, Postgres, SQLite, ya conocemos la forma de limitar registros con la clausula LIMIT, dicha clausula no existe en Oracle (tampoco en SQLServer) y siempre ha sido una pol\u00e9mica entre los usuarios por lo importante que es. C\u00f3mo ya estamos acostumbrados, lo consideramos [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":660,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"footnotes":""},"categories":[239],"tags":[260,261,262,263],"_links":{"self":[{"href":"https:\/\/gregorgonzalez.com.ve\/blog\/wp-json\/wp\/v2\/posts\/711"}],"collection":[{"href":"https:\/\/gregorgonzalez.com.ve\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/gregorgonzalez.com.ve\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/gregorgonzalez.com.ve\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/gregorgonzalez.com.ve\/blog\/wp-json\/wp\/v2\/comments?post=711"}],"version-history":[{"count":4,"href":"https:\/\/gregorgonzalez.com.ve\/blog\/wp-json\/wp\/v2\/posts\/711\/revisions"}],"predecessor-version":[{"id":715,"href":"https:\/\/gregorgonzalez.com.ve\/blog\/wp-json\/wp\/v2\/posts\/711\/revisions\/715"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/gregorgonzalez.com.ve\/blog\/wp-json\/wp\/v2\/media\/660"}],"wp:attachment":[{"href":"https:\/\/gregorgonzalez.com.ve\/blog\/wp-json\/wp\/v2\/media?parent=711"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/gregorgonzalez.com.ve\/blog\/wp-json\/wp\/v2\/categories?post=711"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/gregorgonzalez.com.ve\/blog\/wp-json\/wp\/v2\/tags?post=711"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}