Number check in oracle sql - sql

How to check in 10 digit number whether it contain 999 or 000 in the 4-6th bytes ?
I have a n idea with using INSTR but i don't know how to execute it

This is strange. If the "number" is really a string, then you can use like or substr():
where col like '___999%' or col like '___000%'
or:
where substr(col, 4, 3) in ('999', '000')
or even regular expressions.
Given the nature of your question, you can turn a number into a string and use these methods. However, if you are looking at particular digits, then the "number" should be stored as a string.

If they are actually numbers rather than strings then you could use numeric manipulation:
with t (n) as (
select 1234567890 from dual
union all select 1239997890 from dual
union all select 1230007890 from dual
union all select 1299967890 from dual
union all select 1234000890 from dual
)
select n,
mod(n, 10000000) as stage1,
mod(n, 10000000)/10000 as stage2,
trunc(mod(n, 10000000)/10000) as stage3,
case when trunc(mod(n, 10000000)/10000) in (0, 999) then 'Yes' else 'No' end as matches
from t;
N STAGE1 STAGE2 STAGE3 MATCHES
---------- ---------- ---------- ---------- -------
1234567890 4567890 456.789 456 No
1239997890 9997890 999.789 999 Yes
1230007890 7890 .789 0 Yes
1299967890 9967890 996.789 996 No
1234000890 4000890 400.089 400 No
Stage 1 effectively strips off the first three digits. Stage two almost strips off the last four digits, but leaves fractions, so stage 3 adds trunc() (you could also use floor()) to ignore those fractional parts.
The result of that is the numeric value of the 4-6th digits, and you can then test if that is 0, 999 or something else.
This is really looking at the 4th to 6th most significant digits, which is the same if the number is always 10 digits; if it might actually have different numbers of digits then you'd need to clarify what you want to see.

select
1 from dual where instr(98800054542,000,4,3)in (6) or instr(98800054542,999,4,3)in (6); let me know if this helped.

Related

Issues with SUBSTR function Oracle_SQL

I used the SUBSTR function for the similar purposes, but I encountered the following issue:
I am extracting 6 characters from the right, but the data in column is inconsistent and for some rows it has characters less than 6, i.e. 5 or 4. So for such rows, the function returns blanks. How can I fix this?
Example Scenario 1:
SUBSTR('0000123456',-6,6)
Output: 123456
Scenario 2 (how do I fix this?, I need it to return '23456'):
SUBSTR('23456',-6,6)
Output: ""
You can use a case expression: if the string length is strictly greater than 6 then return just the last 6 characters; otherwise return the string itself. This way you don't need to call substr unless it is really needed.
Alternatively, if speed is not the biggest issue and you are allowed to use regular expressions, you can write this more compactly - select between 0 and 6 characters - as many as possible - at the end of the string.
Finally, if you don't mind using undocumented functions, you can use reverse and standard substr (starting from character 1 and extracting the first 6 characters; that will work as expected even if the string has length less than 6). So: reverse the string, extract first (up to) 6 characters, and then reverse again to restore the order. WARNING: This is shown only for fun; DO NOT USE THIS METHOD!
with
test_data (str) as (
select '0123449389' from dual union all
select '00000000' from dual union all
select null from dual union all
select 'abcd' from dual
)
select str,
case when length(str) > 6 then substr(str, -6) else str end as case_substr,
regexp_substr(str, '.{0,6}$') as regexp_substr,
reverse(substr(reverse(str), 1, 6)) as rev_substr
from test_data
;
STR CASE_SUBSTR REGEXP_SUBSTR REV_SUBSTR
---------- ------------- ------------- --------------
0123449389 449389 449389 449389
00000000 000000 000000 000000
abcd abcd abcd abcd
One method uses coalesce():
select coalesce(substr('23456', -6, 6), '23456')
Another tweaks the length:
select substr('23456', greatest(- length('23456'), -6), 6)

Remove 2 characters in oracle sql

I have a column that contains 12 digits but user wants only to generate a 10 digits.
I tried the trim, ltrim function but nothing work. Below are the queries I tried.
ltrim('10', 'column_name')
ltrim('10', column_name)
ltrim(10, column_name)
For example I have a column that contains a 12 digit number
100000000123
100000000456
100000000789
and the expected result I want is
0000000123
0000000456
0000000789
To extract the last 10 characters of an input string, regardless of how long the string is (so this will work if some inputs have 10 characters, some 12, and some 15 characters), you could use negative starting position in substr:
substr(column_name, -10)
For example:
with
my_table(column_name) as (
select '0123401234' from dual union all
select '0001112223334' from dual union all
select '12345' from dual union all
select '012345012345' from dual
)
select column_name, substr(column_name, -10) as substr
from my_table;
COLUMN_NAME SUBSTR
------------- ----------
0123401234 0123401234
0001112223334 1112223334
12345
012345012345 2345012345
Note in particular the third example. The input has only 5 digits, so obviously you can't get a 10 digit number from it. The result is NULL (undefined).
Note also that if you use something like substr(column_name, 3) you will get just '345' in that case; most likely not the desired result.
try to use SUBSTR(column_name, 2)

Retrieve the characters before a matching pattern

135 ;1111776698 ;AB555678765
I have the above string and what I am looking for is to retrieve all the digits before the first occurrence of ;.
But the number of characters before the first occurrence of ; varies i.e. it may be a 4 digit number or 3 digit number.
I have played with regex_instr and instr, but I unable to figure this out.
The query should return all the digits before the first occurrence of ;
This answer assumes that you are using Oracle database. I don't know of way to do this using REGEX_INSTR alone, but we can do with REGEXP_REPLACE using capture groups:
SELECT REGEXP_REPLACE('135 ;1111776698 ;AB555678765', '^\s*(\d{3,4})\s*;.*', '\1')
FROM dual;
Demo
Here is the regex pattern being used:
^\s*(\d{3,4})\s*;.*
This allows, from the start of the string, any amount of leading whitespace, followed by a 3 or 4 digit number, followed again by any amount of whitespace, then a semicolon. The .* at the end of the pattern just consumes whatever remains in your string. Note (\d{3,4}), which captures the 3-4 digit number, which is then available in the replacement as \1.
Using INSTR,SUBTSR and TRIM should work ( based on your comment that there are "just white spaces and digits" )
select TRIM(SUBSTR(s,1, INSTR(s,';')-1)) FROM t;
Demo
The following using regexp_substr() should work:
SELECT s, REGEXP_SUBSTR(s, '^[^;]*')
Make sure you try all possible values in that first position, even those you don't expect and make sure they are handled as you want them to be. Always expect the unexpected! This regex matches the first subgroup of zero or more optional digits (allows a NULL to be returned) when followed by an optional space then a semi-colon, or the end of the line. You may need to tighten (or loosen) up the matching rules for your situation, just make sure to test even for incorrect values, especially if the input comes from user-entered data.
with tbl(id, str) as (
select 1, '135 ;1111776698 ;AB555678765' from dual union all
select 2, ' 135 ;1111776698 ;AB555678765' from dual union all
select 3, '135;1111776698 ;AB555678765' from dual union all
select 4, ';1111776698 ;AB555678765' from dual union all
select 5, ';135 ;1111776698 ;AB555678765' from dual union all
select 6, ';;1111776698 ;AB555678765' from dual union all
select 7, 'xx135 ;1111776698 ;AB555678765' from dual union all
select 8, '135;1111776698 ;AB555678765' from dual union all
select 9, '135xx;1111776698 ;AB555678765' from dual
)
select id, regexp_substr(str, '(\d*?)( ?;|$)', 1, 1, NULL, 1) element_1
from tbl
order by id;
ID ELEMENT_1
---------- ------------------------------
1 135
2 135
3 135
4
5
6
7 135
8 135
9
9 rows selected.
To get the desired result, you should use REGEX_SUBSTR as it will substring your desired data from the string you give. Here is the example of the Query.
Solution to your example data:
SELECT REGEXP_SUBSTR('135 ;1111776698 ;AB555678765','[^;]+',1,1) FROM DUAL;
So what it does, Regex splits the string on the basis of ; separator. You needed the first occurrence so I gave arguments as 1,1.
So if you need the second string 1111776698 as your output you can give an argument as 1,2.
The syntax for Regexp_substr is as following:
REGEXP_SUBSTR( string, pattern [, start_position [, nth_appearance [, match_parameter [, sub_expression ] ] ] ] )
Here is the link for more examples:
https://www.techonthenet.com/oracle/functions/regexp_substr.php
Let me know if this works for you. Best luck.

Oracle SQL My input should be the format mask in to_char(:n,'fm000')

If my string has more length than 4 digits then my output is displayed as #######
For that the query is:
select to_char(:n,'fm0000') from dual;
It should take the number of zeros based on the input bind variables length after fm.
INPUT : 123
OUTPUT: 0123
INPUT : 123456789
OUTPUT: 0123456789
Zero should come before the number of input.
Any Suggestions!!
Edit - the OP changed the requirement completely.
The solution to the edited problem is trivial:
... '0' || to_char(:n)
End of edit - Original answer (to the question as originally posted) below.
It seems what you are trying to do is best achieved like this. Never mind the with clause, that is only for testing. Adapt as needed, and use enough nines in the format model to cover your longest inputs.
with
test_data ( n ) as (
select 3 from dual union all
select 19923 from dual
)
select n, to_char(n, 'fm99990000') as n_str
from test_data
;
N N_STR
------ --------
3 0003
19923 19923
2 rows selected.
According to documentation
If you omit fmt, then n is converted to a VARCHAR2 value exactly long
enough to hold its significant digits
so perhaps all you need is to_char(:n)
Based on your updated requirement, you can do this with a slight modification of #mathguy's original format mask manipulation; or with default conversion to a string and left-padding, or even more simly just prepending a single zero:
with t (n) as (
select 1 from dual
union all select 123 from dual
union all select 123456789 from dual
)
select n,
to_char(n, 'fm' || rpad('0', length(n) + 1, '0')) as n_str_1,
lpad(to_char(n), length(n) + 1, '0') as n_str_2,
'0' || to_char(n) as n_str_3
from t;
N N_STR_1 N_STR_2 N_STR_3
---------- ---------- ---------- ----------
1 01 01 01
123 0123 0123 0123
123456789 0123456789 0123456789 0123456789
If the field you are checking is a string:
case when substring(field, 1, 1)!=0 then '0'||field else field end
If it's a number you can always add a 0 as proposed by others:
'0'||to_char(field)

to_number from char sql

I have to select only the IDs which have only even digits (an ID looks like: p19 ,p20 etc). That is, p20 is good (both 2 and 0 are even digits); p18 is not.
I thought to use substr to get each number from the IDs and then see if it's even .
select from profs
where to_number(substr(id_prof,2,2))%2=0 and to_number(substr(id_prof,3,2))%2=0;
IF you need all rows consist of 'p' in beginning and even digits on tail It should look like:
select *
from profs
where regexp_like (id_prof, '^p[24680]+$');
with
profs ( prof_id ) as (
select 'p18' from dual union all
select 'p24' from dual union all
select 'p53' from dual
)
-- End of test data; what is above this line is NOT part of the solution.
-- The solution (SQL query) begins here.
select *
from profs
where length(prof_id) = length(translate(prof_id, '013579', '0'));
PROF_ID
-------
p24
This solution should work faster than anything using regular expressions. All it does is to replace 0 with itself and DELETE all odd digits from the input string. (The '0' is included due to a strange but documented behavior of translate() - the third argument can't be empty). If the length of the input string doesn't change after the translation, that means the input string didn't have any odd digits.
where mod(to_number(regexp_replace(id_prof, '[^[:digit:]]', '')),2) = 0