Oracle SQL - find and replace ASCII - sql

In my database, special characters have got inserted with these ASCII values
ASCII(' ') ASCII('')
49828 32
There is ASCII Value 49828 shown in the column description that is showing as special character ¤
How do I find all the values that have this special character? and how to replace it with a regular space (ASCII 32)

I'd say you'd use REPLACE (as you said).
Sample table:
SQL> create table test (col) as
2 select 'x' || chr(67) || 'y' from dual union all
3 select 'x' || chr(49828) || 'y' from dual;
Table created.
Contents (disregard Ą displayed in my SQL*Plus & my database):
SQL> select * from test;
COL
----
xCy
xĄy
Update only rows that contain that value:
SQL> update test set
2 col = replace(col, chr(49828), chr(32))
3 where instr(col, chr(49828)) > 0;
1 row updated.
Result:
SQL> select * from test;
COL
----
xCy
x y
SQL>

Related

Multiline bind parameter

I'm trying the following query from DBeaver (backend is oracle):
SELECT * FROM mytable where mycolumn in (REPLACE( :req_id_list, CHR(13), ','))
when it prompts for the value of req_id_list I want to paste the values from Excel, which will be one value per line. the query is failing with ORA-00907: missing right parenthesis. is there a way to convert the multiline value to a CSV one ?
I don't use DBeaver so this is a SQL*Plus example. Basically, you'll have to "split" that multi-line input value into separate rows (that's what subquery in lines #8 - 10 does):
Declaring a bind variable:
SQL> var req_id_list varchar2(20)
Storing A + carriage return + C into it:
SQL> exec :req_id_list := 'A' || chr(13) || 'C';
PL/SQL procedure successfully completed.
Query itself (lines #1 - 5 represent sample data; I expect A and C to be returned as that's what I passed to req_id_list):
SQL> with mytable (mycolumn) as
2 (select 'A' from dual union all
3 select 'B' from dual union all
4 select 'C' from dual
5 )
6 select *
7 from mytable
8 where mycolumn in (select regexp_substr(replace(:req_id_list, chr(13), '#'), '[^#]+', 1, level)
9 from dual
10 connect by level <= regexp_count(:req_id_list, chr(13)) + 1
11 );
M
-
A
C
SQL>

How to special character after 3rd character in Oracle SQL query

I want to add special character after 3rd character. Below is the example
Current Phone Number:- 123234567
Expected output :- (123)234-567
How can I do this ?
Concatenation, as you said, along with the substr function:
SQL> with test (col) as
2 (select 123234567 from dual)
3 select '(' || substr(col, 1, 3) || ')' ||substr(col, 4, 3) ||'-'|| substr(col, 7) result
4 from test;
RESULT
------------
(123)234-567
SQL>
Or, using regular expressions:
SQL> with test (col) as
2 (select 123234567 from dual)
3 select regexp_replace(col, '([0-9]{3})([0-9]{3})', '(\1)\2-') result_2
4 from test;
RESULT_2
------------
(123)234-567
SQL>

my table contain data in below format and does not contain any automated primary key [duplicate]

I have column in my database where the values are coming like the following:
3862,3654,3828
In dummy column any no. of comma separated values can come. I tried with following query but it is creating duplicate results.
select regexp_substr(dummy,'[^,]+',1,Level) as dummycol
from (select * from dummy_table)
connect by level <= length(REGEXP_REPLACE(dummy,'[^,]+'))+1
I am not understanding the problem. Can anyone can help?
Works perfectly for me -
SQL> WITH dummy_table AS(
2 SELECT '3862,3654,3828' dummy FROM dual
3 )
4 SELECT trim(regexp_substr(dummy,'[^,]+',1,Level)) AS dummycol
5 FROM dummy_table
6 CONNECT BY level <= LENGTH(REGEXP_REPLACE(dummy,'[^,]+'))+1
7 /
DUMMYCOL
--------------
3862
3654
3828
SQL>
There are many other ways of achieving it. Read Split single comma delimited string into rows.
Update Regarding the duplicates when the column is used instead of a single string value. Saw the use of DBMS_RANDOM in the PRIOR clause to get rid of the cyclic loop here
Try the following,
SQL> WITH dummy_table AS
2 ( SELECT 1 rn, '3862,3654,3828' dummy FROM dual
3 UNION ALL
4 SELECT 2, '1234,5678' dummy FROM dual
5 )
6 SELECT trim(regexp_substr(dummy,'[^,]+',1,Level)) AS dummycol
7 FROM dummy_table
8 CONNECT BY LEVEL <= LENGTH(REGEXP_REPLACE(dummy,'[^,]+'))+1
9 AND prior rn = rn
10 AND PRIOR DBMS_RANDOM.VALUE IS NOT NULL
11 /
DUMMYCOL
--------------
3862
3654
3828
1234
5678
SQL>
Update 2
Another way,
SQL> WITH dummy_table AS
2 ( SELECT 1 rn, '3862,3654,3828' dummy FROM dual
3 UNION ALL
4 SELECT 2, '1234,5678,xyz' dummy FROM dual
5 )
6 SELECT trim(regexp_substr(t.dummy, '[^,]+', 1, levels.column_value)) AS dummycol
7 FROM dummy_table t,
8 TABLE(CAST(MULTISET
9 (SELECT LEVEL
10 FROM dual
11 CONNECT BY LEVEL <= LENGTH (regexp_replace(t.dummy, '[^,]+')) + 1
12 ) AS sys.OdciNumberList)) LEVELS
13 /
DUMMYCOL
--------------
3862
3654
3828
1234
5678
xyz
6 rows selected.
SQL>
Giving a PL/SQL example where parsing over a table with an ID and column name. This will parse and print out each ID and the parsed value which could then be inserted into a new table or used in some other way.
Input
Column_ID Column_Name
123 (3862,3654,3828)
Output
Column_ID Column_Name
123 3862
123 3654
123 3828
PL/SQL Code
declare
table_name1 varchar2(1000);
string_to_parse varchar2(2000); -- assign string to table name
string_length number := 0; -- string length for loop
string_value varchar2(2000); -- string value to store value in
column_id number;
begin
--some table in the format '123' as column_id, '(3862,3654,3828)' as column_name
--remove the parenthesis or other special characters if needed
update some_table t
set t.column_name = regexp_replace(t.column_name,'\(|\)','');
commit;
for i in (
select * from some_table
) loop
column_id := i.column_id; --assign the id of the colors
string_to_parse := i.column_name; -- assign string to be parsed
if string_to_parse is null then
--at this point insert into a new table, or do whatever else you need
dbms_output.put_line(column_id || ' ' || string_value);
else
--String to parse is the comma
string_to_parse := string_to_parse||',';
string_length := length(string_to_parse) - length(replace(string_to_parse,',',''));
-- Loop through string from parameter
for i in 1 .. string_length loop
-- [^,] matches any character except for the ,
select regexp_substr(string_to_parse,'[^,]+',1,i)
into string_value -- stores value into string_value
from dual; -- dual is a dummy table to work around
--at this point insert into a new table, or do whatever else you need
dbms_output.put_line(column_id || ' ' || string_value);
--clear out the string value
string_value := null;
end loop;
end if;
end loop;
end;

Handling date formatting in oracle for NULL and 0's

I am trying to parse a record into a table. The date in the
record is of type 0cyymmdd c -> century(0:19,1:20)
ex: if date is00900201 it should be converted as 1990-02-01(yyy-mm-dd)
To do this I am initially loading the data coming in record to a
varchar column and then formatting it using the following query:
UPDATE TABLE
DATE= CASE SUBSTR((DT_1),2,1)
WHEN '0' THEN TO_DATE('19' || SUBSTR(DT_1,3),'yyyy-mm-dd')
WHEN '1' THEN TO_DATE('20' || SUBSTR(DT_1,3),'yyyy-mm-dd')
ELSE NULL
END
In the table DT(DATE), DT_1(VARCHAR)
But the record need not have date always, it might also have either
blank spaces or 0's in that case this query fails.
Could anyone point me in the right direction?
You don't have to update all the rows. To handle the cases where the date value could be zeroes or spaces, you could add a filter condition using TRANSLATE function.
WHERE translate(column_name, '#0 ','#') IS NOT NULL
For example,
Setup
SQL> CREATE TABLE t(A VARCHAR2(8), b DATE);
Table created.
SQL> INSERT INTO t(A) VALUES('00900201');
1 row created.
SQL> INSERT INTO t(A) VALUES('01150820');
1 row created.
SQL> INSERT INTO t(A) VALUES(' ');
1 row created.
SQL> INSERT INTO t(A) VALUES('00000000');
1 row created.
SQL> COMMIT;
Commit complete.
SQL> SELECT * FROM t;
A B
-------- ---------
00900201
01150820
00000000
UPDATE statement
SQL> UPDATE t
2 SET b = CASE
3 WHEN SUBSTR(A, 2, 1) = '0'
4 THEN to_date('19'
5 ||SUBSTR(A, 3), 'YYYYMMDD')
6 WHEN SUBSTR(A, 2, 1) = '1'
7 THEN to_date('20'
8 ||SUBSTR(A, 3), 'YYYYMMDD')
9 ELSE NULL
10 END
11 WHERE translate(A, '#0 ','#') IS NOT NULL
12 /
2 rows updated.
Validation
SQL> SELECT * FROM t;
A B
-------- ---------
00900201 01-FEB-90
01150820 20-AUG-15
00000000
SQL>
So, it updated the required 2 rows having correct date values. Rest other rows it updated as NULL.
Small modifications to your code. These will work if dt1 field will have 0's or nulls also.
UPDATE TABLE a
set a.DATE_column= CASE
WHEN SUBSTR((DT_1),2,1)='0' THEN TO_DATE('19' || SUBSTR(DT_1,3),'yyyy-mm-dd')
WHEN SUBSTR((DT_1),2,1)=1 THEN TO_DATE('20' || SUBSTR(DT_1,3),'yyyy-mm-dd')
when (dt_1 = '0') or (dt_1 = null)
then null
ELSE NULL
END

Splitting comma separated values in Oracle

I have column in my database where the values are coming like the following:
3862,3654,3828
In dummy column any no. of comma separated values can come. I tried with following query but it is creating duplicate results.
select regexp_substr(dummy,'[^,]+',1,Level) as dummycol
from (select * from dummy_table)
connect by level <= length(REGEXP_REPLACE(dummy,'[^,]+'))+1
I am not understanding the problem. Can anyone can help?
Works perfectly for me -
SQL> WITH dummy_table AS(
2 SELECT '3862,3654,3828' dummy FROM dual
3 )
4 SELECT trim(regexp_substr(dummy,'[^,]+',1,Level)) AS dummycol
5 FROM dummy_table
6 CONNECT BY level <= LENGTH(REGEXP_REPLACE(dummy,'[^,]+'))+1
7 /
DUMMYCOL
--------------
3862
3654
3828
SQL>
There are many other ways of achieving it. Read Split single comma delimited string into rows.
Update Regarding the duplicates when the column is used instead of a single string value. Saw the use of DBMS_RANDOM in the PRIOR clause to get rid of the cyclic loop here
Try the following,
SQL> WITH dummy_table AS
2 ( SELECT 1 rn, '3862,3654,3828' dummy FROM dual
3 UNION ALL
4 SELECT 2, '1234,5678' dummy FROM dual
5 )
6 SELECT trim(regexp_substr(dummy,'[^,]+',1,Level)) AS dummycol
7 FROM dummy_table
8 CONNECT BY LEVEL <= LENGTH(REGEXP_REPLACE(dummy,'[^,]+'))+1
9 AND prior rn = rn
10 AND PRIOR DBMS_RANDOM.VALUE IS NOT NULL
11 /
DUMMYCOL
--------------
3862
3654
3828
1234
5678
SQL>
Update 2
Another way,
SQL> WITH dummy_table AS
2 ( SELECT 1 rn, '3862,3654,3828' dummy FROM dual
3 UNION ALL
4 SELECT 2, '1234,5678,xyz' dummy FROM dual
5 )
6 SELECT trim(regexp_substr(t.dummy, '[^,]+', 1, levels.column_value)) AS dummycol
7 FROM dummy_table t,
8 TABLE(CAST(MULTISET
9 (SELECT LEVEL
10 FROM dual
11 CONNECT BY LEVEL <= LENGTH (regexp_replace(t.dummy, '[^,]+')) + 1
12 ) AS sys.OdciNumberList)) LEVELS
13 /
DUMMYCOL
--------------
3862
3654
3828
1234
5678
xyz
6 rows selected.
SQL>
Giving a PL/SQL example where parsing over a table with an ID and column name. This will parse and print out each ID and the parsed value which could then be inserted into a new table or used in some other way.
Input
Column_ID Column_Name
123 (3862,3654,3828)
Output
Column_ID Column_Name
123 3862
123 3654
123 3828
PL/SQL Code
declare
table_name1 varchar2(1000);
string_to_parse varchar2(2000); -- assign string to table name
string_length number := 0; -- string length for loop
string_value varchar2(2000); -- string value to store value in
column_id number;
begin
--some table in the format '123' as column_id, '(3862,3654,3828)' as column_name
--remove the parenthesis or other special characters if needed
update some_table t
set t.column_name = regexp_replace(t.column_name,'\(|\)','');
commit;
for i in (
select * from some_table
) loop
column_id := i.column_id; --assign the id of the colors
string_to_parse := i.column_name; -- assign string to be parsed
if string_to_parse is null then
--at this point insert into a new table, or do whatever else you need
dbms_output.put_line(column_id || ' ' || string_value);
else
--String to parse is the comma
string_to_parse := string_to_parse||',';
string_length := length(string_to_parse) - length(replace(string_to_parse,',',''));
-- Loop through string from parameter
for i in 1 .. string_length loop
-- [^,] matches any character except for the ,
select regexp_substr(string_to_parse,'[^,]+',1,i)
into string_value -- stores value into string_value
from dual; -- dual is a dummy table to work around
--at this point insert into a new table, or do whatever else you need
dbms_output.put_line(column_id || ' ' || string_value);
--clear out the string value
string_value := null;
end loop;
end if;
end loop;
end;