简体   繁体   English

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

[英]DB2 SQL0255 - Function not supported for query when try to user ROW_NUMBER with JOIN

I am using [IBM][iSeries Access ODBC Driver][DB2 UDB] version V5R4 to query against linked servers. 我正在使用[IBM][iSeries Access ODBC Driver][DB2 UDB]版本V5R4来查询链接服务器。 I was getting this error SQL0255 - Function not supported for query while I was trying to make add a pagination option to an existing (and working) query. 我收到此错误SQL0255 - Function not supported for query尝试向现有(且正在运行)的查询添加分页选项时SQL0255 - Function not supported for querySQL0255 - Function not supported for query

The original query that was working before I tried to add the pagination is : 我尝试添加分页之前正在运行的原始查询是:

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 
'
)

Next I wanted to add pagination so I modified the code like this: 接下来,我想添加分页,所以我修改了如下代码:

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
'
)

which is the actual query that gives me the error from the title. 这是实际的查询,它使我从标题中得到了错误。 In fact the full error is : 实际上,完整的错误是:

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

And the final part. 最后一部分。 If I remove the JOIN and leave only the pagination like so: 如果我删除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 
'
)

Next I wanted to add pagination so I modified the code like this: 接下来,我想添加分页,所以我修改了如下代码:

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
'
)

then the query is working again correctly. 那么查询将再次正常工作。 So the only think that I can think of is that there's some problem in using ROW_NUMBER() together with JOIN in the same query in this particular version. 因此,我唯一能想到的是,在此特定版本的同一查询中,将ROW_NUMBER()JOIN一起使用存在一些问题。

After a lot of research the only thing that I could find out is that each version has it's own specifics on for my particular version I found this: 经过大量研究,我唯一能发现的是每个版本都有其特定于我的特定版本的细节,我发现了这一点:

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.

The main thing is to fetch the data so I need to keep the JOIN cluase so my question is how can I add pagination to this query for this specific version of DB2 ? 最主要的是获取数据,因此我需要保留JOIN线索,所以我的问题是如何针对该特定版本的DB2向该查询添加分页?

v5r4 is quite old, circa 2007, and no longer supported by IBM. v5r4很老,大约在2007年,并且不再受IBM支持。

new info 新资讯
At v5r4, IBM was still in the process of moving towards a new SQL Query Engine (SQE) from the original Classic Query engine (CQE). 在v5r4上,IBM仍在从原始的经典查询引擎(CQE)转向新的SQL查询引擎(SQE)的过程中。 In order for the new v5r4 OLAP functions to work, the query must be processed by the SQE. 为了使新的v5r4 OLAP功能正常工作,查询必须由SQE处理。

However, certain things could force the system to use the CQE. 但是,某些情况可能会迫使系统使用CQE。 Among the most likely. 其中最有可能的。 - mere existence of select/omit logical files - the use of functions such as UPPER() in the WHERE clause.. -仅存在选择/省略逻辑文件-在WHERE子句中使用诸如UPPER()之类的功能。

You can work around the first problem by setting IGNORE_DERIVED_INDEX=*YES in the query options file "QAQQINI". 您可以通过在查询选项文件“ QAQQINI”中设置IGNORE_DERIVED_INDEX = * YES来解决第一个问题。 Best practice would be to set it in a local copy unless you want to effect every query on the system. 最佳做法是将其设置在本地副本中,除非您想在系统上执行每个查询。 On a command line: 在命令行上:

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

You can set the QAQQINI to use on the OLEDB driver connection string (v5r3+). 您可以将QAQQINI设置为在OLEDB驱动程序连接字符串(v5r3 +)上使用。 But it appears you are using ODBC instead. 但是看来您使用的是ODBC。 I'm not sure about v5r4, but the 7.1 ODBC driver allows you to specify "Query options file library" 我不确定v5r4,但是7.1 ODBC驱动程序允许您指定“查询选项文件库”

Unfortunately, there's no work around for the second problem... 不幸的是,第二个问题没有解决方法。
If by chance UPPER() or LOWER() are the functions you are using, perhaps for case-insensitive processing; 如果碰巧您正在使用UPPER()或LOWER(),则可能不区分大小写; you might be able to create a case-insensitive index and change your sort sequence to *LANGIDSHR. 您也许可以创建不区分大小写的索引,并将排序顺序更改为* LANGIDSHR。 But you mention that the docs specified that the OLAP functions would work if your query specified a sort sequence. 但是您提到文档指定如果查询指定排序顺序,则OLAP函数将起作用。

end new info 结束新信息

Been a while since I used it. 自从我使用了一段时间以来。 The following works on 7.1 以下工作于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

Note that without ordering specified, you'll get and unknown set of rows. 请注意,不指定顺序,您将获得未知的行集。

I'd suggest you add an window order clause to the row number 我建议您在行号中添加窗口顺序子句

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

Ok, so apparently the above doesn't work on 5.4...Try another layer of CTE 好的,因此上述内容显然不适用于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

A couple of other techniques... 其他一些技巧...

You could load the results set into a temporary file and then you'd be able to use ROW_NUMBER(). 您可以将结果集加载到一个临时文件中,然后就可以使用ROW_NUMBER()。

Or you can consider the following: 或者,您可以考虑以下几点:
Basically, lets say you want 10 rows per page and you want page 5 (ie rows 41-50). 基本上,假设您要每页10行,而要第5页(即第41-50行)。 The below will give you that. 下面将为您提供。 Performance isn't too bad, initially. 最初,性能还不错。 But it does get worse with each page. 但是每页的确会变得更糟。 You're basically hoping the users don't hit page down 100s of times. 基本上,您希望用户不会将页面降级100次。 Luckily most won't. 幸运的是大多数不会。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM