2012-09-06 14 views
6

Estoy usando Glorp en VisualWorks y con una base de datos Oracle. Como Oracle no conoce el comando LIMIT, la consulta siguiente devuelve todos los los registros de myTable para los cuales la cláusula WHERE se evalúa como verdadera.Glorp y Oracle: limitar el resultado de la consulta

q := Glorp.SimpleQuery 
     returningManyOf: MyTable 
     where: [:each | each name = 'test'] 
     limit: 10. 
q orderBy: [:each | each id descending]. 
results:= aGlorpSession execute: q. 

¿Cómo podría incorporar ROWNUM en esta consulta de Glorp?

// editar SQL generado:

SELECT t1.id, t1.name 
FROM MyTable t1 
WHERE (t1.name= ?) ORDER BY t1.id DESC 
+0

La forma habitual de limitar el número de filas en Oracle es seleccionar * de (seleccionar ... ordenar por ...) donde rownum <10. ¿Puede modificar la consulta que genera Glorp? –

+0

Sí, debería haber mencionado que sé cómo hacerlo en Oracle. Simplemente no sé cómo hacerlo en Glorp. – Cantillon

+0

¿Glorp usa cursores en el fondo cuando trabaja con Oracle, o realmente extrae todos los resultados en la memoria? –

Respuesta

1

En Smalltalk.Glorp.DatabasePlatform I añadieron dos métodos vacíos #printPreLimitWrapper: en: y #printPostLimitWrapper: en: que puedo reemplazar en Smalltalk.Glorp.OraclePlatform:

printPreLimitWrapper: anInteger on: aCommand 
    aCommand nextPutAll: ' SELECT * FROM (' 

printPostLimitWrapper: anInteger on: aCommand 

    aCommand nextPutAll: ') WHERE ROWNUM <= '. 
    anInteger printOn: aCommand. 
    aCommand nextPutAll: ' '. 

En Smalltalk.Glorp.SimpleQuery I añadido:

printPostLimitWrapperOn: aCommand 
    self hasLimit ifFalse: [^self]. 
    self platform printPostLimitWrapper: self limit on: aCommand. 

printPreLimitWrapperOn: aCommand 
    self hasLimit ifFalse: [^self]. 
    self platform printPreLimitWrapper: self limit on: aCommand. 

Y en Smalltalk.Glorp.QuerySelectCommand alteré el siguiente método:

printSQL 
    query printPreLimitWrapperOn: self. 
    stream nextPutAll: 'SELECT '. 
    query printSelectFieldsOn: self. 
    self findBoundExpressions. 
    query printTablesOn: self. 
    query printWhereClauseOn: self. 
    query printJoinsOn: self. 
    query printOrderingOn: self. 
    query printGroupByOn: self. 
    query printPostLimitOn: self. 
    query printOffsetOn: self. 
    query printPostLimitWrapperOn: self. 
1

Incluso si puede añadir a esta consulta ROWNUM todavía no puede obtener los resultados que desea. El problema es que la cláusula WHERE se aplica antes que ORDER BY; por lo tanto, al limitarse a las primeras 10 filas devueltas, obtendrás esas diez filas y luego se ordenarán. He aquí un ejemplo:

CREATE TABLE order_test(seq_num NUMBER); 

INSERT INTO order_test(seq_num) VALUES(20); 
INSERT INTO order_test(seq_num) VALUES(19); 
INSERT INTO order_test(seq_num) VALUES(18); 
INSERT INTO order_test(seq_num) VALUES(17); 
INSERT INTO order_test(seq_num) VALUES(16); 
INSERT INTO order_test(seq_num) VALUES(15); 
INSERT INTO order_test(seq_num) VALUES(14); 
INSERT INTO order_test(seq_num) VALUES(13); 
INSERT INTO order_test(seq_num) VALUES(12); 
INSERT INTO order_test(seq_num) VALUES(11); 
INSERT INTO order_test(seq_num) VALUES(10); 
INSERT INTO order_test(seq_num) VALUES(09); 
INSERT INTO order_test(seq_num) VALUES(08); 
INSERT INTO order_test(seq_num) VALUES(07); 
INSERT INTO order_test(seq_num) VALUES(06); 
INSERT INTO order_test(seq_num) VALUES(05); 
INSERT INTO order_test(seq_num) VALUES(04); 
INSERT INTO order_test(seq_num) VALUES(03); 
INSERT INTO order_test(seq_num) VALUES(02); 
INSERT INTO order_test(seq_num) VALUES(01); 

SELECT * FROM order_test WHERE ROWNUM < 10 ORDER BY seq_num; 

la consulta devuelve

12 
13 
14 
15 
16 
17 
18 
19 
20 

en mi sistema. Sospecho que lo que quiere es el equivalente de

SELECT * 
    FROM (SELECT * FROM ORDER_TEST ORDER BY SEQ_NUM) 
    WHERE ROWNUM < 10 

que devuelve 1 a 9.

No sé si es o cómo se puede anidar en consultas Glorp. (FWIW - Conozco y amo Smalltalk, pero detesto los marcos de persistencia por razones como esta). YMMV, obviamente.

(Por cierto, pensando en esto por un minuto, es posible que pueda modificar el método #limit: Glorp.SimpleQuery para insertar una comparación con ROWNUM en la cláusula WHERE, pero como dije anteriormente, los resultados aún pueden no ser lo que se pretende. Una implementación se deja como un ejercicio para el lector interesado :-).

Comparte y disfruta.

1

En primer lugar, me gustaría sugerir sintaxis diferente leer Glorp.Query: ... Usted realmente no desea especificar la clase SimpleQuery en la delantera, y leer: es mucho más corto que returningManyOf: y lleva a cabo la la misma cosa.

No tengo el software en frente de mí en este momento, pero estoy bastante seguro de que en Oracle el límite: el comando debería traducirse en el uso de rownum. ¿Qué SQL estás viendo esto generar?

+0

OK, usaré read :. Escribir el límite se delega a la plataforma de la base de datos. La implementación predeterminada está vacía y solo se implementa para PostgreSQLPlatform y SQLServerPlatform. Agregué el SQL generado a la pregunta original. – Cantillon

Cuestiones relacionadas