Replacing column value which has special characters - sql

I have a table which has column and is inserted with data and in the data there are some characters for example
output should be like this
column name :Name
value 1: andrew-jr
value 2 :john-doctor
but I am getting it as
Name
andrewâ€jr
johnâ€doctor
The - is getting replaced with †character

Your string has CHR(226) and CHR(128).
You could use TRANSLATE or REPLACE.
select TRANSLATE ( 'â€', CHR(226)||CHR(128), '-') FROM DUAL;
yields - ( Tested in SQL developer )
So, to update the column ( check carefully before doing this), use
UPDATE yourtable
SET
columnname = translate(columnname,CHR(226)
|| CHR(128),'-')
WHERE
columnname LIKE '%'
|| CHR(226)
|| CHR(128)
|| '%';
To get a complete list of all characters and CHR values, use any of these.
SELECT
level i,
chr(level) str
FROM
dual
CONNECT BY
level <= 255;
OR
SET SERVEROUTPUT ON
BEGIN
FOR i IN 1..255 LOOP
dbms_output.put_line(chr(i)
|| ' == '
|| i);
END LOOP;
END;
/

Related

How do I add a value to a field without erasing and repeating?

So that's what I have. For example, a field contains six letters:
A, B, C, D, E, F
Ok. Now I want to update this field and add the letter G. I can use this script:
declare
v_c pls_integer;
v_s varchar(7) := 'LETTERS';
begin
select 1 into v_c from some_table where lower(some_column_name) = lower(v_s);
if (v_c = 1) then
execute immediate 'update some_table set values = ''A,B,C,D,E,F,G''
where lower(some_column_name) = lower('''||v_s||''')';
commit;
end if;
end;
/
But I need to check. This field may already contain some letters. Perhaps this letter is already in this list. For example, the letter C. If the letter already exists, then don't add it. If there is no such letter, just add it to the end (separated by commas). How can I do this?
I think that you just want another condition in the where clause:
where ',' || values || ',' not like '%,' || v_s || ',%'
The easiest way is to just append it to the list of existing letters.
Setup
CREATE TABLE test_letters
(
letters VARCHAR2 (50)
);
insert into test_letters
SELECT 'A, B, C, D' AS letters FROM DUAL
UNION ALL
SELECT 'A, B, C, D, E, F' AS letters FROM DUAL;
Update
UPDATE test_letters
SET letters = letters || ', G'
WHERE letters not like '%G%';
Another option is the INSTR function, which may perform better than LIKE or Reg exp.
update test_letters
set letters = letters || ', G'
where instr(letters,'G') = 0;

regexp_substr for getting correct result

I was trying to use regexp_substr to get each correct column name from a column list string.
The query is like:
select regexp_substr(v_keep, '(^|[(,) ]*)' || r.column_name || '($|[(,) ]+)', 1, 1, 'i')
from dual;
But the result is not correct.
The v_keep can be any column name list like abc, abc_abc, abc1 or (abc, abc_abc, abc1).
The r.column_name can be like abc or ab.
- If the input v_keep is (abc, abc_abc, abc1) and the r.column_name is
ab, it will return null.
- If the input v_keep is (abc, abc_abc, abc1) and the r.column_name is
abc, it will return the column name just abc.
Can anyone help me to fix it by just modify the pattern inside the regexp_substr ?
Why not just use a case and like?
select (case when replace(replace(v_keep, '(', ','), '(', ',')) like '%,' || r.column_name || ',%'
then r.column_name
end)
I don't recommend storing lists in a comma-delimited string, but if you are, this is one way to identify individual elements of the list.
It's pretty simple, you just need to add a subexpression so you can pull out the part of the string you want. (A subexpression is a section of the regexp in parentheses.) In this case the last argument is 2, because you want the part of the match that corresponds to the second group of parentheses.
regexp_substr(v_keep, '(^|[(,) ]*)(' || r.column_name || ')($|[(,) ]+)', 1, 1, 'i', 2)
Gordon's solution will have better performance, though.
Edit: working example -
with testdata as (select '(abc, abc_abc, abc1)' as v_keep, 'abc' as column_name from dual)
select regexp_substr(v_keep, '(^|[(,) ]*)(' || r.column_name || ')($|[(,) ]+)', 1, 1, 'i', 2)
from testdata r;
Since this is PL/SQL code to see if a value is in a string, try this which avoids the overhead of hitting the database, and calling REGEXP. Just keep it straight SQL. I hate the nested REPLACE calls but I was trying to avoid using REGEXP_REPLACE although it could be done in one call if you did use it.
set serveroutput on;
set feedback off;
declare
v_keep varchar2(50) := '(abc, abc_abc, abc1)';
compare varchar2(10) := 'abc_';
begin
if instr(',' || replace(replace(replace(v_keep, ' '), '('), ')') || ',', ',' || compare || ',') > 0 then
dbms_output.put_line('Column ''' || compare ||''' IS in the keep list');
else
dbms_output.put_line('Column ''' || compare ||''' IS NOT in the keep list');
end if;
end;

I want to insert one billion records in the oracle database

I have to insert one billion record in oracle database table.
I have 2 column .
One column is a seqence number which follows till 1,000,000,000
Second column is a varchar2 field ... and it is in the format of abc~122~373~7777777~5367
. That is first column must contain 3 random characters followed by '~' then 3 random number followed by '~' then again 3 random number followed by '~' then followed by 7 random number followed by '~' and finally 4 random number followed by '~'.
And I need all records to be unique.
create or replace function fn RETURN VARCHAR2 IS
label varchar2(24) := '';
BEGIN
-- abc~122~373~7777777~5367
select
chr(97 + floor(dbms_random.value*26)) || chr(97 + floor(dbms_random.value*26)) || chr(97 + floor(dbms_random.value*26))|| '~'
|| rpad(floor(dbms_random.value*123),3, '9') || '~'
|| rpad(floor(dbms_random.value*123),3, '8') || '~'
|| rpad(floor(dbms_random.value*1234567),7, '6') || '~'
|| rpad(floor(dbms_random.value*1234),4, '4') into label
from dual ;
RETURN label;
END;
and you could create a table by invoking it n times as below.
create table testtable as select fn from dual connect by level <= 1000000000;

Selecting individual values from csv format in oracle pl sql

I have the following value in a column in Oracle db ('abc', 'xyz')
I want to extract the values separately like abc, xyz by removing ' and (). Is there a way to do it using INSTR and SUBSTR functions?
Thanks
Use this query:
with sample as (select '(''abc'', ''xyz'')' text from dual)
select substr(text,instr(text,'''',1,1) + 1,instr(text,'''',1,2) - instr(text,'''',1,1) - 1),
substr(text,instr(text,'''',1,3) + 1,instr(text,'''',1,4) - instr(text,'''',1,3) - 1)
from sample;
It would help to know what you want to do with the data once parsed. How it could be handled in SQL vs PL/SQL to achieve your requirement could be very different.
That said, here's one way to strip surrounding parens and remove single quotes at the same time during the select using the powerful regexp_replace(source_string, pattern_string, replace_string) :
WITH qry AS (SELECT '(' || '''abc''' || ',' || '''xyz''' || ')' orig_string
FROM dual
)
SELECT regexp_replace(orig_string, '[()'']', '' ) clean_string
FROM qry;
The regexp_replace pattern_string says to match a character class (defind by opening and closing square brackets) containing a left paren or a right paren or a single quote (quoted so Oracle sees it) and the replace_string replaces it with nothing.
Then, to parse the values remaining here's an example from by bag of tricks I got somewhere and tweaked for this case:
set serveroutput on
DECLARE
-- Build a string in the format "('abc','xyz')"
orig_string varchar2(20) := '(' || '''abc''' || ',' || '''xyz''' || ')';
CURSOR cur IS
WITH qry AS (SELECT regexp_replace(orig_string, '[()'']','' ) clean_string
FROM dual
)
SELECT regexp_substr(clean_string, '[^,]+', 1, ROWNUM) element
FROM qry
CONNECT BY LEVEL <= LENGTH(regexp_replace (clean_string, '[^,]+')) + 1;
BEGIN
FOR rec IN cur LOOP
dbms_output.put_line('Element:' || rec.element);
END LOOP;
END;
It basically loops through the elements and prints them. I'm sure you can adapt this to your situation.

Concatenate string in Oracle SQL? (wm-concat)

I've got some SQL that I'd like to format correctly for a mailout (generated directly from SQL - don't ask!). The code is as follows:
SELECT wm_concat('<br>• ' || FIELD1 || ' ' || FIELD2 || ' : ' || FIELD 3 || ' text') AS "Team"
Okay, so this kinda works - but it places a comma at the end of each line. Silly question, and possibly quite trivial, but is there anyway at all to remove the comma please? I think it's being added by the wm_concat function
Thanks
Yes the WM_CONCAT function puts a comma between each value it concatenates.
If there are no commas in your data you could do this:
SELECT replace (wm_concat('<br>• ' || FIELD1 || ' ' || FIELD2 || ' : '
|| FIELD 3 || ' text'),
',', null) AS "Team"
If you are on 11G you can use the new LISTAGG function instead:
SELECT LISTAGG ('<br>• ' || FIELD1 || ' ' || FIELD2 || ' : '
|| FIELD 3 || ' text')
WITHIN GROUP (ORDER BY <something>) AS "Team"
That will produce a result without commas.
Just trim the string for trailing commas:
RTRIM( wm_concat(...), ',' )
Oracle 10g provides a very convenient function wm_concat used to solve line reclassified demand, very easy to use this function, but the function provides only ',' this kind of delimiter.
In fact, as long as some simple conversion you can use other delimiters separated, the first thought is replace function
with t as( select 'a' x from dual union select 'b' from dual )
select replace(wm_concat(x),',','-') from t;
But taking into account the string itself may contain ',' character, use the above SQL will lead to erroneous results, but also made some changes to the above SQL.
with t as( select 'a' x from dual union select 'b' y from dual)
select substr(replace(wm_concat('%'||x),',%','-'),2) from t;
In the above SQL by a '%' as a separator, and then replace the '%' to remove the error. The program assumes that the string does not exist within the '%' string to replace the '%' in the SQL can also use other special characters.
Source: http://www.databaseskill.com/3400944/
You can create your own aggregate functions in Oracle and use those to aggregate strings.
Or use the StrAgg function written by Tom Kyte: http://www.sqlsnippets.com/en/topic-11591.html
SELECT StrAgg('<br>• ' || FIELD1 || ' ' || FIELD2 || ' : ' || FIELD 3 || ' text') AS "Team"
FROM Abc