使用ROWNUM的Oracle数据库问题

时间:2016-05-14 15:38:36

标签: database oracle plsql pagination

尝试在实习期间对新闻测试任务进行分页。无法使其在第7行中出现以下错误:

ORA-00932:不一致的数据类型:预期 - 得到NCLOB

Sql脚本如下。起初我按照评论计数和修改日期排序新闻。然后我只选择行号介于1和2之间的那些:

SELECT NEWS_ID, TITLE, SHORT_TEXT,
    FULL_TEXT, CREATION_DATE, MODIFICATION_DATE
FROM
    ((SELECT APPROPRIATE_NEWS.*, ROWNUM R FROM
        (SELECT *
        FROM ((SELECT NEWS_ID, TITLE, SHORT_TEXT,
                    FULL_TEXT, CREATION_DATE, MODIFICATION_DATE, COMMENTS_COUNT
               FROM NEWS JOIN (SELECT NEWS_ID, COUNT(*) COMMENTS_COUNT
                               FROM COMMENTS
                               GROUP BY NEWS_ID) NEWS_STAT USING(NEWS_ID))
        UNION
        (SELECT NEWS_ID, TITLE, SHORT_TEXT,
                    FULL_TEXT, CREATION_DATE, MODIFICATION_DATE, 0 COMMENTS_COUNT
        FROM NEWS
        WHERE NEWS_ID NOT IN(SELECT NEWS_ID
                             FROM COMMENTS))) ALL_NEWS_STAT
        WHERE EXISTS(SELECT * FROM NEWS_AUTHOR NA
                     WHERE NA.NEWS_ID = ALL_NEWS_STAT.NEWS_ID AND AUTHOR_ID = 1)
            AND NEWS_ID IN (SELECT NEWS_ID
                          FROM NEWS_TAG
                          WHERE TAG_ID IN (1, 2)
                          GROUP BY NEWS_ID
                          HAVING COUNT(*) = 2)
        ORDER BY COMMENTS_COUNT DESC, MODIFICATION_DATE) APPROPRIATE_NEWS) NEWS_PAGE)
WHERE R BETWEEN 1 AND 2;

数据库脚本

CREATE TABLE NEWS
(
    NEWS_ID NUMBER(20) PRIMARY KEY,
    TITLE NVARCHAR2(100) NOT NULL,
    SHORT_TEXT NVARCHAR2(500) NOT NULL,
    FULL_TEXT NCLOB NOT NULL,
    CREATION_DATE TIMESTAMP NOT NULL,
    MODIFICATION_DATE DATE NOT NULL
);

CREATE TABLE TAGS
(
    TAG_ID NUMBER(20) PRIMARY KEY,
    TAG_NAME NVARCHAR2(50) NOT NULL
);

CREATE TABLE NEWS_TAG
(
    NEWS_ID NUMBER(20) NOT NULL,
    TAG_ID NUMBER(20) NOT NULL,
    FOREIGN KEY(NEWS_ID) REFERENCES NEWS(NEWS_ID) ON DELETE CASCADE,
    FOREIGN KEY(TAG_ID) REFERENCES TAGS(TAG_ID) ON DELETE CASCADE
);

CREATE TABLE AUTHORS
(
    AUTHOR_ID NUMBER(20) PRIMARY KEY,
    AUTHOR_NAME NVARCHAR2(30) NOT NULL,
    EXPIRED TIMESTAMP
);

CREATE TABLE NEWS_AUTHOR
(
    NEWS_ID NUMBER(20) NOT NULL,
    AUTHOR_ID NUMBER(20) NOT NULL,
    FOREIGN KEY(NEWS_ID) REFERENCES NEWS(NEWS_ID) ON DELETE CASCADE,
    FOREIGN KEY(AUTHOR_ID) REFERENCES AUTHORS(AUTHOR_ID) ON DELETE CASCADE
);

CREATE TABLE COMMENTS
(
    COMMENT_ID NUMBER(20) PRIMARY KEY,
    NEWS_ID NUMBER(20) NOT NULL,
    COMMENT_TEXT NCLOB NOT NULL,
    CREATION_DATE TIMESTAMP NOT NULL,
    FOREIGN KEY(NEWS_ID) REFERENCES NEWS(NEWS_ID) ON DELETE CASCADE
);

我知道数据库非常糟糕,但我被迫使用它。在mysql用限制关键字

替换rownum东西时,一切正常

提前致谢!

1 个答案:

答案 0 :(得分:2)

在Oracle中,set操作UNION不支持CLOB / NCLOB数据类型。 UNION ALL。无论如何,UNION ALL在您的情况下似乎是正确的操作 - 在UNION的两侧,两个操作数(结果行集)之间不应该重叠。将UNION更改为UNION ALL,它将起作用。祝你好运!

已添加:您可能想知道我是如何得出这个答案的。我不是一个经验丰富的球员,我不知道。为了将来的参考,这里是我如何找到答案。

Big,big plus:您为表提供了CREATE TABLE语句,并提供了完整的查询。这使我能够在我的机器上重新创建整个设置,直到确切的错误消息。

首先我用FULL_TEXT重新创建表NEWS作为CLOB而不是NCLOB;我得到了同样的错误。好消息;它并不特定于NCLOB,这意味着有更多的机会来解决它。 (有关CLOB的信息比关于NCLOB的信息要多得多。)然后我再次更改,这次更改为VARCHAR2,并且查询编译正确。所以有一些关于CLOB的事情导致了这个问题。

然后我说,让我把它缩小到一个更简单的查询。我放弃了UNION和UNION的第二个分支。现在查询编译得非常好。然后我做了相同的但只保留了第二个分支并注释掉了第一个分支。再次,成功。

好的,在这一点上,很明显UNION本身就是问题,而不是其他任何问题。 Google" Oracle union和CLOB"那里有很多关于它的信息。