![]() |
Problema con select first en Firebird
Hola amigos,
Necesito hacer estadísticas de cierto número de registros, viendo otros hilos encontré que con la instrucción FIRST puedo obtener la cantidad que deseo. Todo bien si la cantidad la coloco fija, es decir
pero si le agrego un parámetro de entrada (E_Limite) me muestra el siguiente error: Cita:
Alguien sabe porque no me acepta esta estructura? Muchas gracias Salud OS. Edito: oops, parezco nuevo, Uso Firebird. :D |
No te estoy dando una explicación a tu pregunta, pero te propongo otro método para que funcione. :o
La verdad es que no puedo concluir si el valor de First se puede o no pasar como parámetro. |
Por cierto, ahora que me doy cuenta leyendo de nuevo tu post anterior ... el error que indicas es
Código:
Invalid token. Estás creando la sentencia SQL de manera dinámica en tiempo de ejecución ?? Si es así, te has asegurado de que estás borrando correctamente la anterior ?? ;) |
Muchas gracias gluglu, precisamente eso estaba pensado en este preciso momento, pero estoy con el tema de hacer todas mis consultas con procedimientos almacenados, una mas de mis aferraciones:D:D:D
Edito: Si, perdon el procedimiento almacenado es este
Trato de evitar el error de que pueda pasar un dato 0, que leí en algún lado produce error. Salud OS. |
Puedes intentar usar el Execute Statement, nunca lo he usado con parámetros de fechas pero me supongo que asi debería funcionar:
Pruebalo y si te funciona, espero te sirva :). |
Acabo de darme cuenta que en una base de datos que tengo a mano, ya había hecho lo mismo con parámetros de fechas y toda la cosa, analizándolo recordé que la cuestión debe funcionarte asi:
|
Perfecto, me funcionó de maravilla, solo cambié el AS CHAR(1) del E_Limite por AS INTEGER, porque pueden ser mas de 1 dígito y no sea que se les ocurra solicitar, 9, 30, 120, 1000, etc...
Como lo diria nuestro buen amigo Carlos Alberto, muchas gracias maestro.:) Salud OS. |
Final Feliz¡¡¡ Que bueno :)
|
¿Cuál final feliz? :confused:
Tenía planeado hacer varios procedimientos con esa característica en Firebird 1.5, pero según veo ahora tendré que recurrir a la instrucción Execute Statement para que sea posible. :eek: ¿No lo hace eso un poco más lento? Hablo de unos 20 mil registros, por ejemplo. Por otro lado, ¿cómo es que sí funciona una sentencia como la siguiente en el SQL Editor de IB Expert? Select First :C * From Empleados Me hace suponer que SQL Editor también utiliza Execute Statement, o bien, transforma los parámetros armando una nueva sentencia "plana" (formateo) antes de ejecutarla. Pero no hay como estar seguros, ¿alguien puede mirar qué hace internamente el SQL Editor de IB Expert? Por favor. Un abrazo sacado de onda. Al González. :) |
Hola Alberto, pues exactamente yo tengo alrrededor de 20,000 registros en esta prueba que consta de solo dos dias de información, estos reportes los sacarán por mes, así que por simple operacion matemática estamos hablando de alrrededor de los 300,000 registros al mes.
Y tienes razón, en el Editor SQL de IBExpert funciona sin problema, el tiempo a mi parecer es el mismo, a lo más 1 segundo en realizar la consulta, tanto en el SP como en el Editor SQL. Lo que yo pretendo es que quien trabaje es la base de datos y no el lado de cliente, por eso estoy utilizando SP's. En este aspecto, me gustaría que ustedes los que llevan tiempo con Firebird me comentaran si esto que "soñe" es lo más idóneo o mejor sería hacerlo a través de Queries en los programas como lo hacia con Paradox:D. Salud OS. |
¡Hola a todos!
Cita:
Todas las sentencias Select que llevan uniones horizontales (Join), uniones verticales (Union), columnas calculadas (Case, concatenaciones, operaciones matemáticas, etc.), agrupación (Group By), subconsultas (Select dentro del Select) o más de una condición en su cláusula Where, son colocadas dentro de vistas o procedimientos almacenados (en estos últimos cuando hay necesidad de parametrizar la consulta). Es decir, los únicos Selects directos fuera de la capa de la base de datos son aquellas sentencias simples tipo "Select Campo1, Campo2, Campo3 From Tabla Where Campo4 = Valor Oder By Campo2" (normalmente son típicos "Select * From Tabla Order By Campo"). Bajo el entendido de que el programador operativo (capa cliente) o de lógica de negocios (capa intermedia) no necesariamente cuenta con el conocimiento de un especialista en bases de datos. Es el AD (administrador de datos o "DBA") quien se encarga de la programación SQL de mediana y alta complejidad a nivel de la base de datos. Además, con esto se consigue centralizar muchos procesos que no son simples, evitando que desde la base de datos crezca una enredadera de código SQL hacia las demás capas. Con respecto al uso de Execute Statement, me inquieta un poco que tengo sentencias Select de varias decenas de líneas que ahora tendré que armar como una cadena de caracteres concatenada dentro de los procedimientos. Espero no toparme con un límite de 1024 caracteres o una cosa rara de esas que a veces pasan porque un programador de un país lejano decidió ahorrar unos cuantos bits. Hay que pensar positivo. :rolleyes: Un abrazo selecto. Al González. :) |
Cita:
|
Ahora, cuando trato de hacer esto, en un procedimiento almacenado:
Desde el IbExpert, este me advierte que el procedimiento es mas grande de 64K y que eso podría causarme problemas de compilación y/o de ejecución posteriormente. |
Final feliz alternativo
¡Hola de nuevo!
Ya me había ido a dormir, pero de pronto, entre el barullo de mis últimos pensamientos del día, reflexioné: ---------------------------------------------------- ¿Por qué será que no se permite parametrizar un First? Ah, pero podría "armar" el First n en el Select que llama al procedimiento (Select First n * From Procedimiento...). Después de todo, un procedimiento almacenado que devuelve un cursor hace un Suspend por cada fila, y si desde afuera le digo "First 10", pues sólo deberá traerme 10 y suspender definitivamente la obtención de las filas restantes. Quizá por eso los creadores de InterBase / Firebird no permiten usar una variable o parámetro para indicar la cantidad en el interior de un procedimiento. Pareciera una forma sutil de decirnos, "¿pa' qué quieres el First parametrizado aquí? Tú pide desde afuera la cantidad que requieras." Aunque esto no suena muy convincente, quizá haya otra razón. Ah, ¿pero qué pasaría si a ese Select exterior le añado una cláusula Order By? Temo que se va a traer todo el cursorote y ya luego tomará los First n del orden indicado, discriminando una gran cantidad de filas que ya se trajo. Eso lo volvería muy lento... ---------------------------------------------------- Entonces recordé que tenía una barra de chocolate con almendras en el congelador y aquello fue la gota que derramó la tentación. Me levanté a la media noche para compartir estas reflexiones con ustedes y de paso hacer algunas pruebas adicionales con IB Expert y Delphi. Los resultados de esas pruebas fueron que: 1. Efectivamente, se puede utilizar First en el Select exterior para evitar el empleo de Execute Statement dentro del procedimiento. 2. Ese First sí puede tener un parámetro. 3. Por alguna razón no se permiten cláusulas First sin un valor literal dentro de procedimientos almacenados y disparadores. 4. Como era de esperarse, una cláusula Order By en el Select que llama al procedimiento hace que se obtengan todas las filas posibles de éste antes de aplicar el First de dicha sentencia Select, lo cual no es óptimo. Conclusión para mi caso: Usaré First parametrizados en los Selects que llaman a los procedimientos. Dentro de éstos aplicaré un Order By acorde a ese First de afuera. En esos Selects exteriores evitaré el uso de Order By; con la ventaja de que, al estar utilizando CDSs (client data sets) conectados a los queries, puedo reordenar las filas en memoria según convenga para cada caso. Esta solución podría ser útil en otros casos; todo depende de la cantidad de registros, los componentes utilizados y de qué tanto queramos variar el orden del cursor. Cita:
Un abrazo chocolatoso. Al González. :) |
Ejemplos de las pruebas
Saludos.
Al González podrias si te es posible subir los select's de pruebas que utilizaste? . Gracias de antemano. |
Bueno, el hecho de usar el FIRST, solo lo considero para obtener estadísticas, no para recuperar filas de las tablas, mi caso es por ejemplo, quiero saber los N números más marcados mas no las primeras N filas, eso no me hace sentido y lo haría con validaciones WHERE, HAVING.
Salud OS. |
Tu sentencia esta bien solo le falta unos parentesis
donde: PAGE_NF Numero de registros por pagina PAGE_NRO el numero de pagina este es el codigo q uso, para darte un ejemplo
Agrego: probado en firebird 2.0 y 2.1 beta |
Vaya, Vaya, Vaya¡¡¡ :)
|
:eek::eek::eek:, Funcionó perfectamente.
Muchas gracias ariefez, pues nada, cada día se aprende algo nuevo. Así quedo finalmente mi SP
Solo hago notar que la funcion SUM() requiere de un tipo de dato Numeric, intentaba asignarlo como Integer y me daba un error de casting. Salud OS. |
Final feliz pa' todos
¡Hola a todos!
Cita:
Select que detiene definitivamente el For Select del procedimiento spParte tras obtener las primeras 10 filas construidas por el procedimiento:
Select que, por tener Order By, espera a que se realice todo el For Select del procedimiento spParte, para luego devolver solo 10 de las filas que construyó el procedimiento:
Cita:
Cita:
Cita:
Gracias por el tip Ariefez, creo que has dado con la mejor solución para los casos planteados. Y además he aprendido aquello del Order By en llamadas a procedimientos. Un primer abrazo. Al González. :) |
La franja horaria es GMT +2. Ahora son las 21:38:55. |
Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi