Removing leading zeros from varchar sql developer - sql

How would I remove the leading zeros from a number which is in the form of varchar.
I have tried the following:
Option 1:
insert into example_table (columnName)
(SELECT
SUBSTR(columnName2, InStr('%[^0 ]%', columnName2 + ' '), 10)
from columnName2);
With this, the error I get is
SQL Error: ORA-01722: invalid number
ORA-02063: preceding line from xxxx
01722. 00000 - "invalid number"
Option 2:
insert into example_table (columnName)
(SELECT
SUBSTR(columnName2, InStr('%[^0 ]%', columnName2 + ' '),
LEN(columnName2))
from columnName2);
This time I get
Error at Command Line:23 Column:87
Error report:
SQL Error: ORA-00904: "LEN": invalid identifier
Option 3:
SUBSTRING
(columnName2, PATINDEX('%[^0 ]%', columnName2 + ' '), 10));
Similar to above, I get
Error at Command Line:23 Column:41
Error report:
SQL Error: ORA-00904: "PATINDEX": invalid identifier
00904. 00000 - "%s: invalid identifier"
EDIT
I think that the trim route might be my best option, however... I am uncertain how to use it in the case I have.
INSERT INTO temp_table
(columnNeedTrim, column2, column3, column4, column5)
SELECT * FROM
(SELECT(
SELECT TRIM(leading '0' from columnNeedTrim) FROM table),
table.column2,
table2.column3,
table.column4
table.column5
FROM
table
INNER JOIN
table2 ON
table1.columnNeedTrim=table2.columnNeedTrim)
WHERE NOT EXISTS (SELECT * FROM temp_table);
I now get an error because my trim function returns multiple row result.
Error report:
SQL Error: ORA-01427: single-row subquery returns more than one row
01427. 00000 - "single-row subquery returns more than one row"
I am not sure how to work a trim (or a cast) into the statement above. Any help on that?
Thanks for any help!

Oracle has built-in TRIM functions for strings. Assuming you have a string like '00012345' and you want to keep it as a string, not convert it to an actual NUMBER, you can use the LTRIM function with the optional second setparameter specifying that you're triming zeros:
select ltrim('000012345', '0') from dual;
LTRIM
-----
12345
If you might also have leading spaces you can trim both in one go:
select ltrim(' 00012345', '0 ') from dual;
LTRIM
-----
12345
You could also convert to a number and back, but that seems like a lot of work unless you have other formatting that you want to strip out:
select to_char(to_number('000012345')) from dual;
Incidentally, the immediate reason you get the ORA-01722 from your first attempt is that you're using the numeric + operator instead of Oracle's string concentenation operator ||. It's doing an implicit conversion of your string to a number, which it seems you're trying to avoid, and the implicit conversion of the single space - whatever that is for - is causing the error. (Possibly some of your values are not, in fact, numbers at all - another example of why numbers should be stored in NUMBER fields; and if that is the case then converting (or casting) to a number and back would still get the ORA-01722). You'd get the same thing in the second attempt if you were using LENGTH instead of LEN. Neither would work anyway as INSTR doesn't recognise regular expressions. You could use REGEXP_INSTR instead, but you'd be better off with #schurik's REGEXP_REPLACE version if you wanted to go down that route.
I'm not sure I understand your question edit. It looks like your insert can be simplified to:
INSERT INTO temp_table (columnNeedTrim, column2, column3, column4, column5)
SELECT LTRIM(table1.columnNeedTrim, '0 '),
table1.column2,
table1.column3,
table1.column4,
table1.column5
FROM table1
INNER JOIN table2 ON table2.columnNeedTrim = table1.columnNeedTrim
WHERE NOT EXISTS (
SELECT * FROM temp_table
WHERE columnNeedTrim = LTRIM(t42.columnNeedTrim, '0 '));
(I don't understand why you're doing a subquery in your version, or why you're getting the trimmed value from another subquery.)
You could also use MERGE:
MERGE INTO temp_table tt
USING (
SELECT LTRIM(t42.columnNeedTrim, '0 ') AS columnNeedTrim,
t42.column2,
t42.column3,
t42.column4,
t42.column5
FROM t42
INNER JOIN t43 ON t43.columnNeedTrim=t42.columnNeedTrim
) sr
ON (sr.columnNeedTrim = tt.columnNeedTrim)
WHEN NOT MATCHED THEN
INSERT (tt.columnNeedTrim, tt.column2, tt.column3, tt.column4, tt.column5)
VALUES (sr.columnNeedTrim, sr.column2, sr.column3, sr.column4, sr.column5);

SELECT '00012345' AS zeroWith, TRIM(LEADING 0 FROM '00012345') AS zeroWithOut
FROM dual;
Result : zeroWith > 00012345 & zeroWithOut > 12345

For SQL server, if you know the data is actually a number, you can just cast it twice. Casting to an int removes the leading zeroes, then back to a string for insertion. I'm assuming you can do something similar in Oracle.
DECLARE #vc varchar(100) = '0000000000000000000001234'
SELECT CAST(CAST(#vc as int) as varchar(100))
Returns:
1234

You do not have to replace it. It will be handled by Oracle.
SELECT TO_NUMBER(num)
FROM
(
SELECT '00000123' AS num FROM DUAL
);
-- Result:
-- 123

You can use the following methods:
Option 1: use the ltrim function as Alex said:
select ltrim('0005400', '0')
from dual;
Option 2: use the trim function:
select trim(leading '0' from '0005400')
from dual;
Oracle trim function has the leading, trailing and both options.
Option 3: use regular expressions:
select regexp_substr('0005400', '[^0].+')
from dual;

Related

DB2 SQL Split Record by Delimiter if exists

I would like to return the portion of a string BEFORE a delimiter (in this case, a hyphen). What I find is that DB2 is throwing an error because there's an inconsistency in the values of the column where some records have a hyphen meanwhile others do not. So, I'd like to return the string before hyphen if it exists, otherwise just return the string as is.
Example shown with COLUMN1 below:
ID
COLUMN1
1
ASHJE-JFE
2
QER-SK
3
KSETK
4
SDJ-EJLF
I wrote the following query to return the string prior/before '-' but, I get the following error:
The statement was not executed because a numeric argument of a scalar
function is out of range.
I believe this is because there are records where a hyphen does not exist...
select distinct column1, locate('-',column1), substr(column1,1, (locate('-',column1) - 1)) from db2.table
where column1 is not null
fetch first 25 rows only
with ur
Does anyone know how to accomplish something similar but return the string as is when a hyphen does not exist? Thank you!
You may use the following expression:
SUBSTR (COLUMN1, 1, COALESCE (NULLIF (LOCATE ('-', COLUMN1), 0) - 1, LENGTH (COLUMN1)))
You can use a CASE statement to search for the hyphen along with a LIKE operator and % wildcards.
SELECT ID, column1,
CASE WHEN column1 LIKE '%-%'
THEN substr(column1,1,locate('-',column1)-1)
ELSE column1
END AS column2
FROM fileName
WHERE column1 IS NOT NULL
FETCH FIRST 25 ROWS ONLY
See Fiddle
Result:
ID
COLUMN1
COLUMN2
1
ASHJE-JFE
ASHJE
2
QER-SK
QER
3
KSETK
KSETK
4
SDJ-EJLF
SDJ

How to select rows with only Numeric Characters in Oracle SQL

I would like to keep rows only with Numeric Character i.e. 0-9. My source data can have any type of character e.g. 2,%,( .
Input (postcode)
3453gds sdg3
454232
sdg(*d^
452
Expected Output (postcode)
454232
452
I have tried using WHERE REGEXP_LIKE(postcode, '^[[:digit:]]+$');
however in my version of Oracle I get an error saying
function regexp_like(character varying, "unknown") does not exist
You want regexp_like() and your version should work:
select t.*
from t
where regexp_like(t.postcode, '^[0-9]+$');
However, your error looks more like a Postgres error, so perhaps this will work:
t.postcode ~ '^[0-9]+$'
For Oracle 10 or higher you can use regexp functions. In earlier versions translate function will help you :
SELECT postcode
FROM table_name
WHERE length(translate(postcode,'0123456789','1')) is null
AND postcode IS NOT NULL;
OR
SELECT translate(postcode, '0123456789' || translate(postcode,'x123456789','x'),'0123456789') nums
FROM table_name ;
the above answer also works for me
SELECT translate('1234bsdfs3#23##PU', '0123456789' || translate('1234bsdfs3#23##PU','x123456789','x'),'0123456789') nums
FROM dual ;
Nums:
1234323
For an alternative to the Gordon Linoff answer, we can try using REGEXP_REPLACE:
SELECT *
FROM yourTable
WHERE REGEXP_REPLACE(postcode, '[0-9]+', '') IS NULL;
The idea here is to strip away all digit characters, and then assert that nothing were left behind. For a mixed digit-letter value, the regex replacement would result in a non-empty string.

PLSQL show digits from end of the string

I have the following problem.
There is a String:
There is something 2015.06.06. in the air 1234567 242424 2015.06.07. 12125235
I need to show only just the last date from this string: 2015.06.07.
I tried with regexp_substr with insrt but it doesn't work.
So this is just test, and if I can solve this after it with this solution I should use it for a CLOB query where there are multiple date, and I need only the last one. I know there is regexp_count, and it is help to solve this, but the database what I use is Oracle 10g so it wont work.
Can somebody help me?
The key to find the solution of this problem is the idea of reversing the words in the string presented in this answer.
Here is the possible solution:
WITH words AS
(
SELECT regexp_substr(str, '[^[:space:]]+', 1, LEVEL) word,
rownum rn
FROM (SELECT 'There is something 2015.06.06. in the air 1234567 242424 2015.06.07. 2015.06.08 2015.06.17. 2015.07.01. 12345678999 12125235' str
FROM dual) tab
CONNECT BY LEVEL <= LENGTH(str) - LENGTH(REPLACE(str, ' ')) + 1
)
, words_reversed AS
(
SELECT *
FROM words
ORDER BY rn DESC
)
SELECT regexp_substr(word, '\d{4}\.\d{2}\.\d{2}', 1, 1)
FROM words_reversed
WHERE regexp_like(word, '\d{4}\.\d{2}\.\d{2}')
AND rownum = 1;
From the documentation on regexp_substr, I see one problem immediately:
The . (period) matches any character. You need to escape those with a backslash: \. in order to match only a period character.
For reference, I am linking this post which appears to be the approach you are taking with substr and instr.
Relevant documentation from Oracle:
INSTR(string , substring [, position [, occurrence]])
When position is negative, then INSTR counts and searches backward from the end of string. The default value of position is 1, which means that the function begins searching at the beginning of string.
The problem here is that your regular expression only returns a single value, as explained here, so you will be giving the instr function the appropriate match in the case of multiple dates.
Now, because of this limitation, I recommend using the approach that was proposed in this question, namely reverse the entire string (and your regular expression, i.e. \d{2}\.\d{2}\.\d{4}) and then the first match will be the 'last match'. Then, perform another string reversal to get the original date format.
Maybe this isn't the best solution, but it should work.
There are three different PL/SQL functions that will get you there.
The INSTR function will identify where the first "period" in the date string appears.
SUBSTR applied to the entire string using the value from (1) as the start point
TO_DATE for a specific date mask: YYYY.MM.DD will convert the result from (2) into a Oracle date time type.
To make this work in procedural code, the standard blocks apply:
DECLARE
v_position pls_integer;
... other variables
BEGIN
sql code and function calls;
END
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE finddate
(column1 varchar2(11), column2 varchar2(39))
;
INSERT ALL
INTO finddate (column1, column2)
VALUES ('row1', '1234567 242424 2015.06.07. 12125235')
INTO finddate (column1, column2)
VALUES ('string2', '1234567 242424 2015.06.07. 12125235')
SELECT * FROM dual
;
Query 1:
select instr(column2,'.',1) from finddate
where column1 = 'string2'
select substr(column2,(20-4),10) from finddate
select to_date('2015.06.07','YYYY.MM.DD') from finddate
Results:
| TO_DATE('2015.06.07','YYYY.MM.DD') |
|------------------------------------|
| June, 07 2015 00:00:00 |
| June, 07 2015 00:00:00 |
Here's a way using regexp_replace() that should work with 10g, assuming the format of the lines will be the same:
with tbl(col_string) as
(
select 'There is something 2015.06.06. in the air 1234567 242424 2015.06.07. 12125235'
from dual
)
select regexp_replace(col_string, '^.*(\d{4}\.\d{2}\.\d{2})\. \d*$', '\1')
from tbl;
The regex can be read as:
^ - Match the start of the line
. - followed by any character
* - followed by 0 or more of the previous character (which is any character)
( - Start a remembered group
\d{4}\.\d{2}\.\d{2} - 4 digits followed by a literal period followed by 2 digits, etc
) - End the first remembered group
\. - followed by a literal period
- followed by a space
\d* - followed by any number of digits
$ - followed by the end of the line
regexp_replace then replaces all that with the first remembered group (\1).
Basically describe the whole line as a regular expression, group around what you want to return. You will most likely need to tweak the regex for the end of the line if it could be other characters than digits but this should give you an idea.
For the sake of argument this works too ONLY IF there are 2 occurrences of the date pattern:
with tbl(col_string) as
(
select 'There is something 2015.06.06. in the air 1234567 242424 2015.06.07. 12125235' from dual
)
select regexp_substr(col_string, '\d{4}\.\d{2}\.\d{2}', 1, 2)
from tbl;
returns the second occurrence of the pattern. I expect the above regexp_replace more accurately describes the solution.

number format to char in oracle while creating a view

I have the below view:
CREATE OR REPLACE VIEW viewA ("col1", "col2") AS
SELECT DISTINCT CAST("col1" AS CHAR(1)),
CAST(to_char("col2",'00.0000') AS char(7))
FROM tableA
the col2 has data like 22.33 or 2.3 or 0.2345 or 2 but, four digits in dec and 2 digits in number.
It has to be written into a file with fixed length of 7 digits including decimal. Hence i wrote col2, '00.0000', but the number format'23.234' is written into col2 as 23.234 without any trailing zero.
Your format code of 00.0000 should include the fourth decimal place for 23.234; it's always worked for me. I'm using Oracle 11.
The problem I got when I tried doing CAST(TO_CHAR(23.234, '00.0000') AS CHAR(7)) was the error ORA-25137: Data value out of range. This happens because because the TO_CHAR returns a string of length 8:
SQL> SELECT '[' || TO_CHAR(23.234, '00.0000') || ']' FROM DUAL
'['||TO_CH
----------
[ 23.2340]
TO_CHAR leaves a space at the beginning in case the number is negative, in which case it will put a minus sign there. You can get rid of the leading space by using the FM modifier in the format string:
SQL> SELECT '[' || TO_CHAR(23.234, 'FM00.0000') || ']' FROM DUAL
'['||TO_CH
----------
[23.2340]
This is all a long way of saying "try this instead" - the only change is the FM in the TO_CHAR format string:
CREATE OR REPLACE VIEW viewA ("col1", "col2") AS
SELECT DISTINCT
CAST("col1" AS CHAR(1)),
CAST(to_char("col2",'FM00.0000') AS char(7))
FROM tableA
One final note: enclosing the column names with double quotes makes them case sensitive, and that often leads to trouble. I'd recommend losing the double quotes if you can.
You need to use the RPAD function that would add trailing zeros for you
CREATE OR REPLACE VIEW viewA ("col1", "col2") AS
SELECT DISTINCT CAST("col1" AS CHAR(1)),
RPAD(CAST(to_char("col2",'00.0000') AS char(7)),7,'0')
FROM tableA
But you might face a problem if your number did not have a decimal value, for example assuming the value is 12 you will end up with 1200000 but maybe this would give you an idea

Remove leading zeros

Given data in a column which look like this:
00001 00
00026 00
I need to use SQL to remove anything after the space and all leading zeros from the values so that the final output will be:
1
26
How can I best do this?
Btw I'm using DB2
This was tested on DB2 for Linux/Unix/Windows and z/OS.
You can use the LOCATE() function in DB2 to find the character position of the first space in a string, and then send that to SUBSTR() as the end location (minus one) to get only the first number of the string. Casting to INT will get rid of the leading zeros, but if you need it in string form, you can CAST again to CHAR.
SELECT CAST(SUBSTR(col, 1, LOCATE(' ', col) - 1) AS INT)
FROM tab
In DB2 (Express-C 9.7.5) you can use the SQL standard TRIM() function:
db2 => CREATE TABLE tbl (vc VARCHAR(64))
DB20000I The SQL command completed successfully.
db2 => INSERT INTO tbl (vc) VALUES ('00001 00'), ('00026 00')
DB20000I The SQL command completed successfully.
db2 => SELECT TRIM(TRIM('0' FROM vc)) AS trimmed FROM tbl
TRIMMED
----------------------------------------------------------------
1
26
2 record(s) selected.
The inner TRIM() removes leading and trailing zero characters, while the outer trim removes spaces.
This worked for me on the AS400 DB2.
The "L" stands for Leading.
You can also use "T" for Trailing.
I am assuming the field type is currently VARCHAR, do you need to store things other than INTs?
If the field type was INT, they would be removed automatically.
Alternatively, to select the values:
SELECT (CAST(CAST Col1 AS int) AS varchar) AS Col1
I found this thread for some reason and find it odd that no one actually answered the question. It seems that the goal is to return a left adjusted field:
SELECT
TRIM(L '0' FROM SUBSTR(trim(col) || ' ',1,LOCATE(' ',trim(col) || ' ') - 1))
FROM tab
One option is implicit casting: SELECT SUBSTR(column, 1, 5) + 0 AS column_as_number ...
That assumes that the structure is nnnnn nn, ie exactly 5 characters, a space and two more characters.
Explicit casting, ie SUBSTR(column,1,5)::INT is also a possibility, but exact syntax depends on the RDBMS in question.
Use the following to achieve this when the space location is variable, or even when it's fixed and you want to make a more robust query (in case it moves later):
SELECT CAST(SUBSTR(LTRIM('00123 45'), 1, CASE WHEN LOCATE(' ', LTRIM('00123 45')) <= 1 THEN LEN('00123 45') ELSE LOCATE(' ', LTRIM('00123 45')) - 1 END) AS BIGINT)
If you know the column will always contain a blank space after the start:
SELECT CAST(LOCATE(LTRIM('00123 45'), 1, LOCATE(' ', LTRIM('00123 45')) - 1) AS BIGINT)
both of these result in:
123
so your query would
SELECT CAST(SUBSTR(LTRIM(myCol1), 1, CASE WHEN LOCATE(' ', LTRIM(myCol1)) <= 1 THEN LEN(myCol1) ELSE LOCATE(' ', LTRIM(myCol1)) - 1 END) AS BIGINT)
FROM myTable1
This removes any content after the first space character (ignoring leading spaces), and then converts the remainder to a 64bit integer which will then remove all leading zeroes.
If you want to keep all the numbers and just remove the leading zeroes and any spaces you can use:
SELECT CAST(REPLACE('00123 45', ' ', '') AS BIGINT)
While my answer might seem quite verbose compared to simply SELECT CAST(SUBSTR(myCol1, 1, 5) AS BIGINT) FROM myTable1 but it allows for the space character to not always be there, situations where the myCol1 value is not of the form nnnnn nn if the string is nn nn then the convert to int will fail.
Remember to be careful if you use the TRIM function to remove the leading zeroes, and actually in all situations you will need to test your code with data like 00120 00 and see if it returns 12 instead of the correct value of 120.