I found a funny issue with DB2 v9.7 and the SQL LIKE
operator. Check this out:
-- this works and returns one record
select 1
from SYSIBM.DUAL
where 'abc' like concat('a', 'bc')
-- this doesn't work
select 1
from SYSIBM.DUAL
where 'abc' like concat(cast('a' as varchar(2001)), cast('bc' as varchar(2000)))
-- It causes this error (from JDBC):
-- No authorized routine named "LIKE" of type "FUNCTION" having compatible
-- arguments was found.. SQLCODE=-440, SQLSTATE=42884, DRIVER=4.7.85
I've played around with the lengths and it seems that the problem appears as soon as lengths add up to be larger than 4000
. If I "truncate" the whole concatenated string back to length 4000
, the problem disappears:
select 1
from SYSIBM.DUAL
where 'abc' like
cast(concat(cast('a' as varchar(2001)), cast('bc' as varchar(2000)))
as varchar(4000))
Interestingly, it really seems to be related to the CONCAT
function. The following works as well:
select 1
from SYSIBM.DUAL
where 'abc' like cast('abc' as varchar(32672))
Has anyone experienced such an issue? Is it a bug in DB2? Or some undocumented restriction? N.B: I found a similar issue here:
https://www-304.ibm.com/support/docview.wss?uid=swg1PM18687
Given that another IBM product creates a workaround for this issue in 2010, I guess it's not really a bug, otherwise it would have been fixed in the mean time?
Could this possibly be related to the rowsize for the tablespace your table exists in?
I think if a a DB2 varchar extends beyond the rowsize for the table you're querying, it must be declared as a LONG VARCHAR, is stored external to the rest of the table data and referenced by a pointer, and LIKE queries are no longer possible. But I haven't used DB2 for some years. :)
The real Aha! is here.
Firstly, According to the rules for the concatenation operator result type, concatenating two VARCHARs with the combined length of 4000 bytes or less produces a VARCHAR of that combined length, e.g.
concat(varchar(2000), varchar(2000)) = varchar(4000)
. Concatenating two VARCHARs with the combined length of 4001 bytes or more produces a LONG VARCHAR with the length of 32 700. Though the LONG VARCHAR type is deprecated, I guess the concatenation behaviour still uses the legacy logic.Secondly, the LIKE predicate expects the pattern expression to be a VARCHAR with the maximum length of 32672 bytes.
Subsequently, when you unknowingly attempt to use a LONG VARCHAR as the pattern expression, you get an error. It's not so much about the length of the operand as it is about its data type. The following should work:
Edit: Aha!
While searching the Information Center for another bit of knowledge on
VARCHAR
s, I discovered this nifty tidbit of information on the character data type page:So, it looks like it's a known "feature" of DB2.
I did some additional testing, and it looks like the "workaround" mentioned above works for DB2 on Linux/Unix/Windows, but does not work for DB2 on the Mainframe.
Going off of the SQL and XML Limits page from the Information center, if you look at Table 7 (third row), it says that the maximum length of a row including all overhead for a table space with a 4k page size is 4005 bytes.
My guess is that
SYSIBM.DUAL
is in a 4k pagesize table space, which is causing your error. You can checkSYSCAT.TABLESPACES
, which might confirm or deny this suspicion.You can get the information with a query like so: