Encountered the symbol "end-of-file" - sql

I have written foll query but getting error:
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
:= . ( # % ;
Following is the stored procedure query
I know its the syntax error but cannot figure out where exactly the problem is.
It will be a great help if someone help me.
CREATE OR REPLACE PROCEDURE MCSIL_HR.sp_ins_emp_mst_DEV (
inemp_id emp_mst.emp_id%TYPE,
inemp_restrict_emp emp_mst.restrict_emp%TYPE,
inemp_name emp_mst.emp_name%TYPE,
inemp_email emp_mst.email_id%TYPE,
inemp_pwd emp_mst.emp_pwd%TYPE,
indob VARCHAR2,
indoj VARCHAR2,
indor VARCHAR2,
inemp_status_lkp_id emp_mst.emp_status_lkp_id%TYPE,
inemp_has_reportee_status emp_mst.has_reportees_status_yn%TYPE,
inupd_emp_id emp_mst.emp_id%TYPE,
inupd_flag CHAR,
indept VARCHAR2,
inmgr_id emp_mst.mgr_id%TYPE,
outmsg OUT VARCHAR2,
outstatus OUT VARCHAR2
)
IS
pgm_error EXCEPTION;
as_emp_id emp_mst.emp_id%TYPE;
as_cnt NUMBER;
upd_flag VARCHAR2 (3);
asdob DATE;
asdoj DATE;
asdor DATE;
BEGIN
outmsg := '';
outstatus := 'TRUE';
upd_flag := UPPER (TRIM (inupd_flag));
-- check if Emp Status lookup value exists in lookup table , if not raise error
SELECT COUNT (1)
INTO as_cnt
FROM lookup l
WHERE l.lkp_id = inemp_status_lkp_id;
IF as_cnt = 0
THEN
outmsg :=
'Employee Sattus LOOK UP VALUE : '
|| TO_CHAR (inemp_status_lkp_id)
|| ' NOT EXISTS IN LOOKUP TABLE ';
outstatus := 'INSERT/UPDATE/DELETE Failed.';
RAISE pgm_error;
END IF;
-- check if Yes/No Status ookup value exists in lookup table , if not raise error
SELECT COUNT (1)
INTO as_cnt
FROM lookup l
WHERE l.lkp_id = inemp_has_reportee_status;
IF as_cnt = 0
THEN
outmsg :=
'Has_Reportees Status LOOK UP VALUE : '
|| TO_CHAR (inemp_has_reportee_status)
|| ' NOT EXISTS IN LOOKUP TABLE ';
outstatus := 'INSERT/UPDATE/DELETE Failed.';
RAISE pgm_error;
END IF;
-- check whether user modifying data is valid employee
SELECT COUNT (1)
INTO as_cnt
FROM emp_mst e
WHERE e.emp_id = inupd_emp_id;
IF as_cnt = 0
THEN
outmsg :=
'UPDATING USER ID: '
|| TO_CHAR (inupd_emp_id)
|| ' NOT EXISTS IN EMPLOYEE MASTER ';
outstatus := 'INSERT/UPDATE/DELETE Failed.';
RAISE pgm_error;
END IF;
-- checking date formatt (dd-mm-yyyy)
IF indob IS NULL
OR NOT ( SUBSTR (TRIM (indob), 3, 1) = '-'
AND SUBSTR (TRIM (indob), 6, 1) = '-'
)
THEN
outmsg :=
'Date of Birth is Blank or Formatt for Date of Birth is not in DD-MM-YYYY, Contact Administrator';
outstatus := 'INSERT/UPDATE/DELETE Failed.';
RAISE pgm_error;
END IF;
IF indoj IS NULL
OR NOT ( SUBSTR (TRIM (indoj), 3, 1) = '-'
AND SUBSTR (TRIM (indoj), 6, 1) = '-'
)
THEN
outmsg :=
'Date of Join is Blank or Formatt for Date of Join is not in DD-MM-YYYY, Contact Administrator';
outstatus := 'INSERT/UPDATE/DELETE Failed.';
RAISE pgm_error;
END IF;
IF indor IS NOT NULL
AND NOT ( SUBSTR (TRIM (indor), 3, 1) = '-'
AND SUBSTR (TRIM (indor), 6, 1) = '-'
)
THEN
outmsg :=
'Formatt for Date of Resign is not in DD-MM-YYYY, Contact Administrator';
outstatus := 'INSERT/UPDATE/DELETE Failed.';
RAISE pgm_error;
END IF;
asdob := TO_DATE (TRIM (indob), 'DD-MM-YYYY');
asdoj := TO_DATE (TRIM (indoj), 'DD-MM-YYYY');
asdor := TO_DATE (TRIM (indor), 'DD-MM-YYYY');
DBMS_OUTPUT.put_line ( 'LKP SRNO, UPDATE USER EMPCODE OK,'
|| 'DOB :'
|| TO_CHAR (asdob)
|| ',DOJ :'
|| TO_CHAR (asdoj)
|| ',DOR :'
|| TO_CHAR (asdor)
);
-- check whether user modifying data is valid employee
SELECT COUNT (*)
INTO as_cnt
FROM emp_mst e
WHERE e.emp_id = inemp_id;
IF upd_flag = 'U'
THEN
IF as_cnt = 0
THEN
outmsg :=
'EMPLOYEE CODE : '
|| TO_CHAR (inemp_id)
|| ' NOT EXISTS IN EMPLOYEE MASTER';
outstatus := 'UPDATE Failed.';
RAISE pgm_error;
END IF;
UPDATE emp_mst a
SET a.rec_dtl = rec_dtl (NULL, NULL, NULL, NULL)
WHERE a.rec_dtl IS NULL;
-- For password change call another procedure
UPDATE emp_mst a
SET a.emp_name = inemp_name,
a.restrict_emp = inemp_restrict_emp,
a.email_id=inemp_email,
a.emp_pwd = ENCRYPT(inemp_pwd),
a.dob = asdob,
a.doj = asdoj,
a.dor = asdor,
a.emp_status_lkp_id = inemp_status_lkp_id,
a.has_reportees_status_yn = inemp_has_reportee_status,
a.rec_dtl.updated_by = inupd_emp_id,
a.DEPT= indept,
a.MGR_ID = inmgr_id,
a.rec_dtl.updated_on = SYSDATE
WHERE a.emp_id = inemp_id;
IF SQLCODE <> 0
THEN
ROLLBACK;
outstatus := 'FALSE';
outmsg := 'UPDATE Failed.';
RAISE pgm_error;
ELSE
COMMIT;
outstatus := 'TRUE';
outmsg := 'Process sucessfully executed';
END IF;
ELSIF upd_flag = 'I'
THEN
IF as_cnt > 0
THEN
outmsg :=
'EMPLOYEE ID : '
|| TO_CHAR (inemp_id)
|| ' ALREADY IN EMPLOYEE MASTER';
outstatus := 'INSERT Failed.';
RAISE pgm_error;
END IF;
INSERT INTO mcsil_hr.emp_mst
(emp_id,restrict_emp, emp_name,email_id, emp_pwd, dob, doj, dor, ---added by shailesh
emp_status_lkp_id, has_reportees_status_yn,
rec_dtl,DEPT,MGR_ID
)
VALUES (inemp_id,inemp_restrict_emp, inemp_name, inemp_email, ENCRYPT(inemp_pwd), asdob, asdoj, asdor, ---added by shailesh
inemp_status_lkp_id, inemp_has_reportee_status,
rec_dtl (inupd_emp_id, SYSDATE, NULL, NULL),indept,inmgr_id
);
IF SQLCODE <> 0
THEN
ROLLBACK;
outstatus := 'FALSE';
outmsg := 'INSERT Failed.';
RAISE pgm_error;
ELSE
COMMIT;
outstatus := 'TRUE';
outmsg := 'Process Sucessfully executed';
END IF;
ELSIF upd_flag = 'D'
THEN
IF as_cnt = 0
THEN
outmsg :=
'EMPLOYEE ID : '
|| TO_CHAR (inemp_id)
|| ' NOT EXISTS IN EMPLOYEE MASTER';
outstatus := 'DELETE Failed.';
RAISE pgm_error;
END IF;
UPDATE emp_mst a
SET a.rec_dtl = rec_dtl (NULL, NULL, NULL, NULL)
WHERE a.rec_dtl IS NULL;
UPDATE emp_mst a
SET a.emp_status_lkp_id = 202, -- INCATIVE ACCOUNT CODE
a.rec_dtl.updated_by = inupd_emp_id,
a.rec_dtl.updated_on = SYSDATE
WHERE a.emp_id = inemp_id;
IF SQLCODE <> 0
THEN
ROLLBACK;
outstatus := 'FALSE';
outmsg := 'DELTE Failed.';
RAISE pgm_error;
ELSE
COMMIT;
outstatus := 'TRUE';
outmsg := 'Process sucessfully executed';
END IF;
ELSE
outstatus := 'FALSE';
outmsg := 'ACTION FLAG SHOULD BE IN I(Insert)/U(Update)/D(Delete).';
RAISE pgm_error;
END IF;
DBMS_OUTPUT.put_line ('STATUS :' || outstatus || ', MGS :' || outmsg);
EXCEPTION
WHEN pgm_error
THEN
BEGIN
outstatus := 'FALSE';
DBMS_OUTPUT.put_line ('STATUS :' || outstatus || ', MGS :' || outmsg);
raise_application_error (-20999, outmsg);
END;
WHEN NO_DATA_FOUND
THEN
BEGIN
outmsg := 'INSERT/UPDATE/DELETE FAILED. NO DATA FOUND';
outstatus := 'FALSE';
DBMS_OUTPUT.put_line ('STATUS :' || outstatus || ', MGS :' || outmsg);
raise_application_error (-20999, outmsg);
END;
WHEN OTHERS
THEN
BEGIN
outmsg := 'INSERT/UPDATE/DELETE FAILED. ';
outstatus := 'FALSE';
DBMS_OUTPUT.put_line ('STATUS :' || outstatus || ', MGS :' || outmsg);
raise_application_error (-20999, outmsg || SQLERRM);
END;
END sp_ins_emp_mst_DEV ;
/

Are you using SQL*Plus? If you are, then it's probably the blank lines in your code, which would be interpreted as the end of a line.
I would suggest you do this:
set echo on
spool sp_ins_emp_mst_dev.log
<your procedure declaration>
spool off
And look very carefully at your line numbers. If they don't run smoothly from the beginning to the end, try making the blank lines into comments (my choice) or set sqlblanklines on.

Related

debug oracle procedure

I have a oracle stored procedure, inputs is
p_processId = 5660
p_featureClassName ='future_parcels'
p_DrawnGeometry = MDSYS.SDO_GEOMETRY(2003, 2400000, null,
MDSYS.SDO_ELEM_INFO_ARRAY(1, 1003, 1, 27, 2003, 1),
MDSYS.SDO_ORDINATE_ARRAY(8439212.4589933194220066070556640625,
4540074.1191380098462104797363281250, 8439201.7998965308070182800292968750, 4540058.374383729882538318634033203125, 8439315.814959609881043434143066406250, 4540058.374466760084033012390136718750, 8439319.9868115298449993133544921875, 4540067.6362674199044704437255859375, 8439323.231370599940419197082519531250, 4540081.528450479730963706970214843750, 8439328.328618479892611503601074218750, 4540097.737373660318553447723388671875, 8439330.6458750404417514801025390625, 4540129.691041340120136737823486328125, 8439332.959363190457224845886230468750, 4540149.486472180113196372985839843750, 8439227.984901839867234230041503906250, 4540148.055711519904434680938720703125, 8439225.43722324073314666748046875, 4540138.489620880223810672760009765625, 8439223.1199580393731594085693359375, 4540118.576599569991230964660644531250, 8439220.802692830562591552734375, 4540098.663578259758651256561279296875, 8439212.4589933194220066070556640625, 4540074.1191380098462104797363281250, 8439252.6796298995614051818847656250, 4540086.660427900031208992004394531250, 8439243.2996299006044864654541015625, 4540125.440427900291979312896728515625, 8439299.99962989985942840576171875, 4540138.040427899919450283050537109375, 8439310.49962989985942840576171875, 4540098.280427900142967700958251953125, 8439252.6796298995614051818847656250, 4540086.660427900031208992004394531250))
Procedure:
CREATE OR REPLACE
PROCEDURE get_DrawnGeometries (
p_processId IN INTEGER
, p_featureClassName IN VARCHAR2
, p_DrawnGeometry IN SDO_GEOMETRY
, p_prm_val OUT VARCHAR2
)
IS
PRAGMA AUTONOMOUS_TRANSACTION;
CURSOR featClassAttributes_cur (featureClassName IN VARCHAR2) IS
SELECT
gac.id
, lower(gac.column_name) AS column_name
, gac.view_u_pk
, gac.data_type
, gas.naziv
, gat.table_name
FROM geo_atrib_columns gac
JOIN geo_atrib_tables gat ON gat.table_name = gac.table_name
JOIN geo_app_slojevi gas ON gas.naziv = gat.layer_name
WHERE gas.naziv = featureClassName
AND gat.aktivan = 1
AND gac.aktivan = 1
AND gac.view_iu_write = 1
ORDER BY gac.view_order;
vc_sql CLOB;
vc_sql2 CLOB;
vc_sql3 CLOB;
v_columns VARCHAR2(1000);
v_tableName VARCHAR2(1000);
v_whereClause VARCHAR2(1000);
v_whereClause2 VARCHAR2(1000);
v_g_col_name VARCHAR2(30);
v_tolerance VARCHAR2(20);
v_separator VARCHAR2(16) := ' || ''' || glob_var.v_strSeparator || ''' || ';
p_id INTEGER;
v_mssg VARCHAR2(500) := NULL;
BEGIN
vc_sql := 'SELECT #columns# FROM #table_name# WHERE #where_clause#';
vc_sql2 := 'SELECT #columns# FROM #table_name# WHERE #where_clause2#';
vc_sql3 := vc_sql;
FOR rt_att IN featClassAttributes_cur(p_featureClassName) LOOP
IF rt_att.data_type = 'N' THEN
v_columns := v_columns || v_separator || ' nvl(gt_util.num2CharPointSep(' || rt_att.column_name|| '), ''NULL'')';
ELSE
v_columns := v_columns || v_separator || ' nvl(to_char(' || rt_att.column_name|| '), ''NULL'')';
END IF;
IF v_tableName IS NULL THEN
v_tableName := rt_att.table_name;
END IF;
--dbms_output.put_line(v_tableName);
END LOOP;
v_columns := ltrim(v_columns, v_separator);
v_g_col_name := gt_util.get_layer_g_col(v_tableName);
v_tolerance := gt_util.num2CharPointSep(gt_util.get_layer_tollerance(v_tableName, v_g_col_name));
--v_whereClause := 'ins_id = {0} AND SDO_GEOM.RELATE(:geom, ''EQUAL+INSIDE+CONTAINS+COVEREDBY+COVERS+OVERLAPBDYINTERSECT'', ' || v_g_col_name || ', ' || v_tolerance || ') = ''EQUAL+INSIDE+CONTAINS+COVEREDBY+COVERS+OVERLAPBDYINTERSECT''';
v_whereClause := 'ins_id = {0} AND SDO_GEOM.RELATE(:geom, ''EQUAL'', ' || v_g_col_name || ', ' || v_tolerance || ') = ''EQUAL''';
v_whereClause2 := 'ins_id = {0} AND gt_util.geom_is_equal(:geom, ' || v_g_col_name || ', ' || v_tolerance || ') = ''TRUE''';
v_whereClause := replace(v_whereClause, '{0}', to_char(p_processId));
v_whereClause2 := replace(v_whereClause2, '{0}', to_char(p_processId));
vc_sql := replace(vc_sql, '#columns#', v_columns);
vc_sql := replace(vc_sql, '#table_name#', v_tableName);
vc_sql := replace(vc_sql, '#where_clause#', v_whereClause);
vc_sql2 := replace(vc_sql2, '#columns#', v_columns);
vc_sql2 := replace(vc_sql2, '#table_name#', v_tableName);
vc_sql2 := replace(vc_sql2, '#where_clause2#', v_whereClause2);
dbms_output.put_line(vc_sql);
dbms_output.put_line(vc_sql2);
BEGIN
EXECUTE IMMEDIATE vc_sql INTO p_prm_val USING p_DrawnGeometry;
EXCEPTION WHEN NO_DATA_FOUND THEN
EXECUTE IMMEDIATE vc_sql2 INTO p_prm_val USING p_DrawnGeometry;
WHEN TOO_MANY_ROWS THEN
vc_sql3 := replace(vc_sql3, '#columns#', 'id');
vc_sql3 := replace(vc_sql3, '#table_name#', v_tableName);
vc_sql3 := replace(vc_sql3, '#where_clause#', v_whereClause);
vc_sql3 := 'SELECT * FROM (' || vc_sql3 || ' ORDER BY id DESC) WHERE ROWNUM = 1';
EXECUTE IMMEDIATE vc_sql3 INTO p_id USING p_DrawnGeometry;
EXECUTE IMMEDIATE 'DELETE FROM ' || v_tableName || ' WHERE id = ' || p_id;
COMMIT;
v_mssg := 'Identical geometry already exists. Drawn geometry is deleted. If you want to delete new geometry please delete the old one first';
RAISE error_util.ep_UsrExc;
--dbms_output.put_line(vc_sql2);
END;
EXCEPTION WHEN error_util.ep_UsrExc THEN
ERROR_UTIL.log_and_raise(SQLCODE, SQLERRM, v_mssg, DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
RAISE;
END get_DrawnGeometries;
how I can check result and debug it output ?
when I can call it returned errors
Procedure execution failed ORA-06550: line 1, column 233: PLS-00382:
expression is of wrong type ORA-06550: line 1, column 213: PL/SQL:
Statement ignored
In PL/SQL Developer you can right click on procedure name, click test and start debbuging

Make the declared variable inside a trigger append its value if more than one condition is met

Well I was writing a trigger and I wanted that the declared variable v_message to append every time the condition is met. So for example if the first two statements are met the v_message should be something like "Invalid account Invalid amount". I must also find a way to separate these two messages by a space if the v_message already contains some sort of an error message as it wont be readable if you had something like this "Invalid accountInvalid amount".
CREATE OR REPLACE TRIGGER checkPayments
BEFORE INSERT ON tbl_payments
FOR EACH ROW
DECLARE
v_message VARCHAR(100 CHAR);
v_is_valid CHAR(1) := 'N';
BEGIN
IF getActiveUser(getOrderUsername(:new.order_id)) = 0
THEN v_message := 'Invalid account';
ELSIF isValidAmount(:new.payment_amount) = 0
THEN v_message := 'Invalid amount';
ELSIF checkOrderExist(:new.order_id) = 0
THEN v_message := 'Invalid order ID';
ELSIF (getValidOrderPayments(:new.order_id) + :new.payment_amount ) > getOrderTotal(:new.order_id)
THEN v_message := 'Payment exceeds total';
ELSE v_message := 'OK' ;
v_is_valid := 'Y';
END IF;
:new.payment_id:= seq_payment_id.nextval;
:new.payment_date:= LOCALTIMESTAMP;
:new.payment_message := v_message;
:new.is_valid := v_is_valid;
END;
/
CREATE OR REPLACE TRIGGER checkPayments
BEFORE INSERT ON tbl_payments
FOR EACH ROW
DECLARE
v_message VARCHAR(100 CHAR);
v_is_valid CHAR(1) := 'N';
BEGIN
v_is_valid := 'Y';
IF getActiveUser(getOrderUsername(:new.order_id)) = 0
THEN v_message := 'Invalid account';
v_is_valid := 'N';
END IF;
IF isValidAmount(:new.payment_amount) = 0
THEN v_message := v_message || ' Invalid amount';
v_is_valid := 'N';
END IF;
IF checkOrderExist(:new.order_id) = 0
THEN v_message := v_message || ' Invalid order ID';
v_is_valid := 'N';
END IF;
IF (getValidOrderPayments(:new.order_id) + :new.payment_amount ) > getOrderTotal(:new.order_id)
THEN v_message := v_message || ' Payment exceeds total';
v_is_valid := 'N';
END IF;
IF v_is_valid = 'Y'
THEN v_message := 'OK' ;
END IF;
:new.payment_id:= seq_payment_id.nextval;
:new.payment_date:= LOCALTIMESTAMP;
:new.payment_message := trim(v_message);
:new.is_valid := v_is_valid;
END;
/

preparing sql dynamically in oracle stored procedure

I have 3 input parameters,based on values of each input parameter i have to prepare the SQL in procedure dynamically. I am doing below way but it is failing, if the parameter value is null,then i have to exclude that from the where clause.
IN Parameters:
empid in varchar2 || empname IN varchar2 || empsal IN varchar2
SELECT
EMP_NAME
INTO
V_EMP_NAME
FROM
EMPLOYEE
WHERE
( EMP_ID = EMPID
OR ( EMP_ID IS NULL
AND EMPID IS NULL ) )
AND ( EMP_NAME = EMPNAME
OR ( EMP_NAME IS NULL
AND EMPNAME IS NULL ) )
AND ( EMP_SAL = EMPSAL
OR ( EMP_SAL IS NULL
AND EMPSAL IS NULL ) );
After updates i modified the query like below,it is compiled but giving run time errors saying that ORA-00933: SQL command not properly ended on just before EXECUTE IMMEDIATE
V_SQL :='SELECT EMP_NAME INTO V_empname FROM employee WHERE ';
BEGIN
IF(EMPID IS NOT NULL) THEN
V_SQL := V_SQL || ' emp_id='||EMPID;
END IF;
IF(EMPNAME IS NOT NULL) THEN
V_SQL := V_SQL || ' AND emp_name='||EMPNAME;
END IF;
IF(V_empsalIS NOT NULL) THEN
V_SQL := V_SQL || ' AND emp_sal='||empsal;
V_SQL := V_SQL ||' AND ACTIVE =''Y''' ;
END IF;
EXECUTE IMMEDIATE V_SQL;
EXCEPTION
WHEN NO_DATA_FOUND THEN
V_check:= '' ;
END;
Here you are another alternative:
V_SQL_WHERE := null;
V_SQL :='SELECT EMP_NAME INTO V_empname FROM employee';
BEGIN
IF(EMPID IS NOT NULL) THEN
V_SQL_WHERE := V_SQL_WHERE || ' emp_id='||EMPID;
END IF;
IF(EMPNAME IS NOT NULL) THEN
IF (V_SQL_WHERE is not null) THEN
V_SQL_WHERE := V_SQL_WHERE || ' AND ';
END IF;
V_SQL_WHERE := V_SQL_WHERE || ' emp_name='||EMPNAME;
END IF;
IF(V_empsalIS NOT NULL) THEN
IF (V_SQL_WHERE is not null) THEN
V_SQL_WHERE := V_SQL_WHERE || ' AND ';
END IF;
V_SQL_WHERE := V_SQL_WHERE || ' emp_sal=' || empsal;
V_SQL_WHERE := V_SQL_WHERE || ' AND ACTIVE =''Y''' ;
END IF;
IF (V_SQL_WHERE is not null) then
V_SQL := V_SQL || ' WHERE ' || V_SQL_WHERE;
end if;
EXECUTE IMMEDIATE V_SQL;
EXCEPTION
WHEN NO_DATA_FOUND THEN
V_check:= '' ;
END;
Something like this: (Not tested, but just an idea)
BEGIN
IF EMPID IS NOT NULL
THEN
CLAUSE1 := 'EMP_ID = EMPID';
ELSE
CLAUSE1 := '1=1';
END IF;
IF EMPNAME IS NOT NULL
THEN
CLAUSE2 := 'EMP_NAME = EMPNAME';
ELSE
CLAUSE2 := '1=1';
END IF;
IF EMPSAL IS NOT NULL
THEN
CLAUSE3 := 'EMP_SAL = EMPSAL';
ELSE
CLAUSE3 := '1=1';
END IF;
IF ( EMPSAL IS NULL
AND EMPNAME IS NULL
AND EMPID IS NOT NULL )
THEN
CLAUSE1 := '1=0';
CLAUSE2 := '1=0';
CLAUSE3 := '1=0';
END IF;
QUERY_STR :=
' SELECT EMP_NAME INTO V_EMP_NAME FROM EMPLOYEE WHERE'
|| CLAUSE1
|| ' AND '
|| CLAUSE2
|| ' AND '
|| CLAUSE3;
END;
You can create one from scratch, including if's and elses, or you can use a package called plsql-utils, the SQL_BUILDER_PKG. It does the whole work for you.
Have a look on SQL utilities
http://code.google.com/p/plsql-utils/
Eg:
declare
l_my_query sql_builder_pkg.t_query;
l_sql varchar2(32000);
begin
sql_builder_pkg.add_select (l_my_query, 'ename');
sql_builder_pkg.add_select (l_my_query, 'sal');
sql_builder_pkg.add_select (l_my_query, 'deptno');
sql_builder_pkg.add_from (l_my_query, 'emp');
sql_builder_pkg.add_where (l_my_query, 'ename = :p_ename');
sql_builder_pkg.add_where (l_my_query, 'sal > :p_sal');
l_sql := sql_builder_pkg.get_sql (l_my_query);
dbms_output.put_line (l_sql);
end;
I used it in one project and it was a good tool.

PL/SQL CRUD matrix from a source code

I am trying to create a CRUD matrix for my function from a source code of that function, so I created a procedure that will read a source code.
create or replace procedure test_
IS
CURSOR c_text is
SELECT USER_SOURCE.TEXT
FROM USER_SOURCE
WHERE USER_SOURCE.name='TEST_FUNCTION'
AND USER_SOURCE.type='FUNCTION';
order by line;
v_single_text varchar2(4000);
v_tmp_text varchar2(10000) := ' ';
begin
open c_text;
loop
fetch c_text into v_single_text;
exit when c_text%notfound;
v_tmp_text := v_tmp_text|| chr(10) || rtrim(v_single_text);
dbms_output.put_line(v_single_text);
end loop;
close c_text;
end test_;
And that works very good for me, I get the source code of my desired function. It's a very simple function and I use this to learn PL/SQL. Output of that procedure look's like this.
function test_funkction Return varchar2
IS
kpp_value varchar2(20);
begin
select KPP
into kpp_value
from CUSTOMER
where CUSTOMER_ID = 200713;
dbms_output.put_line (kpp_value);
Return kpp_value;
end test_function;
Now, how to parse the string I've got in the output to get a desired result, my result should be like this
==TABLE_NAME==========OPERATIONS==
CUSTOMER - R - -
==================================
Now I have managed to do it.
But it will only work with my simple function, now I want to make a procedure that will work with any function.
Source code below.
create or replace procedure test_
IS
v_string_fnc varchar2(10000) := UPPER('function test_function
Return varchar2
IS
kpp_value varchar2(20);
begin
select KPP into kpp_value from CUSTOMER where CUSTOMER_ID = 200713;
dbms_output.put_line (kpp_value);
Return kpp_value;
end test_function;');
v_check PLS_INTEGER;
CURSOR c_text is
SELECT USER_SOURCE.TEXT
FROM USER_SOURCE
WHERE USER_SOURCE.name = 'TEST_FUNCTION'
AND USER_SOURCE.type = 'FUNCTION'
order by line;
v_single_text varchar2(4000);
v_tmp_text varchar2(10000) := ' ';
/*v_string varchar2(10000);*/
insert_flag char := '-';
read_flag char := '-';
update_flag char := '-';
delete_flag char := '-';
empty_space char(34) := ' ';
underline char(42) := '==========================================';
/*v_txt varchar2(10000) := ' ';*/
result_table varchar2(1000) := '/';
begin
open c_text;
loop
fetch c_text
into v_single_text;
exit when c_text%notfound;
v_tmp_text := v_tmp_text || chr(10) || rtrim(v_single_text);
/* print source code*/
/*dbms_output.put_line(v_single_text);*/
end loop;
close c_text;
/*DELETE SEARCH*/
v_check := instr(v_string_fnc, 'DELETE ');
if v_check < 1 then
dbms_output.put_line('THERE IS NO DELETE COMMAND');
else
dbms_output.put_line('THERE IS A DELETE COMMAND');
delete_flag := 'D';
v_check := instr(v_string_fnc, 'FROM ');
v_check := v_check + 5;
result_table := substr(v_string_fnc, v_check);
result_table := substr(result_table, 0, instr(result_table, ' '));
dbms_output.put_line('TABLE AFFECTED BY DELETE: ' || result_table);
end if;
/*SELECT SEARCH*/
v_check := instr(v_string_fnc, 'SELECT ');
if v_check < 1 then
dbms_output.put_line('THERE IS NO READ COMMAND');
else
dbms_output.put_line('THERE IS A READ COMMAND');
read_flag := 'R';
v_check := instr(v_string_fnc, 'FROM ');
v_check := v_check + 5;
result_table := substr(v_string_fnc, v_check);
result_table := substr(result_table, 0, instr(result_table, ' '));
dbms_output.put_line('TABLE AFFECTED BY READ: ' || result_table);
end if;
/*UPDATE SEARCH*/
v_check := instr(v_string_fnc, 'UPDATE ');
if v_check < 1 then
dbms_output.put_line('THERE IS NO UPDATE COMMAND');
else
dbms_output.put_line('THERE IS A UPDATE COMMAND');
update_flag := 'U';
v_check := instr(v_string_fnc, 'FROM ');
v_check := v_check + 5;
result_table := substr(v_string_fnc, v_check);
result_table := substr(result_table, 0, instr(result_table, ' '));
dbms_output.put_line('TABLE AFFECTED BY UPDATE: ' || result_table);
end if;
/*INSERT SEARCH*/
v_check := instr(v_string_fnc, 'INSERT ');
if v_check < 1 then
dbms_output.put_line('THERE IS NO CREATE COMMAND');
else
dbms_output.put_line('THERE IS A CREATE COMMAND');
insert_flag := 'C';
v_check := instr(v_string_fnc, 'FROM ');
v_check := v_check + 5;
result_table := substr(v_string_fnc, v_check);
result_table := substr(result_table, 0, instr(result_table, ' '));
dbms_output.put_line('TABLE AFFECTED BY CREATE: ' || result_table);
end if;
dbms_output.put_line(' ');
dbms_output.put_line('==========' || 'TABLE_NAME' || '==========' ||
'OPERATIONS' || '==');
dbms_output.put_line(empty_space || insert_flag || read_flag ||
update_flag || delete_flag);
dbms_output.put_line(underline);
end test_;
With that procedure I can extract and output my code, dbms needs a bit clean up but it will give the result I need.
Now a few questions, how to put a source code of my function to a variable that is not predefined, here is v_string_fnc but it needs to be predefined to work.
And how to link a certain operation with the table, here in my example is easy, one SELECT and keyword FROM that gives me a name of table.
Struggling continues
The bigger part it's done, just a tuning after this.
v_check := instr2(v_string_fnc, 'DROP ');
if v_check > 0 then
delete_flag := 'D';
v_check := instr2(v_string_fnc, 'TABLE ', v_check);
v_check := v_check + 6;
result_table := substr(v_string_fnc, v_check);
rest_string := result_table;
result_table := substr(result_table, 0, instr(result_table, ' '));
result_table := rtrim(result_table);
result_table := rtrim(result_table, ';');
merge into result_set
using dual
on (tables_used = result_table)
when matched then
update set drop_operation = delete_flag
when not matched then
insert
(tables_used, drop_operation)
values
(result_table, delete_flag);
while v_check > 0 loop
v_check := instr2(rest_string, 'DROP ');
if v_check > 0 then
delete_flag := 'D';
v_check := instr2(rest_string, 'TABLE ', v_check);
v_check := v_check + 6;
result_table := substr(rest_string, v_check);
rest_string := result_table;
result_table := substr(result_table, 0, instr(result_table, ' '));
result_table := rtrim(result_table);
result_table := rtrim(result_table, ';');
merge into result_set
using dual
on (tables_used = result_table)
when matched then
update set drop_operation = delete_flag
when not matched then
insert
(tables_used, drop_operation)
values
(result_table, delete_flag);
end if;
end loop;
end if;

pl sql and dynamic sql

I am trying to create some dynamic sql using the following code block
firstSqlStatement := true;
updateText := 'UPDATE T_EMPLOYEES SET ';
if FIRSTNAME IS NOT NULL and FIRSTNAME > 0 THEN
updateText:=updateText || ' firstName=' || FIRSTNAME || ' ';
firstSqlStatement := false;
end if;
if MIDDLENAME IS NOT NULL and length(MIDDLENAME) > 0 THEN
if firstSqlStatement = false THEN
updateText:=updateText || ',';
end if;
updateText:=updateText || ' middleName=' || MIDDLENAME || ' ';
firstSqlStatement := false;
end if;
updateText:=updateText
|| ' where upper(id)=upper(' || ID ||');';
DBMS_OUTPUT.put_line(updateText);
EXECUTE IMMEDIATE updateText;
The statement never executes properly as there are missing single quotes around values.
Any ideas what i can do to make this small example work or is there any better way of doing this?
firstSqlStatement := true;
updateText := 'UPDATE T_EMPLOYEES SET ';
if FIRSTNAME IS NOT NULL and FIRSTNAME > 0 THEN
updateText:=updateText || ' firstName=''' || FIRSTNAME || ''' ';
firstSqlStatement := false;
end if;
if MIDDLENAME IS NOT NULL and length(MIDDLENAME) > 0 THEN
if firstSqlStatement = false THEN
updateText:=updateText || ',';
end if;
updateText:=updateText || ' middleName=''' || MIDDLENAME || ''' ';
firstSqlStatement := false;
end if;
updateText:=updateText || ' where upper(id)=upper(' || ID || ');';
DBMS_OUTPUT.put_line(updateText);
EXECUTE IMMEDIATE updateText;
use '''
Maybe you can do it this way.
declare
ll_employee_id number := 10;
lv_firstname varchar2(30) := 'Thomas';
lv_middlename varchar2(30) := null;
begin
update t_employees
set firstname = decode(lv_firstname, null, firstname, lv_firstname),
middlename = decode(lv_middlename, null, middlename, lv_middlename)
where employee_id = ll_employee_id;
end;
DECLARE
my_error exception;
sql_stmt VARCHAR2 (500);
v_char_field VARCHAR2 (500);
v_number_field NUMBER;
v_stmt_number NUMBER;
BEGIN
sql_stmt := 'UPDATE TABLE';
IF 1 = 1 -- REPLACE WITH CONDITION FOR SELECTION FIELD
THEN
sql_stmt := sql_stmt || 'field_1 = :1';
v_stmt_number := 1;
ELSIF 1 = 1 -- REPLACE WITH CONDITION FOR SELECTION FIELD
THEN
sql_stmt := sql_stmt || 'field_2 = :1';
v_stmt_number := 2;
ELSE
DBMS_OUTPUT.put_line ('Field unmanaged');
RAISE my_error;
END IF;
IF 1 = 1 -- REPLACE WITH CONDITION FOR SELECTION TYPE FIELD
THEN
EXECUTE IMMEDIATE sql_stmt USING v_char_field;
ELSIF 1 = 1 -- REPLACE WITH CONDITION FOR SELECTION TYPE FIELD
THEN
EXECUTE IMMEDIATE sql_stmt USING v_number_field;
ELSE
DBMS_OUTPUT.put_line ('Type Field unmanaged');
RAISE my_error;
END IF;
DBMS_OUTPUT.PUT_LINE ('STATEMENT NUMBER : ' || v_stmt_number);
DBMS_OUTPUT.PUT_LINE ('TOTAL RECORD UPDATE : ' || SQL%ROWCOUNT);
EXCEPTION
WHEN my_error
THEN
NULL;
WHEN OTHERS
THEN
DBMS_OUTPUT.PUT_LINE ('ERROR :' || SQLERRM);
END;
You can use multiple selections to compose your statement for selection fields to be updated and for the type.