How to replace comma separated different values with a particular value - oracle

I've a string with the values - 'a','b','c','d,'e'. I need to convert each of the values to the text null - null,null,null,null,null. If there are 10 values in quotes and separated by comma, then 10 null will appear. I tried using REGEXP_REPLACE but failed to get the result.
declare
a varchar2(32767) := q'#'a','b','c'#';
c varchar2(32767);
begin
c := replace(REGEXP_REPLACE (a, <don't know what pattern should be here>, 'null'),'''');
dbms_output.put_line(c);
end;
/

There are many ways to do this. For example, you could use the regular expression '[^,]+' - which means any number (one or more) of consecutive non-comma characters. Then every occurrence of that pattern will be replaced with the replacement string (while the commas will stay in place).
declare
a varchar2(32767) := q'#'a','b','c'#';
c varchar2(32767);
begin
c := REGEXP_REPLACE (a, '[^,]+', 'null'); -- notice the regular expression
dbms_output.put_line(c);
end;
/
null,null,null
PL/SQL procedure successfully completed.

Related

Converting number into word using length PL/SQL

I am converting number into word with own code using length function.
Here is the code:
CREATE OR REPLACE FUNCTION num_to_words (NUM IN NUMBER)
RETURN VARCHAR2
IS
v_length NUMBER;
v_words VARCHAR2(100);
word_1 VARCHAR2(100);
BEGIN
word_1 := 'HUNDRED';
v_length := LENGTH(NUM);
IF v_length = 3
THEN v_words := SUBSTR(TO_CHAR(TO_DATE(NUM,'J'),'JSP'),1,3) ||' '|| word_1;
END IF;
RETURN(v_words);
END;
Problem is when I enter "100", it successfully converts into "ONE HUNDRED".
How can I implement the code for converting "101" into "ONE HUNDRED ONE".
The JSP conversion will do that for you; you don't need to extract the first digit, or supply the 'hundred' text yourself:
IF v_length <= 3 THEN
v_words := TO_CHAR(TO_DATE(NUM,'J'),'JSP');
END IF;
If you pass in 101 the result is ONE HUNDRED ONE. And because I changed = 3 to <= 3 it will work for any 1, 2 or 3-digit value, so passing in 11 returns ELEVEN.
For longer values you might be looking for something like this, which breaks the number down into groups and converts each group onto words plus the corresponding scale (e.g. 'million'). If you want non-standard grouping then it's a bit more involved, but there's a recent example for lakh here.

Identifier Too long Exception

I have a query of more than 4000 characters which is formed from different varaibles having varchar2 datatype of size 2000
example
query1 varcahr2(2000):='string 1';
query2 varchar2(2000):='string2';
query3 varcahr2 (2000):= string3';
I have declared a variable query varchar2(32000)
query := query1|| query2 || query3 ;
create table t (
id number,
querystring varchar2(4000));
I tried to get the first 4000 characters from the query variable it is not working. Can anyone please help?
declare
querystring1 varchar2(2000) := "string1";
querystring2 varchar2(2000) := "string2";
l_query varchar2(32000);
query varchar2(4000);
begin
l_query := querystring1 || querystring2 ;
select substr(l_query,1,4000) into query from dual;
insert into lib_query_table values('1',query);
end;
You are using double quotes around your query string literals, instead of single quotes. That makes Oracle interpret them as identifier names - so as soon as your literal is more than 30 characters long you'll get that exception. With shorter strings you'd still get an error, but something like 'unknown identifier'.
Replace your double quotes with single ones:
declare
querystring1 varchar2(2000) := 'string1';
querystring2 varchar2(2000) := 'string2';
l_query varchar2(32000);
query varchar2(4000);
begin
l_query := querystring1 || querystring2 ;
select substr(l_query,1,4000) into query from dual;
insert into lib_query_table values (1, query);
end;
You don't need the query from dual, you can do:
query := substr(l_query, 1, 4000);
You could skip that variable and do:
insert into lib_query_table (id, querystring)
values (1, substr(l_query, 1, 4000);
or even:
insert into lib_query_table (id, querystring)
values (1, substr(querystring1 || querystring2, 1, 4000));
As your ID column is a number you should not insert the value for that as a string '1' - just use a number. You probably want a sequence to set that value, eventually.
Also not directly related, but when you're concatenating parts of a query together, say where one string is the select list and the second is the from clause etc., make sure you have whitespace at the end of each part (or the start of the next part), or the combined string might end up invalid.
Variable-length character string having maximum length size bytes or characters. You must specify size for VARCHAR2. Minimum size is 1 byte or 1 character. Maximum size is: 32767 bytes or characters if MAX_STRING_SIZE = EXTENDED 4000 bytes or characters .
You can look CLOB data type

PL/SQL String Validation

I am trying to write a script that prompts for a input and it should validate if the given input has 19 characters;the first 3 characters must be 'ABC' followed by 16 characters(combination of alphabets and numbers)...
def mch_id='&1'
declare
chk_var varchar2(200) := '&mch_id';
begin
IF chk_var like'ABC_____________' then
dbms_output.put_line('correct');
else
dbms_output.put_line('incorrect');
end if;
end;
Expected Output :
ABC5678GVTC438755RW43 - correct
ADSE4NJ8GGFT5FVNOKNHY - incorrect
Your comparison string is only 16 characters long, ABC and 13 underscores. You need 16 underscores to follow ABC according to your specification.
EDIT: As HepC notes below, even after fixing the number of underscores, you may still get incorrect answers. This is because the underscore stands for ANY character, not only for alpha or numeric.
Try this instead:
... if regexp_like(chk_var, '^ABC[[:alnum:]]{16}$') then...
This evaluates as TRUE if and only if chk_var matches
from the beginning of the string (the ^ marker)
the letters A, B, C in order
any alpha or numeric character (the outer [...] means any single character in the list provided within [...]; inside it, [:alnum:] is shorthand for any alpha or numeric character)
exactly 16 occurrences of "a single alnum character" (the 16 characters may be different from each other) (the {16} marker)
and the end of the string right after that (the $ marker).
Sample SQL*Plus session (screenshot):
SQL> set serveroutput on
SQL> define mch_id = 'ABC1234567812345678'
SQL> declare
2 chk_var varchar2(200) := '&mch_id';
3 begin
4 if regexp_like(chk_var, '^ABC[[:alnum:]]{16}$') then
5 dbms_output.put_line('correct');
6 else
7 dbms_output.put_line('incorrect');
8 end if;
9 end;
10 /
old 2: chk_var varchar2(200) := '&mch_id';
new 2: chk_var varchar2(200) := 'ABC1234567812345678';
correct
PL/SQL procedure successfully completed.
SQL> define mch_id = 'ABC123456781234%%%%'
SQL> /
old 2: chk_var varchar2(200) := '&mch_id';
new 2: chk_var varchar2(200) := 'ABC123456781234%%%%';
incorrect
PL/SQL procedure successfully completed.

Array not working correctly

I have a function that takes in 1 parameter, abc(parameter1 IN varchar2)
In the parameter I will be taking in a string that is comma delimited:
E.g Abc('1,2,a')
Type vartype is varray(10) of varchar2(50);
X1 vartype:= vartype (parameter1);
For X in X1.count loop
Dbms_output.put_line(x1(X));
End loop;
The DBMS Output gives me
1,2,a
Instead of
1
2
A
Is there anyway I can solve this?
For my understanding your function parameter will be single value.
If you are mentioned varray, you should give format like ('1','2','a','b')
For example :-
declare
Type vartype is varray(10) of varchar2(50);
X1 vartype:=vartype ('1','2','a','b');
begin
For X in 1..X1.count loop
Dbms_output.put_line(x1(x));
End loop;
end;
/
Above query will help you to understand concepts of Varray
You are passing a varchar2 variable to the varray and it's considered the first paramter; so your array contains only one element (the content of parameter1). You must split the string into substring before passing to the varray.
Here is an extract from Oracle documentation
DECLARE TYPE ProjectList IS VARRAY(50) OF VARCHAR2(16);
accounting_projects ProjectList;
BEGIN
accounting_projects := ProjectList('Expense Report', 'Outsourcing', 'Auditing');
END;
For splitting a string into substring you can check some solutions here

Remove a character from a given position on Oracle

Is there anyway to remove a character from a given position?
Let's say my word is:
PANCAKES
And I want to remove the 2nd letter (in this case, 'A'), so i want PNCAKES as my return.
Translate doesnt work for this.
Replace doesnt work for this.
Regex is damn complicated...
Ideas?
Example:
SUBSTR('PANCAKES', 0, INSTR('PANCAKES', 'A', 1, 1)-1) || SUBSTR('PANCAKES', INSTR('PANCAKES', 'A', 1, 1)+1)
I don't have an Oracle instance to test with, might have to tweak the -1/+1 to get the position correct.
References:
INSTR
SUBSTR
Concatenating using pipes "||"
You should strongly consider using regexp_replace. It is shorter and not so complicated as it seems at a first glance:
SELECT REGEXP_REPLACE( S, '^(.{1}).', '\1' )
FROM (
SELECT 'PANCAKES'
FROM DUAL
)
The pattern ^(.{1}). searches from the start of the string ( denoted by ^ ) for exactly one ( .{1} ) of printable or uprintable characters followed by again just one of those characters ( . ). The "exact" part is closed in parenthesis so it can be referenced as match group by it's number in the third function's argument ( \1 ). So the whole substring matched by regexp is 'PA', but we reference only 'P'. The rest of the string remains untouched. So the result is 'PNCAKES'.
If you want to remove N-th character from the string just replace number 'one' in the pattern (used to remove second character) with the value of N-1.
It's good for programmer or any kind of IT specialist to get familiar with regular expressions as it gives him or her a lot of power to work with text entries.
Or use a custom made SplitAtPos function using SUBSTR. Advantage is that it still works on Oracle v9.
set serveroutput on
declare
s1 varchar2(1000);
s2 varchar2(1000);
function SplitAtPos(s in out varchar2, idx pls_integer)
return varchar2
is
s2 varchar2(1000);
begin
s2:=substr(s,1,idx-1);
s:=substr(s,idx,length(s)-idx+1);
return s2;
end;
begin
s1:='Test123';
s2:=SplitAtPos(s1,1);
dbms_output.put_line('s1='||s1||' s2='||s2);
s1:='Test123';
s2:=SplitAtPos(s1,5);
dbms_output.put_line('s1='||s1||' s2='||s2);
s1:='Test123';
s2:=SplitAtPos(s1,7);
dbms_output.put_line('s1='||s1||' s2='||s2);
s1:='Test123';
s2:=SplitAtPos(s1,8);
dbms_output.put_line('s1='||s1||' s2='||s2);
s1:='Test123';
s2:=SplitAtPos(s1,0);
dbms_output.put_line('s1='||s1||' s2='||s2);
end;
yes REPLACE and SUBSTR in the proper order will do the trick.
the end result should be a concatenation of the SUBSTR before the removed char to the SUBSTR after the char.
if the entire column is only one word, then you can just do an update, if the word is in another string, then you could use REPLACE as a wrapper.
You can use something like this in pl/SQL
DECLARE
v_open NUMBER;
v_string1 VARCHAR2(10);
v_string2 VARCHAR2(10);
v_word VARCHAR2(10);
BEGIN
v_open := INSTR('PANCAKES' ,'A',1);
v_string1 := SUBSTR('PANCAKES' ,1, 1);
v_string2 := SUBSTR('PANCAKES' ,v_open+1);
v_word := v_string1||v_string2;
END;

Resources