DB2 LIKE operator character range - db2

I'm attempting to construct a LIKE operator in my query on DB2 that is checking if a varchar is just two digits. I've looked online and it seems like DB2 does not support a character range i.e. [0-9]. I've tried LIKE '[0-9][0-9]' and I didn't get an error from DB2, but no rows showed up in my result set from that query when I can see rows that exactly match this through looking at a SELECT * of the same table.
Is there anyway I can replicate this in DB2 if it is indeed true? Is my syntax for the LIKE wrong? Thanks in advance.

The TRANSLATE function is more appropriate for validating an expression that contains a limited number of valid values.
WHERE TRANSLATE( yourExpressionOrColumn, '000000000', '123456789') = '00'

Found it. No you cannot and there are no symbols that can represent an OR in LIKE.

Related

DB2 query results in Hex format -- Need Character/String

I have a query that I can run on a DB2 table using my python SQL tester, and it returns the string values I'm looking for.
However, when I run it directly on my database it returns a hex value. Any help in getting the results as a character string would be greatly appreciated!
Here is the field definition:
ORCTL CCDATA 243 A 14 256 Order Control File Data
My query on the iSeries is:
select ccdata from ORCTL where ccctlk = 'BUYRAK'
Using your query, you can cast a string with another CCSID, eg :
select cast(ccdata as char(14) CCSID 37) from ORCTL where ccctlk = 'BUYRAK'
My guess is that it isn't returning hex...
Rather it's returning EBCDIC.
Your column is probably tagged with CCSID 65535, which tells the system not to translate it.
The right way to fix this issue, is to make sure the column is tagged with the appropriate CCSID; for example, 37 for US English.
The alternative, is to look for a "force translate" option in the settings of driver you're using.

replacing characters in a CLOB column (db2)

I have a CLOB(2000000) field in a db2 (v10) database, and I would like to run a simple UPDATE query on it to replace each occurances of "foo" to "baaz".
Since the contents of the field is more then 32k, I get the following error:
"{some char data from field}" is too long.. SQLCODE=-433, SQLSTATE=22001
How can I replace the values?
UPDATE:
The query was the following (changed UPDATE into SELECT for easier testing):
SELECT REPLACE(my_clob_column, 'foo', 'baaz') FROM my_table WHERE id = 10726
UPDATE 2
As mustaccio pointed out, REPLACE does not work on CLOB fields (or at least not without doing a cast to VARCHAR on the data entered - which in my case is not possible since the size of the data is more than 32k) - the question is about finding an alternative way to acchive the REPLACE functionallity for CLOB fields.
Thanks,
krisy
Finally, since I have found no way to this by an SQL query, I ended up exporting the table, editing its lob content in Notepad++, and importing the table back again.
Not sure if this applies to your case: There are 2 different REPLACE functions offered by DB2, SYSIBM.REPLACE and SYSFUN.REPLACE. The version of REPLACE in SYSFUN accepts CLOBs and supports values up to 1 MByte. In case your values are longer than you would need to write your own (SQL-based?) function.
BTW: You can check function resolution by executing "values(current path)"

What is the best way to decipher a DB2 -302 error from Java?

I am getting this error running an insert query for a single record:
DB2 SQL Error: SQLCODE=-302, SQLSTATE=22001, SQLERRMC=null,
DRIVER=3.62.56
Exception: org.springframework.dao.DataIntegrityViolationException
I looked this up on IBM's help site, but there being no parameter index, I am stuck. The SQL state also seems to specify it is other than a value being too big.
The format of the query is INSERT INTO [[TABLE_NAME]] VALUES (?,?,?,...) using Spring's JdbcTemplate.update(String sql, Object... params).
This being for work, I cannot post schema nor query. I am looking for general advice into debugging this issue. I already know using Arrays.toString(Object[]) does not print out in SQL format.
To find the explanation for SQLCODE -302 in the manual you need to search for SQL0302N (the general rule for DB2 SQLCODE values is this: "SQL" plus four digits, padded if necessary with zeros on the left, plus "N" for "negative" because -302 is a negative number).
If you have the DB2 command line processor installed, you can also use it to look up error codes:
db2 ? sql302
which would produce something like this:
SQL0302N The value of a host variable in the EXECUTE or OPEN
statement
is out of range for its corresponding use.
Explanation:
The value of an input host variable was found to be out of range for
its use in the SELECT, VALUES, or prepared statement.
In other words, one of the bind variables in your INSERT is too large for the target column. You'll need to compare the table column definitions with the actual values you're trying to insert.
In addition to mustaccio's answer you can also get the info from sql with SYSPROC.SQLERRM. Example:
values SYSPROC.SQLERRM ('SQL302', '', '', 'en_US', 0)
SQL0302N The value of a host variable in the EXECUTE or OPEN statement
is out of range for its corresponding use.
Explanation:
...

SQL Server's isNumeric() equivalent in amazon redshift

I'm using amazon redshift as my data warehouse
I have a field (field1)of type string. Some of the strings start with four numbers and others with letters:
'test alpha'
'1382 test beta'
I want to filter out rows where the string does not start with four numbers
Looking at the redshift documentation, I don't believe isnumber or isnumeric are functions. It seems that the 'like' function is the best possibility.
I tried
where left(field1, 4) like '[0-9][0-9][0-9][0-9]'
this did not work and from the link below seems like redshift may not support that:
https://forums.aws.amazon.com/message.jspa?messageID=439850
is there an error in the 'where' clause? if not and that clause isn't supported in redshift, is there a way to filter? I was thinking of using cast
cast(left(field1,4) as integer)
and then passing over the row if it generated an error, but not sure how to do this in amazon redshift. or is there some other proxy for the isnumeric filter.
thanks
Try something like:
where field1 ~ '^[0-9]{4}'
It will match any string, that starts with 4 digits.
Although long time has passed since this question was asked I have not found an adequate response. So I feel obliged to share my solution which works fine on my Redshift cluster today (March 2016).
The UDF function is:
create or replace function isnumeric (aval VARCHAR(20000))
returns bool
IMMUTABLE
as $$
try:
x = int(aval);
except:
return (1==2);
else:
return (1==1);
$$ language plpythonu;
Usage would be:
select isnumeric(mycolumn), * from mytable
where isnumeric(mycolumn)=false
It looks like the code you are looking for the is the similar to function:
where left(field,4) similar to '[0-9]{4}'
Redshift doc
It seems that redshift doesn't support any of the following:
where left(field1,4) like '[0-9][0-9][0-9][0-9]'
where left(field1,4) ~ '^[0-9]{4}'
where left(field1,4) like '^[0-9]{4}'
what does seem to work is:
where left(field1,4) between 0 and 9999
this returns all rows that start with four numeric characters.
it seems that even though field1 is type string, the 'between' function interprets left(field1,4) as a single integer when the string characters are numeric (and does not give an error when they are not numeric). I'll follow up if I find a problem. For instance I don't deal with anything less than 1000, so I assume, but am not sure, that 0001 is interpreted as 1.
Per Amazon, the posix style ~regex style expressions are slow...
https://docs.aws.amazon.com/redshift/latest/dg/pattern-matching-conditions.html
Using their own REGEXP_* functions seems to be faster.
https://docs.aws.amazon.com/redshift/latest/dg/String_functions_header.html
For checking just a true/false for integers I've been using the following with success.
REGEXP_COUNT(my_field_to_check, '^[0-9]+$') > 0
this returns 1 if only numeric, 0 if anything else
where regexp_instr(field1,'^[0-9]{4}') = 0
will remove rows starting with 4 digits (the above regexp_instr will return 1 for the rows with field1 starting with 4 digits)
We have tried the following and worked for most of our scenarios:
columnn ~ '^[-]{0,1}[0-9]{1,}[.]{0,1}[0-9]{0,}$'
This will positive, negative, integer and float numbers.
redshift should support similar to.
WHERE field1 SIMILAR TO '[0-9]{4}%'
This reads as where field1 starts with 4 characters in the range of 0-9, then anything else.

Finding first alphabetic character in a DB2 database field

I'm doing a bit of work which requires me to truncate DB2 character-based fields. Essentially, I need to discard all text which is found at or after the first alphabetic character.
e.g.
102048994BLAHBLAHBLAH
becomes:-
102048994
In SQL Server, this would be a doddle - PATINDEX would swoop in and save the day. Much celebration would ensue.
My problem is that I need to do this in DB2. Worse, the result needs to be used in a join query, also in DB2. I can't find an easy way to do this. Is there a PATINDEX equivalent in DB2?
Is there another way to solve this problem?
If need be, I'll hardcode 26 chained LOCATE functions to get my result, but if there is a better way, I am all ears.
SELECT TRANSLATE(lower(column), ' ', 'abcdefghijklmnopqrstuvwxyz')
FROM table
write a small UDF (user defined function) in C or JAVA, that does your task.
Peter