2012-09-06 13 views
6

Sto utilizzando Glorp in VisualWorks e con un database Oracle. Poiché Oracle non conosce il comando LIMIT, dopo la query restituisce tutti i i record di myTable per i quali la clausola WHERE restituisce true.Glorp e Oracle: limitazione del risultato della query

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

Come dovrei andare a incorporare ROWNUM in questa domanda di Glorp?

// modificare SQL generato:

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

Il metodo normale per limitare il numero di righe in Oracle è selezionare * da (selezionare ... ordina per ...) dove rownum <10. È possibile modificare la query generata da Glorp? –

+0

Sì, avrei dovuto dire che so come farlo in Oracle. Solo che non so come farlo in Glorp. – Cantillon

+0

Glorp utilizza i cursori in background quando si lavora con Oracle o in realtà recupera tutti i risultati in memoria? –

risposta

1

Su Smalltalk.Glorp.DatabasePlatform ho aggiunto due metodi vuoti #printPreLimitWrapper: su: e #printPostLimitWrapper: su: che sovrascrivo in Smalltalk.Glorp.OraclePlatform:

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

printPostLimitWrapper: anInteger on: aCommand 

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

On Smalltalk.Glorp.SimpleQuery I aggiunto:

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. 

E su Smalltalk.Glorp.QuerySelectCommand ho alterato il seguente metodo:

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

Anche se si può aggiungere ROWNUM a questa domanda si può ancora non ottenere i risultati desiderati. Il problema è che la clausola WHERE viene applicata prima di ORDER BY, quindi, limitando le prime 10 righe restituite, otterrai quelle dieci righe e quindi verranno ordinate. Ecco un esempio:

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 query restituisce

12 
13 
14 
15 
16 
17 
18 
19 
20 

sul mio sistema. Ho il sospetto che ciò che si vuole è l'equivalente di

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

che ritorna da 1 a 9.

Non so se e come è possibile query nidificare in Glorp. (FWIW - Conosco e amo Smalltalk, ma detesto le strutture di persistenza per ragioni come questa). YMMV, ovviamente.

(BTW - pensateci per un minuto, potreste essere in grado di modificare il metodo #limit: su Glorp.SimpleQuery per iniettare un confronto con ROWNUM nella clausola WHERE - ma come ho detto sopra, i risultati potrebbero ancora non è ciò che è inteso: un'implementazione è lasciata come esercizio al lettore interessato :-).

Condividi e divertiti.

1

Prima di tutto, io suggerirei di sintassi diversa come letto Glorp.Query: ... Non si vuole veramente per specificare la classe SimpleQuery in attacco, e leggere: è molto più breve di returningManyOf: e compie il stessa cosa.

Non ho il software di fronte a me al momento, ma sono abbastanza sicuro che su Oracle il limite: il comando dovrebbe tradursi nell'utilizzo di Rownum. Che cosa stai vedendo generare questo SQL?

+0

OK, userò leggere :. La scrittura del limite è delegata alla piattaforma del database. L'implementazione predefinita è vuota e viene implementata solo per PostgreSQLPlatform e SQLServerPlatform. Ho aggiunto l'SQL generato alla domanda originale. – Cantillon

Problemi correlati