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.