Procedure to Insert into table and its columns by given parameters? - sql

i`ll start this with some code...
CREATE OR REPLACE PROCEDURE LOAD_IMAGE_INTO_TABLE (
imgDir varchar2
, imgName varchar2
, destTable varchar2
, destIndex varchar2
, destBlob varchar2)
AS
fHnd bfile;
b blob;
srcOffset integer := 1;
dstOffset integer := 1;
BEGIN
dbms_lob.CreateTemporary( b, true );
fHnd := BFilename( imgDir, imgName );
dbms_lob.FileOpen( fHnd, DBMS_LOB.FILE_READONLY );
dbms_lob.LoadFromFile( b, fHnd, DBMS_LOB.LOBMAXSIZE, dstOffset, srcOffset );
--insert into (Select * From user_tables Where table_name = destTable) values(imgName,b);
--insert into destTable (destIndex, destBlob) values( imgName, b );
commit;
dbms_lob.FileClose( fHnd );
END LOAD_IMAGE_INTO_TABLE;
As you might see, I am trying to create a procedure which puts an image into a table. Target table name and column names (for imgname and blobfile) will be given as parameters.
Both ways I tried didn't work. (see --insert(...) in code)
Maybe you have any idea how to solve this?
Thanks in advance.

Related

oracle sql : "get or insert" stored procedure

I would like to do a stored procedure that receive an input param and then
if targeted table does not contains that value, a new row is created and then the id of the created row is returned
if targeted table already contain input param, the id of the row is returned
For moment I only manage to insert new row only if input param is new:
--exemple of table with a primary id a column with value
create table unique_number_table (
id NUMBER(12) not null,
UNIQUE_NUMBER VARCHAR2(80) not null,
constraint PK_ID primary key (ID)
);
create sequence SEQ_NUMBER
INCREMENT BY 1
START WITH 2
MAXVALUE 999999999
MINVALUE 0;
create or replace procedure insert_or_get_unique_number ( input_number in varchar ) is
begin
insert into unique_number_table (id, UNIQUE_NUMBER)
select SEQ_NUMBER.NEXTVAL ,input_number
from dual
where not exists(select * from unique_number_table
where UNIQUE_NUMBER =input_number);
end insert_or_get_unique_number;
Do you know how to do this?
Seems to me like you want a stored function and not a procedure.
create or replace function insert_or_get_unique_number (input_number varchar2)
return UNIQUE_NUMBER_TABLE.ID%type
is
L_NUM UNIQUE_NUMBER_TABLE.ID%type;
begin
select ID
into L_NUM
from UNIQUE_NUMBER_TABLE
where UNIQUE_NUMBER = input_number;
return L_NUM;
exception
when NO_DATA_FOUND then
insert into unique_number_table (id, UNIQUE_NUMBER)
values (SEQ_NUMBER.NEXTVAL, input_number)
returning ID into L_NUM;
return L_NUM;
end insert_or_get_unique_number;
This is a possible solution to your problem.
CREATE OR REPLACE PROCEDURE insert_or_get_unique_number (
input_number IN VARCHAR,
c_out out sys_refcursor
) IS
Lv_input_exists INT;
lv_myRowid VARCHAR2(200);
err_code varchar2(600);
err_msg varchar2(500);
BEGIN
--step 1 check if the input param exists. -
select count(*)
INTO Lv_input_exists
FROM unique_number_table
WHERE unique_number = input_number;
--step 2 if it exists than get the rowid of that row and return that value
IF Lv_input_exists > 0
THEN
OPEN c_out for
SELECT ROWID
FROM unique_number_table Uni
WHERE uni.id = input_number ;
RETURN;
ELSE
-- STEP 3 the input number does not exists therefore we need to insert and return the rowid--
INSERT INTO unique_number_table (
id,
unique_number
)
VALUES(
seq_number.NEXTVAL,
input_number)
returning ROWID into lv_myRowid;
----STEP 4 Open the cursor and return get the rowid.
OPEN c_out for
SELECT lv_myRowid
FROM DUAL ;
SYS.dbms_output.put_line( 'Done' );
END IF;
EXCEPTION WHEN OTHERS THEN
err_code := SQLCODE;
err_msg := SUBSTR(SQLERRM, 1, 200);
SYS.dbms_output.put_line( err_code || ' '||': '||err_msg );
END insert_or_get_unique_number;
you can test the procedure like so.
set serveroutput on ;
DECLARE
INPUT_NUMBER VARCHAR2(200);
C_OUT sys_refcursor;
BEGIN
INPUT_NUMBER := '3';
INSERT_OR_GET_UNIQUE_NUMBER(
INPUT_NUMBER => INPUT_NUMBER,
C_OUT => C_OUT
);
DBMS_SQL.return_result(C_OUT);
END;

Copy data for another table using Collections Types index-by table (associated with a table)

I don't know how to create a function with collections type. I am familiar with SQL, but I do not know that particular function. Here is what I tried:
Create or Replace Function COPY_EMPLOYEES_WITH_RT(
Begin
insert into jjj_employees ( select * from employees)
I want to create a function COPY EMPLOYEES_WITH_RT and copy data from the table EMPLOYEES to jjj_EMPLOYEES using Collections Types index-by table (associated with a table).
CREATE OR REPLACE FUNCTION COPY_EMPLOYEES_WITH_RT(O_ERROR_MESSAGE OUT VARCHAR)
--DECLARE type
TYPE EMP_RECORD IS TABLE OF employees%ROWTYPE;
l_emp EMP_RECORD;
-- define cursor
CURSOR c_employees IS
SELECT *
FROM employees;
--
BEGIN
--
open c_employees;
loop
fetch c_employees
bulk collect into l_emp limit 1000;
exit when l_emp.count = 0;
-- Process contents of collection here.
Insert into jrf_employees values l_emp;
END LOOP;
CLOSE c_employees;
EXCEPTION
--
WHEN OTHERS THEN
O_error_message := SQLERRM;
END;
/
it's like something like that, i just didn't know, what is wrong
If you are using object-relational tables and particularly want to use PL/SQL associative arrays (index-by table types) then you can create your tables as:
CREATE TYPE employee_t IS OBJECT(
id NUMBER(10,0),
first_name VARCHAR2(20),
last_name VARCHAR2(20)
);
CREATE TABLE employees OF employee_t (
id PRIMARY KEY
);
CREATE TABLE jjj_employees OF employee_t (
id PRIMARY KEY
);
With the sample data:
INSERT INTO employees
SELECT 1, 'One', 'Uno' FROM DUAL UNION ALL
SELECT 2, 'Two', 'Dos' FROM DUAL UNION ALL
SELECT 3, 'Three', 'Tres' FROM DUAL;
And the function as:
CREATE FUNCTION COPY_EMPLOYEES_WITH_RT
RETURN NUMBER
IS
TYPE employee_a IS TABLE OF employee_t INDEX BY PLS_INTEGER;
emps employee_a;
i PLS_INTEGER;
BEGIN
FOR r IN ( SELECT VALUE(e) AS employee FROM employees e )
LOOP
emps( r.employee.id ) := r.employee;
END LOOP;
i := emps.FIRST;
WHILE i IS NOT NULL LOOP
INSERT INTO jjj_employees VALUES ( emps(i) );
i := emps.NEXT(i);
END LOOP;
RETURN 1;
END;
/
Then you can run the function using:
BEGIN
DBMS_OUTPUT.PUT_LINE( COPY_EMPLOYEES_WITH_RT() );
END;
/
And the table is copied as:
SELECT * FROM jjj_employees;
Outputs:
ID | FIRST_NAME | LAST_NAME
-: | :--------- | :--------
1 | One | Uno
2 | Two | Dos
3 | Three | Tres
db<>fiddle here
Update
Since you appear to want to use a collection and not an associative array:
CREATE OR REPLACE FUNCTION COPY_EMPLOYEES_WITH_RT
RETURN VARCHAR2
IS
--DECLARE type
TYPE EMP_RECORD IS TABLE OF employees%ROWTYPE;
l_emp EMP_RECORD;
-- DECLARE cursor
CURSOR c_employees IS
SELECT *
FROM employees;
BEGIN
OPEN c_employees;
LOOP
FETCH c_employees
BULK COLLECT INTO l_emp LIMIT 1000;
EXIT WHEN l_emp.COUNT = 0;
-- Process contents of collection here.
FORALL i IN 1 .. l_emp.COUNT
INSERT INTO jjj_employees VALUES l_emp(i);
END LOOP;
CLOSE c_employees;
RETURN NULL;
EXCEPTION
WHEN OTHERS THEN
RETURN SQLERRM;
END;
/
db<>fiddle

How to select into varray in Oracle

I'm trying to save a set of ids in array:
create or replace type vrray_4 as varray(4) of varchar2(10);
create or replace procedure get_acl_owner_exchange (id in varchar2 ) is
path_count int;
acl_type out vrray_4;
begin
select owner_id into acl_type from kmc_acl_perm
where permission_name = 'read.'
or permission_name = 'write.'
or permission_name = 'delete.';
end get_acl_owner_exchange;
I'm getting the error:
LINE/COL ERROR
-------- --------------------------------------------------------------------------------
3/17 PLS-00103: Encountered the symbol "VRRAY_4" when expecting one of the following:
:= . ( # % ; not null range default character
The symbol ":=" was substituted for "VRRAY_4" to continue.
You have the OUT parameter in the wrong place and you need to use BULK COLLECT INTO rather than just INTO:
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE KMC_ACL_PERM(
owner_id VARCHAR2(10),
permission_name VARCHAR2(10)
)
/
CREATE OR REPLACE TYPE vrray_4 AS VARRAY(4) OF VARCHAR2(10)
/
create or replace PROCEDURE GET_ACL_OWNER_EXCHANGE (
id IN VARCHAR2,
acl_type OUT VRRAY_4
) IS
BEGIN
SELECT owner_id
bulk collect into acl_type
from KMC_ACL_PERM
where permission_name IN ( 'read.', 'write.', 'delete.' );
END GET_ACL_OWNER_EXCHANGE;
/
Does this work for you:
CREATE OR REPLACE TYPE vrray_4 AS VARRAY(4) OF VARCHAR2(10);
/
CREATE TABLE kmc_acl_perm (
owner_id VARCHAR2(10),
permission_name VARCHAR2(10)
);
CREATE OR REPLACE PROCEDURE get_acl_owner_exchange (id IN VARCHAR2) IS
path_count NUMBER;
acl_type vrray_4;
BEGIN
SELECT owner_id BULK COLLECT INTO acl_type
FROM kmc_acl_perm
WHERE permission_name IN ('read.', 'write.', 'delete.');
END get_acl_owner_exchange;
/

Oracle SQL FGA sys_context(‘userenv’,’current_sql’) truncated

I want to log all statement against a specific table, using FGA and sys_context(‘userenv’,’current_sql’) I get close to what I need but it appears like current_sql is always truncated to 256 char.
I tried looking at current_sql1 to 7 but they are always empty. Here is the code I'm using to set this up :
create table emp_audit
( whodidit varchar2(40)
, whenwasit timestamp
, sql_executed varchar2(4000)
, sql_executed1 varchar2(4000)
, sql_executed2 varchar2(4000)
, sql_executed3 varchar2(4000)
, sql_executed4 varchar2(4000)
, sql_executed5 varchar2(4000)
, sql_executed6 varchar2(4000)
, sql_executed7 varchar2(4000)
);
create or replace
package AUDIT_HANDLER
is
PROCEDURE HANDLE_EMP_SAL_ACCESS
( object_schema VARCHAR2
, object_name VARCHAR2
, policy_name VARCHAR2
);
end;
create or replace
package body AUDIT_HANDLER
is
PROCEDURE HANDLE_EMP_SAL_ACCESS
( object_schema VARCHAR2
, object_name VARCHAR2
, policy_name VARCHAR2
) is
PRAGMA AUTONOMOUS_TRANSACTION;
begin
insert into emp_audit
( whodidit, whenwasit, sql_executed, SQL_EXECUTED1, SQL_EXECUTED2, SQL_EXECUTED3, SQL_EXECUTED4, SQL_EXECUTED5, SQL_EXECUTED6, SQL_EXECUTED7)
values
( user, systimestamp, sys_context('userenv','current_sql'),sys_context('userenv','current_sql1'),sys_context('userenv','current_sql2'),sys_context('userenv','current_sql3'),sys_context('userenv','current_sql4'),sys_context('userenv','current_sql5'),sys_context('userenv','current_sql6'),sys_context('userenv','current_sql7'))
;
commit;
end HANDLE_EMP_SAL_ACCESS;
end;
begin
dbms_fga.add_policy
( object_schema=>'EPAT'
, object_name=>'PERSON'
, policy_name=>'PHI_ACCESS_HANDLED'
, handler_schema => 'SBOUCHAR'
, handler_module => 'AUDIT_HANDLER.HANDLE_EMP_SAL_ACCESS'
);
end;
It appears like you have to specify the length in the call to sys_context :
sys_context('userenv','current_sql',4000)

How to Create Stored procedure in DB2

Can you please help me to create a below Oracle procedure in DB2? Same table name with columns are available in DB2 also but below script is not working
CREATE OR REPLACE PROCEDURE sample_proc (ACCT_NO in CHAR,p_cursor out SYS_REFCURSOR)
is
BEGIN
OPEN p_cursor FOR
select sampl1,sample2,sample3
from
table_test b
where
rec_id='A'
and sample3=ACCT_NO ;
END;
If you want a return better use function here are some example to get collection
CREATE TABLE table_test
(
sample1 VARCHAR2 (1000),
sample2 VARCHAR2 (1000),
sample3 VARCHAR2 (1000)
);
insert into table_test ( sample1,sample2 ,sample3)
values ('daftest1','dsdtest1','sstsest3');
insert into table_test ( sample1,sample2 ,sample3)
values ('FAStest1','fstest1','sstsest3');
insert into table_test ( sample1,sample2 ,sample3)
values ('sdtest1','asdtest1','fstest3');
insert into table_test ( sample1,sample2 ,sample3)
values ('test2','test2','test123');
CREATE OR REPLACE TYPE TEST_REC
AS OBJECT (
sample1 VARCHAR2(1000)
,sample2 VARCHAR2(1000)
,sample3 VARCHAR2(1000)
);
CREATE OR REPLACE TYPE TEST_REPORT_TABLE
AS TABLE OF TEST_REC;
CREATE OR REPLACE FUNCTION testing (p_acct_no IN varchar2)
RETURN test_report_table
IS
v_rec test_rec;
v_test_report_table test_report_table := test_report_table();
BEGIN
FOR i IN (SELECT sample1,sample2,sample3
FROM table_test b
--where rec_id='A'
where sample3=p_acct_no)
LOOP
v_rec:=test_rec(NULL,NULL,NULL);
dbms_output.put_line(i.sample1);
v_rec.sample1:=i.sample1;
v_rec.sample2:=i.sample2;
v_rec.sample3:=i.sample3;
v_test_report_table.EXTEND;
v_test_report_table(v_test_report_table.COUNT) :=v_rec;
END LOOP;
RETURN v_test_report_table;
END;
select * from table(testing(p_acct_no=>'sstsest3'))
Or better use bulk collect if you don't need to add rows dynamically
CREATE OR REPLACE FUNCTION JSTRAUTI.testing (p_acct_no IN varchar2)
RETURN test_report_table
IS
v_test_report_table test_report_table := test_report_table();
BEGIN
SELECT test_rec(sample1,sample2,sample3)
bulk collect into v_test_report_table
FROM table_test b
--where rec_id='A'
where sample3=p_acct_no;
RETURN v_test_report_table;
END;
result the same.