Insert some spaces into a string oracle database - sql

I have a oracle table called MYTABLE , with a prog_model column.
I am trying the CASE (if oracle) to insert some spaces into my prog_model depending of the string length.
My issue is that I'm getting ORA-00936 error missing expression ligne 3 c18 I have no idea where it comes from being a super noob in SQL, any ideas?
Here is my .sql :
SELECT prog_model,
CASE Length(prog_model)
WHEN 11 THEN Insert(' ',2,3,prog_model)
WHEN 12 THEN Insert(' ',2,3,prog_model)
WHEN 13 THEN Insert(' ',2,3,prog_model)
END
FROM MYTABLE;
EDIT:
Basically in prog_model I always have a string from 11 to 14 characters :
if 11 chars , "ABCEFGHIJKL" --> "ABC_ _ _EFGHIKL"
if 12 chars , "ABCEFGHIJKLM" --> "ABC_ _EFGHIJKLM"

I am not aware of an insert() function in Oracle. There is one in MySQL, though. Your error is probably because insert is a keyword.
If you wanted the spaces at the beginning, you would use the lpad() function only:
select lpad(prog_model, 14, ' ')
You seem to want them in the middle. I think this goes like:
select substr(prog_model, 1, 3) || lpad(substr(prog_model, 4), 11, ' ')
I might have the length wrong in the second part. Without sample data, it is challenging to figure out the exact length.

How about this (three approaches to try, including Gordon's substr/lpad):
with demo (prog_model) as
( select 'ABCEFGHIJKL' from dual union all
select 'ABCEFGHIJKLM' from dual union all
select 'ABCEFGHIJKLMN' from dual union all
select 'ABCEFGHIJKLMNO' from dual )
select prog_model
, regexp_replace(prog_model,'(...)(.*$)', '\1'|| rpad(' ',14 - length(prog_model)) ||'\2') as result1
, case length(prog_model)
when 11 then regexp_replace(prog_model,'(...)(.*$)', '\1 \2')
when 12 then regexp_replace(prog_model,'(...)(.*$)', '\1 \2')
when 13 then regexp_replace(prog_model,'(...)(.*$)', '\1 \2')
when 14 then prog_model
end as result2
, substr(prog_model,1,3) || lpad(substr(prog_model,4),11) as result3
from demo;
PROG_MODEL RESULT1 RESULT2 RESULT3
-------------- -------------- -------------- --------------
ABCEFGHIJKL ABC EFGHIJKL ABC EFGHIJKL ABC EFGHIJKL
ABCEFGHIJKLM ABC EFGHIJKLM ABC EFGHIJKLM ABC EFGHIJKLM
ABCEFGHIJKLMN ABC EFGHIJKLMN ABC EFGHIJKLMN ABC EFGHIJKLMN
ABCEFGHIJKLMNO ABCEFGHIJKLMNO ABCEFGHIJKLMNO ABCEFGHIJKLMNO

Related

Oracle SQL: Merging multiple columns into 1 with conditions

I am new to SQL and don't really have a lot of experience. I need help on this where I have Table A and I want to write a SQL query to generate the result. Any help would be greatly appreciated! Thanks!
Table A
Name
Capacity A
Capacity B
Capacity C
Plant 1
10
20
Plant 2
10
Result Table
Name
Type
Capacity
Plant 1
A,C
10,20
Plant 2
B
10
I know listagg function might be able to combine few columns into one, but is there anyway for me to generate the additional column 'Type' where its smart enough to know which column I am taking my value from? Preferably without creating any additional views/table.
Use NVL2 (or CASE) and concatenate the columns and trim any excess trailing commas:
SELECT Name,
RTRIM(
NVL2(CapacityA,'A,',NULL)
||NVL2(CapacityB,'B,',NULL)
||NVL2(CapacityC,'C',NULL),
','
) AS type,
RTRIM(
NVL2(CapacityA,CapacityA||',',NULL)
||NVL2(CapacityB,CapacityB||',',NULL)
||NVL2(CapacityC,CapacityC,NULL),
','
) AS capacity
FROM table_name;
Which, for the sample data:
CREATE TABLE table_name (name, capacitya, capacityb, capacityc) AS
SELECT 'Plant1', 10, NULL, 20 FROM DUAL UNION ALL
SELECT 'Plant2', NULL, 10, NULL FROM DUAL;
Outputs:
NAME
TYPE
CAPACITY
Plant1
A,C
10,20
Plant2
B
10
db<>fiddle here
Here's one option:
sample data in lines #1 - 4
temp CTE simply - conditionally - concatenates types and capacities
final query (line #17)
removes double separators (commas) (regexp)
removes superfluous leading/trailing commas (trim)
SQL> with test (name, capa, capb, capc) as
2 (select 'Plant1', 10, null, 20 from dual union all
3 select 'Plant2', null, 10, null from dual
4 ),
5 temp as
6 (select name,
7 --
8 case when capa is not null then 'A' end ||','||
9 case when capb is not null then 'B' end ||','||
10 case when capc is not null then 'C' end as type,
11 --
12 case when capa is not null then capa end ||','||
13 case when capb is not null then capb end ||','||
14 case when capc is not null then capc end as capacity
15 from test
16 )
17 select name,
18 trim(both ',' from regexp_replace(type , ',+', ',')) as type,
19 trim(both ',' from regexp_replace(capacity, ',+', ',')) as capacity
20 from temp;
NAME TYPE CAPACITY
------ ---------- ----------
Plant1 A,C 10,20
Plant2 B 10
SQL>

REGEXP to validate a specific number

How can I search for a specific number in an array using REGEXP?
I have an array and need to verify if it has a specific number.
Ex: [5,2,1,4,6,19] and I am looking for number 1, but just the number 1 and not any number that contain the digit 1.
I had to do this:
case when REGEXP_INSTR(JSON_QUERY(MY_JSON_COLUMN,'$.path') , '[[]{1}[1][,]')<>0
or REGEXP_INSTR(JSON_QUERY(MY_JSON_COLUMN,'$.path') , '[,]{1}[1][,]{1}')<>0
or REGEXP_INSTR(JSON_QUERY(MY_JSON_COLUMN,'$.path') , '[,]{1}[1][]]')<>0
or REGEXP_INSTR(JSON_QUERY(MY_JSON_COLUMN,'$.path') , '[[]{1}[1][]]') <>0
then 'DIGIT_ONE' else 'NO_DIGIT_ONE'
end
Is there anything simpler?
You can use
(^|\D)1(\D|$)
This will seach for 1 not enclosed with other digits.
See this regex demo.
Details
(^|\D) - start of string or non-digit
1 - a 1 char
(\D|$) - non-digit or end of string.
Do NOT use regular expressions, use a proper JSON parser and then filter for the number you want:
SELECT my_json_column,
CASE
WHEN JSON_EXISTS( my_json_column, '$?(#.path[*] == 1)' )
THEN 'DIGIT ONE'
ELSE 'NO DIGIT ONE'
END AS has_one
FROM table_name;
or (if you are using Oracle 12.1 and cannot use path filter expressions with JSON_EXISTS, which is only available from Oracle 12.2):
SELECT my_json_column,
CASE
WHEN EXISTS(
SELECT 'X'
FROM JSON_TABLE(
t.my_json_column,
'$.path[*]'
COLUMNS (
value NUMBER PATH '$'
)
)
WHERE value = 1
)
THEN 'DIGIT ONE'
ELSE 'NO DIGIT ONE'
END
FROM table_name t;
Which, for the sample data:
CREATE TABLE table_name (
my_json_column CHECK ( my_json_column IS JSON )
) AS
SELECT '{"path":[5,2,1,4,6,19],"not_this_path":[1,2,3,4,5]}' FROM DUAL UNION ALL
SELECT '{"path":[5,2,4,6,19],"not_this_path":[1,2,3,4,5]}' FROM DUAL UNION ALL
SELECT '{"path":[11],"not_this_path":[1]}' FROM DUAL UNION ALL
SELECT '{"path":[2],"not_this_path":[1]}' FROM DUAL UNION ALL
SELECT '{"path":[1,11]}' FROM DUAL;
Both output:
MY_JSON_COLUMN | HAS_ONE
:-------------------------------------------------- | :-----------
{"path":[5,2,1,4,6,19],"not_this_path":[1,2,3,4,5]} | DIGIT ONE
{"path":[5,2,4,6,19],"not_this_path":[1,2,3,4,5]} | NO DIGIT ONE
{"path":[11],"not_this_path":[1]} | NO DIGIT ONE
{"path":[2],"not_this_path":[1]} | NO DIGIT ONE
{"path":[1,11]} | DIGIT ONE
db<>fiddle here
Alternatively, with a little bit more typing (a little bit? Am I kidding?!), splitting the string into rows and comparing values to the search string:
SQL> with test (col) as
2 (select '[5,2,1,4,6,19]' from dual)
3 select t.col,
4 case when '&par_search_string' in
5 (select regexp_substr(substr(col, 2, length(col) - 1), '[^,]+', 1, level) val
6 from test
7 connect by level <= regexp_count(col, ',') + 1
8 )
9 then 'Search string exists'
10 else 'Search string does not exist'
11 end result
12 from test t;
Enter value for par_search_string: 1
COL RESULT
-------------- ----------------------------
[5,2,1,4,6,19] Search string exists
SQL> /
Enter value for par_search_string: 24
COL RESULT
-------------- ----------------------------
[5,2,1,4,6,19] Search string does not exist
SQL>

TRIM Trailing Zeros

I know this is a relatively simple question, but I couldn't find anything with my keywords using Google.
I am referencing with a SQL (Oracle) to a column that has numbers like that:
100
12500
300
Now I need to remove the last 2 zeros.
This approach is not working:
Trim(TRAILING '00' FROM F0035.Nr) "Sequence",
Does anyone have any idea?
The result should be a column with numbers - not a text
See these two options:
SQL> with test (col) as
2 (select '100' from dual union all
3 select '12500' from dual union all
4 select '300' from dual
5 )
6 select col,
7 to_number(substr(col, 1, length(col) - 2)) result_1,
8 to_number(col) / 100 result_2
9 from test;
COL RESULT_1 RESULT_2
----- ---------- ----------
100 1 1
12500 125 125
300 3 3
SQL>
the first one removes the last two characters (from your sample data, it seems that they are always 00)
the second one divides that "number" by 100
You could do this:
SELECT regexp_replace(F0035.Nr, '^(.*)00$', '\1')
FROM F0035
You can easily tweak the regular expression if your requirements change subtly, such as removing more than 2 trailing zeros (e.g. ^(.*)00+), or other characters
with test (col) as (
select 10 from dual union all
select 100 from dual union all
select 1000 from dual union all
select 12500 from dual union all
select 125002 from dual union all
select 3000 from dual
)
select col,
case when substr(col, -2) = '00' then col/100 else col end newnum
from test;
If the column contains numbers, why are you using string operations?
If all values have two 00s as the end, then:
F0035.Nr / 100
If some do not, then use a case:
(case when mod(F0035.Nr, 100) = 0 then F0035.Nr / 100 else F0035.Nr end)
I don't recommend converting to a string to do numeric operations under most circumstances.
The following expression will strip off any number of zeroes from a number:
SELECT NR / POWER(10, LENGTH(REGEXP_SUBSTR(TO_CHAR(NR), '0*$')))
FROM F0035
db<>fiddle here

pls help me with this oracle sql query

I have to write a oracle SQL query where I have to check that length of string is 64 or not if it's 64 like in this string
'Lst021_23-FehlerDatenprotokoll.AenDienst2019.06.11_08.48.42.tx' then extension of the string should be txt and we have to remove the part of string upto - also
So for the string
'Lst021_23-FehlerDatenprotokoll.AenDienst2019.06.11_08.48.42.tx' output will be
FehlerDatenprotokoll.AenDienst2019.06.11_08.48.42.txt
i am trying to write this query
SELECT 'Lst021_23-Fehler-Datenprotokoll.AenDienst.2019.06.11_08.48.42.tx'FROM Dual;
CASE
WHEN LENGTH('Lst021_23-Fehler-Datenprotokoll.AenDienst.2019.06.11_08.48.42.tx')=64 THEN CONCAT('SUBSTR('Lst021_23-Fehler-Datenprotokoll.AenDienst.2019.06.11_08.48.42.tx',11,53)','t')
END
CASE;
You have syntax issue in the script. Try this way
SELECT
CASE
WHEN LENGTH('Lst021_23-Fehler-Datenprotokoll.AenDienst.2019.06.11_08.48.42.tx') = 64
THEN CONCAT(SUBSTR('Lst021_23-Fehler-Datenprotokoll.AenDienst.2019.06.11_08.48.42.tx',11,53),'t')
ELSE 'Lst021_23-Fehler-Datenprotokoll.AenDienst.2019.06.11_08.48.42.tx'
END
FROM Dual;
Prefer writing your string only once :
with t( str ) as
(
select 'Lst021_23-Fehler-Datenprotokoll.AenDienst.2019.06.11_08.48.42.tx' from dual
)
select decode(length(str), 64, concat(str,'t')) as "File Name"
from t;
File Name
-----------------------------------------------------------------
Lst021_23-Fehler-Datenprotokoll.AenDienst.2019.06.11_08.48.42.txt
Demo
How about this? If length is 64, then:
take a substring from the first hyphen (-) to the end of the string
apply regexp_replace and substitute the last "word" (\w+$) with txt (as you said that extension has to be txt)
Here we go:
SQL> with test (id, col) as
2 (select 1, 'Lst021_23-Fehler-Datenprotokoll.AenDienst.2019.06.11_08.48.42.tx' from dual
3 union all
4 select 2, 'blabla-Something-else.Which_is_64_characters_long.2019.06.12.txt' from dual
5 union all
6 select 3, 'This will not be "fixed" as it is shorter than 64 chars.exe' from dual
7 union all
8 select 4, 'Yet another nice string-Kein_Fehler.Mitwoch.2019.06.13_22.22.com' from dual
9 )
10 select
11 id,
12 case when length(col) = 64 then
13 regexp_replace(substr(col, instr(col, '-') + 1), '\w+$', 'txt')
14 else col
15 end result
16 from test;
ID RESULT
--- -----------------------------------------------------------------
1 Fehler-Datenprotokoll.AenDienst.2019.06.11_08.48.42.txt
2 Something-else.Which_is_64_characters_long.2019.06.12.txt
3 This will not be "fixed" as it is shorter than 64 chars.exe
4 Kein_Fehler.Mitwoch.2019.06.13_22.22.txt
SQL>

substring Oracle sql

I need to get substring of String in oralce till a character is found. if Character is not found it should show entire string
Ex :
ABC_DEF
XY_Z
PQRS
Expected result is
ABC
XY
PQRS
I tried below query But it will not work in case search charcter "_" is not found.
SELECT SUBSTR('ABC_X', 0, INSTR('ABC_X', '_')-1) AS output
FROM DUAL
If INSTR() didn't find the character, it would return zero. So, we use DECODE to flip it to length of string itself. otherwise use the position that INSTR returns.
SELECT SUBSTR('ABC_X',0,
DECODE(INSTR('ABC_X', '_'),
0,LENGTH('ABC_X'),
INSTR('ABC_X', '_')-1)) AS output
FROM DUAL;
You can use also regular expressions (something like):
SQL> with t as (
2 select 'ABC_DEF' x from dual union all
3 select 'XY_Z' from dual union all
4 select 'PQRS' from dual union all
5 select '_MJU' from dual union all
6 select 'POI_' from dual union all
7 select 'PAS_PIN_APP' from dual union all
8 select 'LIE$#' from dual
9 )
10 select regexp_substr(x, '[^_]*') from t
11 /
REGEXP_SUBSTR(X,'[^_]*')
--------------------------------------------
ABC
XY
PQRS
POI
PAS
LIE$#