Is it possible to update data inside a CLOB using SQL? - sql

I have a table having one clob column which has XML data in it.
Say I want to replace XYZ with ABC in the clob column.
Is it possible using sqlplus?

Why not try it ?
SQL> create table nnn(c1 clob);
Table created.
SQL> insert into nnn values ('text ABC end');
1 row created.
SQL> select * from nnn;
C1
-------------------------------------------------
text ABC end
SQL> update nnn set c1=replace(c1,'ABC','XYZ');
1 row updated.
SQL> select * from nnn;
C1
-------------------------------------------------
text XYZ end
SQL>

"i have new line in the column. any
advice?"
Newlines are characters; if you want to amend text which contains them you need to include them in the search string. You can do this using the CHR() which takes an ASCII value as an argument. The precise codes you need to include vary according to OS. Because I ran this example on MS Windows I needed to pass both linefeed (ASCII=10) and carriage return (ASCII=13).
SQL> select * from t42
2 /
TXT
--------------------------------------------------------------------------------
<ABC> ABCD
</ABC>
SQL> update t42 set txt=replace(txt,'ABCD'||chr(10)||chr(13), 'APC woz here')
2 /
1 row updated.
SQL> select * from t42
2 /
TXT
--------------------------------------------------------------------------------
<ABC> APC woz here </ABC>
SQL>
Incidentally, if you are storing XML text it might be worthwhile using the XMLType datatype for the column instead of CLOB. It comes with a lot of useful functionality.

Yes, it's possible with one REPLACE() function. Try:
update nnn set c1 = REPLACE(c1,'ABC>','XYZ>')

Related

How to compare similar data

I want to insert the data to PL-SQL.
But I need to check whether the table has similar Data.
If the table check has similar information, it cannot be added
exanple:
Insert Data : ABCD or ABCE
Table:
enter image description here
The Tabel Device has ABC,so it cannot be added.
How can I write this program?
You can use instr in plsql
example:
declare
x number;
begin
for i in (select distinct value from table)
loop
select count(1) into x
from table2
where instr(Device, i.value) > 0;
if (x = 0) then
insert into table2(Device) values(i.value);
end if;
commit;
end loop;
end;
Similar or the same data? That makes a huge difference. Because if you don't want the same data in your columns, you can just make the column unique. But if you want to check for similar data, welp, that's kind of hard to implement, hard to understand, and that just outright kills your performance...But if you still want to go that way, you can check out Jaro-Winkler Algorithm
Isi already mentioned the algorithm; here's an example of what you might be looking for.
Current table contents:
SQL> select * from test;
COL
-----
ABC
ABD
ABR
Here's how similar current values are to certain strings (ABCD, FDGH) you'd want to insert:
SQL> select t.col,
2 utl_match.jaro_winkler_similarity('ABCD', t.col) sim_abcd,
3 utl_match.jaro_winkler_similarity('FDGH', t.col) sim_fdgh
4 from test t;
COL SIM_ABCD SIM_FDGH
----- ---------- ----------
ABC 94 0
ABD 93 52
ABR 77 0
Now, it is up to you to decide which value will represent a limit and either insert a value into that table or not. Let's presume it is 90%. Then you'd
SQL> insert into test (col)
2 select '&&par_insert'
3 from dual
4 where 90 > (select max(utl_match.jaro_winkler_similarity('&&par_insert', a.col))
5 from test a
6 );
Enter value for par_insert: ABCD
0 rows created.
SQL>
Right; ABCD is similar to any of current values more than 90% and wasn't inserted.
How about FDGH?
SQL> undefine par_insert
SQL> /
Enter value for par_insert: FDGH
1 row created.
SQL> select * from test;
COL
-----
ABC
ABD
ABR
FDGH
SQL>
Yes, it was inserted.

REGEXP_REPLACE expression issue

I got some sql script below to remove word between words, but it will find last occurrence of my (/hide) instead of the first occurrence. Need help to get the output as expected. Thanks.
select regexp_replace('(hide)it(/hide)should be show(hide)my(/hide) text',
'^\(hide\).*\(/hide\)', '') "TESTING"
from dual;
I expect the output will be:
should be show text
but the actual output is:
text
If my data is in one of the column with datatype of clob. As currently i use below script to select. For example my table is testing_table with column of desc_str with data_type of clob which inside contain value '(hide)it(/hide)should be show(hide)my(/hide) text';
select trim(to_char(regexp_replace(desc_str,'^\(hide\).*\(/hide\)',''))) as desc
from testing_table
where OOE_FP_SS_ID = $id;
Based on your example:
SQL> with test (col) as
2 (select '(hide)it(/hide)should be show(hide)my(/hide) text' from dual)
3 select regexp_replace(col, '\(hide\)\w+\(/hide\)', '') result
4 from test;
RESULT
-------------------
should be show text
SQL>
[EDIT: CLOB]
You asked for a CLOB. Here's an example:
SQL> create table test (desc_str clob);
Table created.
SQL> insert into test values ('(hide)it(/hide)should be show(hide)my(/hide) text');
1 row created.
SQL> select regexp_replace(desc_str, '\(hide\)\w+\(/hide\)', '') result from test;
RESULT
--------------------------------------------------------------------------------
should be show text
SQL>
Another example:
SQL> with test (desc_str) as
2 (select '(hide)ItemId: 4334(/hide)|(hide)Description Item - SubType:(/hide) Name - Item|(irow)Price Value: MYR 1,668' from dual)
3 select regexp_replace(desc_str, '\(hide\).+?\(/hide\)', '') result from test;
^
RESULT | this question mark was missing
------------------------------------------
| Name - Item|(irow)Price Value: MYR 1,668
SQL>

Create Auto Sequence text and number in oracle 11g

How I do create column ID with value JASG1?
I am only find example like this :
select 'JASG'||to_char(mtj_id_seq.nextval) from talend_job
Although what you wrote probably works (if there's a sequence named MTJ_ID_SEQ, you have a privilege to select from it; the same goes for the TALEND_JOB table), I'd say that it isn't what you should use.
Here's why: I'll create a table and a sequence. Table will be pre-populated with some IDs (just to put something in there).
SQL> create sequence mtj_id_seq;
Sequence created.
SQL> create table talend_job as
2 select rownum id from dept;
Table created.
SQL> select * from talend_job;
ID
----------
1
2
3
4
OK; 4 rows so far. Now, run your SELECT:
SQL> select 'JASG'||to_char(mtj_id_seq.nextval) from talend_job;
'JASG'||TO_CHAR(MTJ_ID_SEQ.NEXTVAL)
--------------------------------------------
JASG1
JASG2
JASG3
JASG4
SQL> select 'JASG'||to_char(mtj_id_seq.nextval) from talend_job;
'JASG'||TO_CHAR(MTJ_ID_SEQ.NEXTVAL)
--------------------------------------------
JASG5
JASG6
JASG7
JASG8
SQL>
See? You didn't get only 1 JASGx value, but as many as number of rows in the TALEND_JOB table. If there was a million rows, you'd get a million JASGx rows as well.
Therefore, maybe you meant to use DUAL table instead? E.g.
SQL> select 'JASG'||to_char(mtj_id_seq.nextval) from dual;
'JASG'||TO_CHAR(MTJ_ID_SEQ.NEXTVAL)
--------------------------------------------
JASG9
SQL> select 'JASG'||to_char(mtj_id_seq.nextval) from dual;
'JASG'||TO_CHAR(MTJ_ID_SEQ.NEXTVAL)
--------------------------------------------
JASG10
SQL>
See? Only one value.
Also, notice that sequences will provide unique values, but you can't rely on them being gapless.
As you mentioned "how to create column ID" - one option is to use a trigger. Here's an example:
SQL> create table talend_job (id varchar2(20), name varchar2(20)
Table created.
SQL> create or replace trigger trg_bi_tj
2 before insert on talend_job
3 for each row
4 begin
5 :new.id := 'JASG' || mtj_id_seq.nextval;
6 end;
7 /
Trigger created.
Let's insert some names; IDs should be auto-populated by the trigger:
SQL> insert into talend_job (name) values ('littlefoot');
1 row created.
SQL> insert into talend_job (name) values ('Ishak');
1 row created.
SQL> select * From talend_job;
ID NAME
-------------------- --------------------
JASG11 littlefoot
JASG12 Ishak
SQL>
OK then; now you have some more info - read and think about it.
By the way, what is the "compiler-errors" tag used for? Did you write any code and it failed? Perhaps you'd want to share it with us.

Creating a sequence for a varchar2 field in Oracle

I want to create a sequence for this varchar. It would have been easier had it been a number instead of varchar. In that case, I could do
seq_no := seq_no + 1;
But what can I do when I want to store next value in column as A0000002, when the previous value was A0000001 (to increment the number in the next varchar rowby 1)?
This can be done by
to_char(seq_no,'FM0000000')
your example can be done by creating sequence in oracle
create sequence seq_no start with 1 increment by 1;
then
select 'A'||to_char(seq_no.nextval,'FM0000000') from dual;
Right now i have used in dual ..but place this
'A'||to_char(seq_no.nextval,'FM0000000')
in your required query ..this will create sequence as you mentioned
sqlfiddle
Sequences are purely numeric. However, you need a trigger anyway, so simply adapt such trigger to insert the desired prefix:
CREATE OR REPLACE TRIGGER FOO_TRG1
BEFORE INSERT
ON FOO
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
BEGIN
IF :NEW.FOO_ID IS NULL THEN
SELECT 'A' || TO_CHAR(FOO_SEQ1.NEXTVAL, 'FM0000000') INTO :NEW.FOO_ID FROM DUAL;
END IF;
END FOO_TRG1;
/
ALTER TRIGGER FOO_TRG1 ENABLE;
If you're able I'd actually use a virtual column as defined in the CREATE TABLE syntax. It makes it more easily extensible should the need arise.
Here's a working example.
SQL> create table tmp_test (
2 id number(7,0) primary key
3 , col1 number
4 , seq varchar2(8 char) generated always as (
5 'A' || to_char(id, 'FM0999999'))
6 );
Table created.
SQL>
SQL> create sequence tmp_test_seq;
Sequence created.
SQL>
SQL> create or replace trigger tmp_test_trigger
2 before insert on tmp_test
3 for each row
4 begin
5
6 :new.id := tmp_test_seq.nextval;
7 end;
8 /
Trigger created.
SQL> show errors
No errors.
SQL>
SQL> insert into tmp_test (col1)
2 values(1);
1 row created.
SQL>
SQL> select * from tmp_test;
ID COL1 SEQ
---------- ---------- --------------------------------
1 1 A0000001
Having said that; you would be better off if you did not do this unless you have an unbelievably pressing business need. There is little point to making life more difficult for yourself by prepending a constant value onto a number. As A will always be A it doesn't matter whether it's there or not.
If the format is always a letter followed by 7 digits you can do:
sequence = lpad(substr(sequence,2,7)+1,7,'0')

Oracle:Set default value for number column

How can we set default value for a number typed column has '00'?I tried this but it still saved it has '0',I need to do this.
//alter table table_name add column column1 default '00';
Please suggest a way for me.
You can store as number and when you retrieve do as
select column1,to_char(column2,'00') from mytable
SQL Fiddle Demo
It is not possible to store numbers like that - In a format you have described ('00'). You can store numbers as numbers (as values of numeric data type of course) and use to_char function or to_char function combined with lpad function to represent numbers in a format you like. Here is an example:
SQL> create table TB_SingleNumberColumn(
2 col number
3 )
4 /
Table created
SQL> insert into TB_SingleNumberColumn(Col) values(1);
1 row inserted
SQL> insert into TB_SingleNumberColumn(Col) values(5);
1 row inserted
SQL> insert into TB_SingleNumberColumn(Col) values(11);
1 row inserted
SQL> insert into TB_SingleNumberColumn(Col) values(111);
1 row inserted
SQL> commit;
Commit complete
-- The values as they are
SQL> select * from TB_SingleNumberColumn;
COL
----------
1
5
11
111
-- Values padded with zeros.
SQL> select to_char(col, '000') res
2 from TB_SingleNumberColumn;
RES
----
001
005
011
111
SQL> select lpad(to_char(col), 3, '0')
2 from TB_SingleNumberColumn
3 ;
LPAD(TO_CHAR(COL),3,'0')
------------------------
001
005
011
111