Glorp和Oracle:限制查询结果

时间:2012-09-06 07:50:03

标签: oracle limit smalltalk

我在VisualWorks中使用Glorp并使用Oracle数据库。因为Oracle不知道LIMIT命令,所以在查询后返回 all ,WHERE子句的计算结果为true的myTable记录。

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

如何在此Glorp查询中加入ROWNUM?

//编辑生成的SQL:

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

3 个答案:

答案 0 :(得分:1)

即使您可以将ROWNUM添加到此查询中,您仍可能无法获得所需的结果。问题是WHERE子句在ORDER BY之前应用 - 因此,通过限制返回的前10行,您将获得这10行,然后它们将被排序。这是一个例子:

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;

查询返回

12
13
14
15
16
17
18
19
20

在我的系统上。我怀疑你想要的是等同于

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

返回1到9。

我不知道您是否或如何在Glorp中嵌套查询。 (FWIW - 我知道并喜欢Smalltalk,但我因为这样的原因而讨厌持久性框架)。 YMMV,显然。

(顺便说一句 - 考虑一下这一点,您可以修改Glorp.SimpleQuery上的#limit:方法,将ROWNUM的比较注入到WHERE子句中 - 但正如我上面所述,结果可能仍然没有这是一个实施,留给感兴趣的读者: - )。

分享并享受。

答案 1 :(得分:1)

首先,我建议使用不同的语法    Glorp.Query读取:... 你真的不想在前面指定SimpleQuery类,并且读取:比returnsManyOf短得多:并且完成同样的事情。

我目前没有在我面前的软件,但我很确定在Oracle上的限制:命令应转换为使用rownum。您看到这会生成什么SQL?

答案 2 :(得分:1)

On Smalltalk.Glorp.DatabasePlatform我添加了两个空方法#printPreLimitWrapper:on:和#printPostLimitWrapper:on:我在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我添加了:

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.

在Smalltalk.Glorp.QuerySelectCommand上,我改变了以下方法:

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.