6

我在 VisualWorks 和 Oracle 数据库中使用 Glorp。由于 Oracle 不知道 LIMIT 命令,因此以下查询将返回myTable 中 WHERE 子句计算结果为 true 的所有记录。

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

我将如何将 ROWNUM 合并到此 Glorp 查询中?

//编辑生成的SQL:

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

3 回答 3

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 子句 - 但正如我上面所说,结果可能仍然不是预期的. 一个实现留给感兴趣的读者作为练习:-)。

分享和享受。

于 2012-09-06T11:56:21.417 回答
1

首先,我建议使用不同的语法,如 Glorp.Query 读取:...您真的不想预先指定 SimpleQuery 类,并且读取:比 returnManyOf: 短得多,并且完成相同的事情。

目前我面前没有软件,但我很确定在 Oracle 上 limit: 命令应该转换为使用 rownum。你看到这个生成了什么 SQL?

于 2012-09-06T20:04:15.343 回答
1

在 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: ' '.

在 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.
于 2012-11-22T16:20:19.990 回答