DB2 SQL0255 - 尝试使用JOIN用户ROW_NUMBER时不支持查询功能

时间:2014-09-12 07:30:46

标签: sql-server join pagination db2

我使用[IBM][iSeries Access ODBC Driver][DB2 UDB]版本V5R4来查询链接的服务器。当我试图为现有(和工作)查询添加分页选项时,我收到此错误SQL0255 - Function not supported for query

我尝试添加分页之前正在运行的原始查询是:

select *
from openquery(MyLinkedServer,
'
select 
  ORG.FirstName as "First_Name",
  ORG.LastName  AS "Last_Name",
  PRS.Address as Address

  FROM Table1 AS ORG

     inner join Table2 PRS
       ON ORG.Id = PRS.Id 
'
)

接下来我想添加分页,所以我修改了这样的代码:

select *
from openquery(MyLinkedServer,
'
select 
  ORG.FirstName as "First_Name",
  ORG.LastName  AS "Last_Name",
  PRS.Address as Address

  FROM
  ( SELECT R . * , ROW_NUMBER ( ) OVER ( ) AS ROW_NUM
    FROM Table1 AS R) ORG

     inner join Table2 PRS
       ON ORG.Id = PRS.Id 

 WHERE ROW_NUM BETWEEN 1 AND 10
'
)

这是从标题中给出错误的实际查询。事实上,完整的错误是:

OLE DB provider "..." for linked server "MyLinkedServer" returned message "[IBM][iSeries Access ODBC Driver][DB2 UDB]SQL0255 - Function not supported for query.".

最后一部分。如果我删除了JOIN并且只留下了这样的分页:

select *
from openquery(MyLinkedServer,
'
select 
  ORG.FirstName as "First_Name",
  ORG.LastName  AS "Last_Name",
  PRS.Address as Address

  FROM Table1 AS ORG

     inner join Table2 PRS
       ON ORG.Id = PRS.Id 
'
)

接下来我想添加分页,所以我修改了这样的代码:

select *
from openquery(MyLinkedServer,
'
select 
  ORG.FirstName as "First_Name",
  ORG.LastName  AS "Last_Name"

  FROM
  ( SELECT R . * , ROW_NUMBER ( ) OVER ( ) AS ROW_NUM
    FROM Table1 AS R) ORG

 WHERE ROW_NUM BETWEEN 1 AND 10
'
)

然后查询再次正常工作。因此,我能想到的唯一想法是,在此特定版本的同一查询中使用ROW_NUMBER()JOIN时存在一些问题。

经过大量研究后,我唯一能发现的是每个版本都有我自己的特定版本,我发现了这个:

V5R4 supports OLAP. But there are some restrictions described in "SQL Reference".

An OLAP specification is not allowed if the query specifies:
- lateral correlation,
- a sort sequence,
- an operation that requires CCSID conversion,
- a UTF-8 or UTF-16 argument in a CHARACTER_LENGTH, POSITION, or SUBSTRING scalar function,
- a distributed table,
- a table with a read trigger, or
- a logical file built over multiple physical file members.

主要是获取数据,因此我需要保留JOIN cluase,所以我的问题是如何为此DB2特定版本的此查询添加分页?

1 个答案:

答案 0 :(得分:3)

v5r4已经相当陈旧,大约在2007年,并且不再受IBM支持。

新信息
在v5r4,IBM仍在从原始经典查询引擎(CQE)转向新的SQL查询引擎(SQE)。为了使新的v5r4 OLAP功能起作用,查询必须由SQE处理。

但是,某些事情可能会迫使系统使用CQE。最有可能的。 - 仅存在选择/省略逻辑文件 - 在WHERE子句中使用诸如UPPER()之类的函数。

您可以通过在查询选项文件" QAQQINI"中设置IGNORE_DERIVED_INDEX = * YES来解决第一个问题。最佳做法是将其设置为本地副本,除非您想要影响系统上的每个查询。 在命令行上:

CRTDUPOBJ OBJ(QAQQINI)
          FROMLIB(QSYS)
          OBJTYPE(*FILE)
          TOLIB(MYLIB)
          DATA(*YES)

您可以将QAQQINI设置为在OLEDB驱动程序连接字符串(v5r3 +)上使用。但是看起来你正在使用ODBC。我不确定v5r4,但是7.1 ODBC驱动程序允许你指定"查询选项文件库"

不幸的是,第二个问题没有解决办法...... 如果偶然UPPER()或LOWER()是您正在使用的函数,可能是为了不区分大小写的处理;您可能能够创建不区分大小写的索引并将排序顺序更改为* LANGIDSHR。但是您提到文档指定如果您的查询指定了排序序列,OLAP函数将起作用。

结束新信息

我使用它已经有一段时间了。以下适用于7.1

with tbl as 
  (SELECT 
     ROW_NUMBER ( ) OVER ( ) AS ROW_NUM,
     ORG.FirstName as "First_Name",
     ORG.LastName  AS "Last_Name",
     PRS.Address as Address
   FROM ORG
     INNER JOIN PRS
       ON ORG.ID = PRS.ID
)
SELECT * 
FROM TBL
WHERE ROW_NUM BETWEEN 1 AND 10

请注意,如果未指定排序,您将获得未知的行集。

我建议您在行号

中添加一个窗口顺序子句
with tbl as 
  (SELECT 
     ROW_NUMBER ( ) OVER (ORDER BY ORG.LASTNAME ) AS ROW_NUM,
     ORG.FirstName as "First_Name",
     ORG.LastName  AS "Last_Name",
     PRS.Address as Address
   FROM ORG
     INNER JOIN PRS
       ON ORG.ID = PRS.ID
)
SELECT * 
FROM TBL
WHERE ROW_NUM BETWEEN 1 AND 10

好的,显然上面的内容并不适用于5.4 ...尝试另一层CTE

with tbl as 
  (SELECT 
     ORG.FirstName as "First_Name",
     ORG.LastName  AS "Last_Name",
     PRS.Address as Address
   FROM ORG
     INNER JOIN PRS
       ON ORG.ID = PRS.ID
)
 , tbl2 as 
(SELECT 
   ROW_NUMBER ( ) OVER (ORDER BY "Last_Name" ) AS ROW_NUM,
   , tbl.*
 FROM TBL
)
SELECT * 
FROM TBL2
WHERE ROW_NUM BETWEEN 1 AND 10

其他几种技术......

您可以将结果集加载到临时文件中,然后您就可以使用ROW_NUMBER()。

或者您可以考虑以下事项:
基本上,假设你想要每页10行,你想要第5页(即行41-50)。以下将给你。最初,表现并不是太糟糕。但每页都会变得更糟。您基本上希望用户不会在100次上下页。幸运的是,大多数人都没赢。

select *                              
from (select *                        
      from (select * from mytbl
            order by myfld           
            fetch first 50 rows only  
           ) as t1                    
      order by myfld desc            
      fetch first 10 rows only        
     ) as t2