I was wondering if there is someway i can handle a exception if i get an error while creating a table during a procedure.
IF testes=0 then
stmt:= 'create table ' || prefix || SII_BCK_TAB_ID_SEQ.nextval || ' AS SELECT * FROM '|| n_tab || ' WHERE 1=0';
EXECUTE IMMEDIATE stmt;
can i create a exception after executing the statement? what is the best process to handle errors while creating a table? or is it the same as handling dml statements?
can i insert something like savepoints?
thank you
If I were you, I'd create a separate procedure to handle the table creation and then have an exception clause. This makes it modular code, then; easy to unit test, etc.
e.g.: the procedure would look something like:
PROCEDURE create_table (in_new_table_name in varchar2,
in_old_table_name in varchar2)
is
E_TAB_EXISTS EXCEPTION;
PRAGMA EXCEPTION_INIT(E_TAB_EXISTS,-955);
BEGIN
execute immediate 'create table ' || in_new_table_name || ' AS SELECT * FROM '|| in_old_table_name || ' WHERE 1=0';
EXCEPTION
WHEN E_TAB_EXISTS THEN
NULL;
END create_table;
and you would call it like:
If testes = 0 then
create_table(in_new_table_name => prefix || sii_bck_tab_id_seq.nextval,
in_old_table_name => n_tab);
...
end if;
Ideally, you're creating your code in a package, and can simply have the new procedure as a separate procedure in the package.
Related
I am new to Oracle so please sorry the question that seems to be very easy for you.
I need to get the following procedure with UPDATE query with replace function
CREATE OR REPLACE PROCEDURE proc_replace_space_1
(
p_table user_tables.table_name%TYPE,
p_search IN varchar2,
p_replace IN varchar2
)
IS
BEGIN
EXECUTE IMMEDIATE
'update ' || p_table ||
'set docnum = replace(docnum, :2, :3 )'
USING p_search, p_replace;
END;
This procedure removes all spaces.
But when I call it
BEGIN
proc_replace_space_1('cm_risk.fct_loans_temp', ' ', '');
END;
I've got the following error
SQL Error [971] [42000]: ORA-00971: missing SET keyword
ORA-06512: at "CM_RISK.PROC_REPLACE_SPACE_1", line 9
ORA-06512: at line 2
How can I modify my code to handle the problems?
Thank you.
Dynamic SQL is hard because it turns compilation errors into runtime errors. So I urge you to acquire the good habit of assembling your dynamic SQL as string variables which you can persist to a log table if you have such a thing (and if you don't it would be another good habit to acquire) or display using dbms_output.put_line.
So your procedure would look like this:
CREATE OR REPLACE PROCEDURE proc_replace_space_1
(
p_table user_tables.table_name%TYPE,
p_search IN varchar2,
p_replace IN varchar2
)
IS
l_sql varchar2(32767);
BEGIN
l_sql := 'update ' || p_table ||
'set docnum = replace(docnum, :2, :3 )';
EXECUTE IMMEDIATE
l_stmt
USING p_search, p_replace;
exception
when others then
dbms_output.put_line(l_sql);
raise;
END;
This approach allows you to see the actual SQL your procedure executed. Probably you'll be able to spot the syntax error immediately (in this case it's the missing space between table name and set). Otherwise you can try to run the statement for yourself and see what the SQL compiler highlights.
NB: depending on your environment you may need to enable DBMS_OUTPUT before you can see the message.
You just need to add a space before set. Currently your table name is appended to set keyword and it is assuming it as a table name i.e MyTableSet
CREATE OR REPLACE PROCEDURE proc_replace_space_1
(
p_table user_tables.table_name%TYPE,
p_search IN varchar2,
p_replace IN varchar2
)
IS
BEGIN
EXECUTE IMMEDIATE
'update ' || p_table ||
' set docnum = replace(docnum, :2, :3 )'
USING p_search, p_replace;
END;
I created procedure in oracle that drops my table and creates same table from my view. But I have some problems with running this procedure. First step with drop table works but copying it doesn't work.
It this a good procedure ?
create or replace PROCEDURE transfer_table (table_name IN VARCHAR2,tableFrom IN VARCHAR2) IS
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE ' || table_name;
EXECUTE IMMEDIATE 'CREATE TABLE ' || table_name || ' AS SELECT * FROM ' || tableFrom;
commit;
END transfer_table;
Next I click on this procedure and change the variable then view and click ok, but only the first step of dropping the table is working. What am I doing wrong ?
I think you need to catch the error if the table you are creating doesn't exist.
create or replace PROCEDURE transfer_table (table_name IN VARCHAR2,tableFrom IN VARCHAR2) IS
BEGIN
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE ' || table_name;
EXCEPTION WHEN OTHERS THEN
NULL;
END;
EXECUTE IMMEDIATE 'CREATE TABLE ' || table_name || ' AS SELECT * FROM ' || tableFrom;
commit;
END transfer_table;
I have a stored procedure to truncate the table whose name is passed as a parameter to the procedure.
create or replace procedure delete_data_from_table(table_id VARCHAR2)
is
cursor table_cur is
SELECT table_name FROM all_tables WHERE table_name LIKE '%' || table_id || '%';
tab_name VARCHAR2(25);
BEGIN
open table_cur;
LOOP
FETCH table_cur into tab_name;
exit when table_cur%notfound;
EXECUTE IMMEDIATE 'TRUNCATE TABLE ' || tab_name;
END LOOP;
close table_cur;
END;
I want to display the output of the execute immediate statement using DBMS_OUTPUT.PUT_LINE. Is it possible to do so?
Thanks in advance.
There is no native output from execute immediate or the statement you are running. When you truncate a table in a client it will usually report something like:
Table truncated.
or
Table MY_TABLE truncated.
or similar; but those messages are generated by the client running the command, not by the database.
You can just generate whatever message you want in your procedure, e.g.:
...
LOOP
FETCH table_cur into tab_name;
exit when table_cur%notfound;
EXECUTE IMMEDIATE 'TRUNCATE TABLE ' || tab_name;
DBMS_OUTPUT.PUT_LINE('Table ' || tab_name || ' truncated.');
END LOOP;
...
If the truncate statement fails for any reason then it will throw an exception and it won't reach the dbms_output line.
For other statement types you can optionally use SQL%ROWCOUNT to report the number of rows inserted/updated/merged/deleted to mimic what your client might show for those, but that doesn't apply for truncation.
Bear in mind though that someone else running your code might not have display of those messages enabled.
I've been trying to get this procedure working for the last few hours:
CREATE OR REPLACE PROCEDURE Search_Testimonials(keyword VARCHAR2)
AS
l_cursor_1 SYS_REFCURSOR;
Temp_Content VARCHAR(255);
BEGIN
OPEN l_cursor_1 FOR
SELECT T_Content
INTO Temp_Content
FROM Testimonial
WHERE T_Content LIKE '%' || Keyword || '%';
dbms_output.put_line(Temp_Content);
DBMS_SQL.RETURN_RESULT(l_cursor_1);
END;
It's pretty much supposed to run through the testimonials table and output every row that has an instance of the keyword in the parameter.
It compiles with no errors but when i execute like so:
EXECUTE Search_Testimonials('someword');
I get this error: "anonymous block completed".
Does anyone know what's going on? I'm new to PL/SQL and am running out of resources on the internet or just don't understand what I'm reading.
-I'm running this all in oracle sql developer.
You are mixing metaphors here. You either need to use all dynamic SQL syntax here or none at all.
However you do not really need dynamic SQL for what you are doing, just make the l_cursor_1 type as an out parameter.
Try something like this:
<code>
CREATE OR REPLACE PROCEDURE Search_Testimonials(keyword VARCHAR2 IN,
oResults IN OUT l_cursor_1,
oStatus OUT VARCHAR)
IS
type l_cursor_1 is REF CURSOR;
-- Temp_Content VARCHAR(255);
err_code varchar2(30);
err_msg varchar2(200);
BEGIN
oStatus := "1";
OPEN oResults FOR
SELECT T_Content
FROM Testimonial
WHERE T_Content LIKE '%' || Keyword || '%';
oStatus := "0";
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
WHEN OTHERS THEN
oStatus := "2";
err_code := SQLCODE;
err_msg := SUBSTR (SQLERRM, 1, 200);
DBMS_OUTPUT.PUT_LINE('ERROR: '|| err_code || ' : ' || err_msg );
-- RAISE;
END Search_Testimonials;
</code>
Check the oStatus before processing the output if it's 2 you have an error or if 1 no data.
You can extend the Exception processing by inserting the error code, message, proc name into an error table.
Also for performance reasons I would not use the %Keyword% construct by default. use Keyword% as default and pass "% some keyword" to do the same. If you have a index on the column it will never be used with %Keyword% construct ....
Hope this helps
Nick
I have a procedure that has an execute immediate statement. Within that execute immediate statement calls a procedure that has two out parameters. I'm having trouble trying to obtain those out parameters to be used in the procedure calling the execute immediate statement.
execute_stmt := 'DECLARE pi_error_log_rec error_log%ROWTYPE; p_plan_id NUMBER; begin SCHEMA.PACKAGE_NAME.' ||
PROCEDURE || '(' ||
p_audit_log_id || ', ' ||
V_PARAMETER1 || ', ' || '''' ||
V_PARAMETER2 || '''' ||
', p_plan_id, pi_error_log_rec); end;';
execute immediate execute_stmt;
if(pi_error_log_rec.error_text IS NOT NULL) THEN
--do stuff;
ELSE
--do stuff;
The out parameters are p_plan_id and pi_error_log_rec, the remaining are IN parameters. So I need to obtain those two outputs for use inside the procedure calling this execute immediate. But it's not setting the output in the variable. Am I missing a step or should I use a different approach in using out parameters?
Try this one:
execute_stmt := 'Begin SCHEMA.PACKAGE_NAME.PROCEDURE(:p_audit_log_id, :V_PARAMETER1, :V_PARAMETER2); END;';
execute immediate execute_stmt USING IN p_audit_log_id, OUT pi_error_log_rec, OUT p_plan_id;
Since Oracle 12c you can also fetch PL/SQL datatypes (like RECORDS, BOOLEAN) into dynamic SQL. In earlier versions you where limited to SQL datatypes only (like NUMBER, VARCHAR2, etc.)