SQL ORACLE using %VALUE% - sql

Hi because of technical limitation of a Framework I need another way to do a smiliar query without using single quotes
--> current
Select Json_Value(json, '$.bankReference') From R_O where json like '%12345%';
--> Need a Valid query without single quotes which is doing exactly the same thing, maybe a function or something.
Select Json_Value(json, '$.bankReference') From R_O where json like %12345%;

A similar alternative, but a little bit more dynamic
Demo
SQL> create table t1 ( c1 varchar2(10) ) ;
Table created.
SQL> insert into t1 values ( 'A12345B' );
1 row created.
SQL> insert into t1 values ( 'A12345C' );
1 row created.
SQL> insert into t1 values ( 'A12345D' );
1 row created.
SQL> insert into t1 values ( 'A12399B' );
1 row created.
SQL> insert into t1 values ( 'A13299B' );
1 row created.
SQL> insert into t1 values ( 'A21399B' );
1 row created.
SQL> commit ;
Commit complete.
SQL> select * from t1 ;
C1
----------
A12345B
A12345C
A12345D
A12399B
A13299B
A21399B
6 rows selected.
Now let's create a function that admits two parameters:
The column we want to check
The value we want to apply the % ( I am guessing that is always a number ). If the value contains any string, it won't work.
Function
SQL> create or replace function p_chk_json(p_text varchar2, p_val number)
return integer is
begin
if p_text like '%'||p_val||'%' then
return 1;
else
return 0;
end if;
end;
/
Function created.
Then test it for 12345 or 99
SQL> select * from t1 where p_chk_json(c1 , 12345) = 1;
C1
----------
A12345B
A12345C
A12345D
SQL> select * from t1 where p_chk_json(c1 , 99 ) = 1 ;
C1
----------
A12399B
A13299B
A21399B

In Oracle you can write a function something like that:
create or replace function test1(p_text varchar2)
return integer is
begin
if p_text like '%12345%' then
return 1;
else
return 0;
end if;
end test1;
Your modified SQL statement will be:
Select Json_Value(json, '$.bankReference') From R_O where test1(json) = 1;

Related

Oracle - Adding NOT NULL constraint to a currently nullable column

I have a handful of numeric fields that are currently nullable. I want to add a NOT NULL constraint to these fields and have the default value now set to 0.
Data gets pushed in to this table on a schedule. There is nothing being pushed into these fields, and they're nullable, so these certain fields are all being set to null. This is causing some trouble when we're trying to do math with these fields.
If I first run updates on these fields to set all of the current nulls to zeros, should I have any issues adding a NOT NULL with default 0 constraint on these currently nullable fields? Is there anything I should look out for?
Thanks
edit:
SET SERVEROUTPUT ON
DECLARE
P_PROJECT_NUM VARCHAR2(200);
P_FISCAL_YEAR VARCHAR2(200);
P_RESP_CENTER VARCHAR2(200);
FIELD1 INTEGER;
FIELD2 INTEGER;
FIELD3 INTEGER;
BEGIN
P_PROJECT_NUM := '123456';
P_FISCAL_YEAR := '2019_2020';
P_RESP_CENTER := '123A';
FIELD1 := 0;
FIELD2 := 0;
FIELD3 := 0;
FMS_EXTRACT.LOAD_TEMPLATE(
P_PROJECT_NUM => P_PROJECT_NUM,
P_FISCAL_YEAR => P_FISCAL_YEAR,
P_RESP_CENTER => P_RESP_CENTER,
FIELD1 => FIELD1,
FIELD2 => FIELD2,
FIELD3 => FIELD3
);
COMMIT;
You can do it like this
Add the default clause to the columns
Update the null values to 0
Add the constraint NOT NULL
My example:
SQL> create table t ( c1 number , c2 number );
Table created.
SQL> insert into t values ( 1 , null ) ;
1 row created.
SQL> insert into t values ( null , 1 ) ;
1 row created.
SQL> select * from t ;
C1 C2
---------- ----------
1
1
SQL> alter table t modify c1 number default 0 ;
Table altered.
SQL> alter table t modify c2 number default 0 ;
Table altered.
SQL> update t set c1 = 0 where c1 is null ;
1 row updated.
SQL> update t set c2 = 0 where c2 is null ;
1 row updated.
SQL> commit ;
Commit complete.
SQL> alter table t modify c1 number not null ;
Table altered.
SQL> alter table t modify c2 number not null ;
Table altered.
SQL> insert into t ( c1 ) values ( 2 ) ;
1 row created.
SQL> select * from t ;
C1 C2
---------- ----------
1 0
0 1
2 0
This is too long for a comment. I don't think you want a NOT NULL constraint. That would result in your inserts failing if any of the NOT NULL columns are NULL.
The simplest solution is to not change the data at all. After all, NULL appears to be a valid value, if that is how the data is coming in. Just use COALESCE() in your logic:
select coalesce(x, 0) + coalesce(y, 0)
You can encompass this logic in a view or in generated columns:
alter table t add x_notnull generated always as (coalesce(x, 0));
If you want to prevent rows coming in with NULL values, then you can filter them out in your data important process. You don't provide details, so I can't make any suggestions.
You can add a default value. For instance:
alter table modify y default 0;
Then subsequent inserts where the value is missing will be replaced by the default value. However, explicit NULL values will not be affected.
Finally, you can add a NOT NULL constraint -- after removing all current NULL values.
Here is a db<>fiddle showing some examples of the above.

Create procedure for inserting the records, if exception, procedure needs start from exception line

I need to write the procedure for inserting the records in to multiple tables, for example I have 3 table,
CREATE TABLE SOURCE
(
SORT_CODE NUMBER,
FLAG CHAR(1)
);
INSERT INTO SOURCE VALUES(605096,5);
INSERT INTO SOURCE VALUES(605097,5);
INSERT INTO SOURCE VALUES(605098,5);
INSERT INTO SOURCE VALUES(605099,5);
INSERT INTO SOURCE VALUES(605100,5);
INSERT INTO SOURCE VALUES(605101,6);
INSERT INTO SOURCE VALUES(605102,6);
INSERT INTO SOURCE VALUES(605103,6);
INSERT INTO SOURCE VALUES(605104,6);
INSERT INTO SOURCE VALUES(605105,6);
SQL> SELECT * FROM SOURCE;
SORT_CODE F
---------- -
605096 5
605097 5
605098 5
605099 5
605100 5
605101 6
605102 6
605103 6
605104 6
605105 6
10 rows selected.
CREATE TABLE TARGET
(
SORT_CODE NUMBER,
TARGET_SORT_CODE NUMBER
);
Table created.
INSERT 5 VALUES
INSERT INTO TARGET VALUES(605101,189873);
INSERT INTO TARGET VALUES(605102,189874);
INSERT INTO TARGET VALUES(605103,189875);
INSERT INTO TARGET VALUES(605104,189876);
INSERT INTO TARGET VALUES(605105,'');
SELECT * FROM TARGET;
SORT_CODE TARGET_SORT_CODE
---------- ----------------
605101 189873
605102 189874
605103 189875
605104 189876
605105
CREATE TABLE NEWID
(
SORT_CODE NUMBER,
ID_SCODE NUMBER
);
Table created.
INSERT 2 VALUES
INSERT INTO TARGET VALUES(605103,189875);
INSERT INTO TARGET VALUES(605104,189876);
SELECT * FROM NEWID;
SORT_CODE ID_SCODE
---------- ----------------
605103 189875
605104 189876
Creating intermediate tables with existing table's structure.
CREATE TABLE SOURCE_TEMP AS (SELECT * FROM SOURCE WHERE 1=2);
CREATE TABLE TARGET_TEMP AS (SELECT * FROM TARGET WHERE 1=2);
CREATE TABLE NEWID_TEMP AS (SELECT * FROM NEWID WHERE 1=2);
My Procedure for inserting the records
CREATE OR REPLACE PROCEDURE insert_sql
is
BEGIN
DELETE FROM SOURCE_TEMP;
INSERT INTO SOURCE_TEMP SELECT * FROM SOURCE; --insert query 1
DELETE FROM TARGET_TEMP;
INSERT INTO TARGET_TEMP SELECT * FROM TARGET; --insert query 2
--due to some network issue or table error this procedure GOT EXEPCTION here and above insert query 2(TARGET_TEMP) and below --insert query 3(NEWID_TEMP) is not inserted the values or not executed procedure is came out from this line.
DELETE FROM NEWID_TEMP;
INSERT INTO NEWID_TEMP SELECT * FROM NEWID; --insert query 3
EXCEPTION
WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('ERROR');
END;
Point 1: The above procedure is executed only one insert query 1 SOURCE_TEMP is got the values.
Point 1: TARGET_TEMP and NEWID_TEMP is not inserted the values or not execute.
My question: can I re-execute this procedure with starting point of '--insert query 2' line?
because I am inserting the 100 tables records in new tables, if 50 tables are inserted the values during this time if I am getting any error in the proc execution, remaining 50 tables needs to insert the values, for I don't wish to delete the previous 50 tables inserted the values it will be the time consuming activity. Any save point or boolean concepts is there for this type of issue in ORACLE (which is available in java and unix). if yes how to use this function?
CREATE OR REPLACE PROCEDURE insert_sql
is
v_new_rec_count int:=0;
BEGIN
select count(*)
into v_new_rec_count
from (
select * FROM SOURCE
minus
select * FROM SOURCE_TEMP
) ;
If v_new_rec_count >0 then
INSERT INTO SOURCE_TEMP SELECT * FROM SOURCE; --insert query 1
Commit;--permanently save the records in table and it wont be rolledback after - -- any subsequent failure.
v_new_rec_count :=0;
end if;
select count(*)
into v_new_rec_count
from (
select * FROM TARGET
minus
select * FROM TARGET_TEMP
) ;
If v_new_rec_count >0 then
INSERT INTO TARGET_TEMP SELECT * FROM TARGET; --insert query 2
Commit;--permanently save the records in table and it wont be rolledback after - -- any subsequent failure.
v_new_rec_count :=0;
end if;
select count(*)
into v_new_rec_count
from (
select * FROM NEWID
minus
select * FROM NEWID_TEMP
) ;
If v_new_rec_count >0 then
INSERT INTO NEWID_TEMP SELECT * FROM NEWID; --insert query 2
Commit;--permanently save the records in table and it wont be rolledback after - -- any subsequent failure.
v_new_rec_count :=0;
end if;
EXCEPTION
WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('ERROR');
END;
CREATE OR REPLACE PROCEDURE insert_sql
IS
x int;
FLG FLAG.FLAG%type;
BEGIN
dbms_output.enable;
SELECT FLAG INTO FLG FROM FLAG;
if FLG='PASS01' then
DBMS_OUTPUT.PUT_LINE('PASS01');
DELETE FROM SOURCE_TEMP;
DBMS_OUTPUT.PUT_LINE('SOURCE_TEMP-DELETED');
INSERT INTO SOURCE_TEMP SELECT * FROM SOURCE;
DBMS_OUTPUT.PUT_LINE('SOURCE_TEMP-INSERTED');
UPDATE FLAG SET FLAG='PASS02';
DBMS_OUTPUT.PUT_LINE('PASS02-updated');
SELECT FLAG INTO FLG FROM FLAG;
DBMS_OUTPUT.PUT_LINE('PASS02-SELECT');
COMMIT;
end if;
if FLG='PASS02' then
DBMS_OUTPUT.PUT_LINE('PASS02');
DELETE FROM TARGET_TEMP;
DBMS_OUTPUT.PUT_LINE('TARGET_TEMP-DELETED');
INSERT INTO TARGET_TEMP SELECT * FROM TARGET;
DBMS_OUTPUT.PUT_LINE('TARGET_TEMP-INSERTEDD');
UPDATE FLAG SET FLAG='PASS03';
DBMS_OUTPUT.PUT_LINE('PASS03-updated');
SELECT FLAG INTO FLG FROM FLAG;
DBMS_OUTPUT.PUT_LINE('PASS03-FLG');
COMMIT;
end if;
--x :=1/0;
if FLG='PASS03' then
DBMS_OUTPUT.PUT_LINE('PASS03');
DELETE FROM NEWID_TEMP;
DBMS_OUTPUT.PUT_LINE('NEWID_TEMP-DELETED');
INSERT INTO NEWID_TEMP SELECT * FROM NEWID;
DBMS_OUTPUT.PUT_LINE('NEWID_TEMP-INSERTEDD');
UPDATE FLAG SET FLAG='PASS01';
DBMS_OUTPUT.PUT_LINE('PASS01-updated');
SELECT FLAG INTO FLG FROM FLAG;
DBMS_OUTPUT.PUT_LINE('PASS01-FLG');
COMMIT;
end if;
EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE('NO_DATA_FOUND!');
WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Error Message: !'|| SQLERRM ||' Sql Code: ' || SQLCODE);
END;
CREATE OR REPLACE PROCEDURE insert_sql
is
v_new_rec_count int:=0;
CURSOR cur_src
IS
SELECT * FROM SOURCE ;
TYPE cur_src_typ IS TABLE OF cur_src%ROWTYPE;
cur_src_tbl cur_src_typ;
CURSOR cur_newid
IS
SELECT * FROM newid ;
TYPE cur_newid_typ IS TABLE OF cur_src%ROWTYPE;
cur_newid_tbl cur_newid_typ;
CURSOR cur_target
IS
SELECT * FROM target ;
TYPE cur_target_typ IS TABLE OF cur_src%ROWTYPE;
cur_target_tbl cur_target_typ;
BEGIN
cur_src_tbl :=cur_src_tbl();
cur_newid_tbl :=cur_newid_tbl();
cur_target_tbl :=cur_target_tbl();
OPEN cur_src;
LOOP
FETCH cur_src BULK COLLECT INTO cur_src_tbl LIMIT 500;
EXIT WHEN cur_src_tbl.count =0;
FOR i IN cur_src LOOP
BEGIN
INSERT INTO SOURCE_TEMP VALUES(cur_src(i).sort_code,cur_src(i).flag);
COMMIT;
EXCEPTION
WHEN OTHERS THEN NULL;
END;
CLOSE cur_src;
OPEN cur_target;
LOOP
FETCH cur_target BULK COLLECT INTO cur_target_tbl LIMIT 500;
EXIT WHEN cur_target.count =0;
FOR i IN cur_target_tbl LOOP
BEGIN
INSERT INTO target_temp VALUES(cur_target_tbl(i).sort_code,cur_target_tbl(i).target_sort_code);
COMMIT;
EXCEPTION
WHEN OTHERS THEN NULL;
END;
CLOSE cur_newid;
OPEN cur_newid;
LOOP
FETCH cur_newid BULK COLLECT INTO cur_newid_tbl LIMIT 500;
EXIT WHEN cur_newid_tbl.count =0;
FOR i IN cur_newid_tbl LOOP
BEGIN
INSERT INTO newid_TEMP VALUES(cur_newid_tbl(i).sort_code,cur_newid_tbl(i).flag);
COMMIT;
EXCEPTION
WHEN OTHERS THEN NULL;
END;
CLOSE cur_newid;
END;
Thanks to All ur support
I created the Proc, Finally I got PLSQL-PROCEDURE to execute my concepts.
create TABLE FLAG
(
FLAG VARCHAR2(6)
);
INSERT INTO FLAG VALUES('PASS01');

Oracle SQL random value from string set

In Oracle SQL 11g I am trying to fill a table with procedure. For some columns I need to take data randomly from predefined set of strings. How do I define such set and take data from it by random order?
You could use a cte and dbms_random.value. Something like:
with strings as (
select 'string1' as s from dual union all
select 'string2' as s from dual union all
select 'string3' as s from dual union all
select 'string4' as s from dual
)
select <col1>,
(select s
from (select s from strings order by dbms_random.value) s
where rownum = 1
) as RandomString
from dual;
Can you give this a try,it is working.
1.Insert the list of strings in a table (strings).
2.Create a function(RANDOM) to generate random number.
3.Create a procedure(PROC_STRING) to pick a string name from (STRINGS) table using the random number generated from function(RANDOM) and then insert into (NEW_TABLE)
PROGRAM:
--Table with list of string names
Create table strings (string_id number,string_name varchar2(2000) );
--Table to store new string names in random order
Create table new_table (string_id number,string_name varchar2(2000) );
--Function to generate random numbers
create or replace function random(p_number in number)
return number
is
a number;
begin
select dbms_random.value(1,10) into a
from dual;
a := floor(a);
return a;
end;
/
delete from strings;
delete from new_table;
insert into strings values(1,'abc');
insert into strings values(2,'def');
insert into strings values(3,'ghi');
insert into strings values(4,'abc 1');
insert into strings values(5,'def 1');
insert into strings values(6,'ghi 1');
insert into strings values(7,'abc 2');
insert into strings values(8,'def 2');
insert into strings values(9,'ghi 2');
insert into strings values(10,'xyz 3');
--Procedure to pick string names randomly from strings table and insert into new_table
create or replace procedure proc_string(p_no in number)
as
s_id number;
s_name varchar2(2000);
begin
select random(1) into s_id from dual;
select string_name into s_name from strings where string_id = s_id;
insert into New_table values(s_id,s_name);
dbms_output.put_line('insert successfully completed');
commit;
Exception when others
then dbms_output.put_line('ERROR:' || SQLCODE || ' ' || SQLERRM);
end;
/
commit;
EXECUTION:
--After executing the procedure for 3 times
SQL> exec proc_string(1);
insert successfully completed
PL/SQL procedure successfully completed.
-- Random string names got inserted into newtable
SQL> select * from new_table;
STRING_ID STRING_NAME
5 def 1
3 ghi
1 abc
Let me know if you questions.

Set a value if null inserted in Oracle SQL

I have created a trigger, that will automatically set the first column values as subsequent factorial numbers. However, additionally, I would like to set the second column's value as the value of first incremented by 5, in case a null value is inserted. Here's what I try right now:
create or replace trigger test_tr
before insert on myT
for each row
begin
IF :new.mNumb is null
THEN
UPDATE myT
SET mNumb = :new.tab_id + 5;
END IF;
SELECT fac(test_seq.NEXTVAL)
INTO :new.tab_id
FROM dual;
end;
But clearly I'm missing something, as nothing happens, the inserted null is still empty.
Do not re-update the table in your trigger, update the row you're given directly:
...
IF :new.mNumb is null
THEN
:new.mNumb = :new.tab_id + 5;
END IF;
...
It all works as expected, using Emmanuel's suggestion to remove the update stmt, as far as I can tell. Here's the test case I used:
drop table test;
create table test (col1 number, col2 number);
create trigger test_trg
before insert on test
for each row
begin
IF :new.col2 is null
THEN
:new.col2 := :new.col1 + 5;
END IF;
:new.col1 := dbms_random.value;
end;
/
insert into test values (1, 1);
insert into test values (1, null);
insert into test values (null, null);
commit;
select * from test;
which produces the following output:
COL1 COL2
---------- ----------
.617580128 1
.030570358 6
.555066268
Maybe if you set :new.col1 before dealing with the null col2 scenario, that would work better for you? Doing that produces:
COL1 COL2
---------- ----------
.302670917 1
.024927489 5.02492749
.667568400 5.66756840

select forall array in sql statement(PL/SQL)

Type tabArray IS TABLE OF TABLE%ROWTYPE;
tableArray tabArray ;
--fill array
SELECT *
BULK COLLECT INTO tableArray
FROM TABLE
WHERE TABLE.field = ....
--work
FOR pos IN 1..tableArray .count
LOOP
dbms_output.put_line(pos||' '||audArray(pos).field);
end loop;
--doesn't work
SELECT * TABLE2
WHERE TABLE2.field in (SELECT filed FROM FORALL tableArray );
Main question: how can I use my array in sql statement (in) ?
First you have to create a type in SQL then can use as given below
CREATE TYPE FRUIT_TT AS TABLE OF VARCHAR2(100)
SELECT column_value AS val
FROM TABLE(FRUIT_TT('Apple','Banana','Apricot'))
WHERE column_value NOT LIKE 'A%';
Here a type FRUIT_TT is created and using it in SQL query.
Here is an example, you just need to adjust your SQL statement.
CREATE TYPE col_ntt IS TABLE OF NUMBER;
CREATE TABLE num_tab
(
col NUMBER
);
INSERT INTO num_tab VALUES(1);
INSERT INTO num_tab VALUES(2);
INSERT INTO num_tab VALUES(4);
DECLARE
l_col1 col_ntt := col_ntt(1, 2, 3);
l_col2 col_ntt;
BEGIN
SELECT *
BULK COLLECT INTO l_col2
FROM num_tab
WHERE col IN (SELECT column_value FROM TABLE(l_col1));
FOR indx IN 1..l_col2.COUNT LOOP
DBMS_OUTPUT.PUT_LINE(l_col2(indx));
END LOOP;
END;
/*
1
2
*/