简体   繁体   中英

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. 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.

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:

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.

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 ?

v5r4 is quite old, circa 2007, and no longer supported by 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). In order for the new v5r4 OLAP functions to work, the query must be processed by the SQE.

However, certain things could force the system to use the CQE. Among the most likely. - mere existence of select/omit logical files - the use of functions such as UPPER() in the WHERE clause..

You can work around the first problem by setting IGNORE_DERIVED_INDEX=*YES in the query options file "QAQQINI". 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+). But it appears you are using ODBC instead. I'm not sure about v5r4, but the 7.1 ODBC driver allows you to specify "Query options file library"

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; you might be able to create a case-insensitive index and change your sort sequence to *LANGIDSHR. But you mention that the docs specified that the OLAP functions would work if your query specified a sort sequence.

end new info

Been a while since I used it. The following works on 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

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().

Or you can consider the following:
Basically, lets say you want 10 rows per page and you want page 5 (ie rows 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. 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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