Log an already executed query to a table - oracle

I have a PL/SQL block:
begin
...
delete table1
where date = l_date
and name = l_name
and code = l_code;
...
end;
I want to log this query into my own debug_table, but I don't want to just use a copied query (as in copy paste this as an insert to my debug_table). Is there a way to somehow log this query that was executed and insert it into my debug_table?

Related

FollowUp:How to use partition name as a parameter in the select statement?

Based on this post: How to use partition name as a parameter in the select statement? I have tried to replicate it, but no success. I get error message "ORA-00922" Invalid or missing option. It must be something small syntax issue, but not sure where is it exactly. Here my code:
DECLARE
TYPE PROD_TAB IS TABLE OF DBA_TAB_PARTITIONS%ROWTYPE;
PRODUCTS_TAB PROD_TAB := PROD_TAB();
START_TIME NUMBER;
END_TIME NUMBER;
BEGIN
SELECT *
BULK COLLECT
INTO products_tab
FROM dba_tab_partitions t
WHERE table_name = 'LST_COLL';
FOR i in products_tab.first .. products_tab.last LOOP
EXECUTE IMMEDIATE 'CREATE TABLE test_partition_copy
PARALLEL NOLOGGING
("ID", datetime, ...)
SELECT * FROM test_partition PARTITION (||products_tab(i).partition_name||)';
COMMIT;
END LOOP;
COMMIT;
END;
You need the PL/SQL variable to be injected via string concatenation; you're missing some single quotes:
EXECUTE IMMEDIATE 'CREATE TABLE test_partition_copy
(id, datetime, ...)
PARALLEL NOLOGGING
AS SELECT id, datetime, ...
FROM test_partition PARTITION ("' || products_tab(i).partition_name || '")';
You also need the AS keyword; the PARALLEL NOLOGGING clauses come after the new table's column-name list; it's better to list the columns explicitly in both parts of the statement; and I've included double-quotes around the partition name just in case.
If you build up your dynamic statement as a string variable, you can inspect that (e.g. via dbms_output) to look for errors, or even try to run it manually to get a better idea exactly where the error is happening, depending on your client. You can then do EXECUTE IMMEDIATE <string_variable>.
You still have an issue in that you're trying to create a table with the same name - test_partition_copy - each time; the first time round the loop for the first partition you might create that table OK, but the second loop for the second partition will get an error because the table already exists.
Incidentally, DDL commits implicitly, so you don't need the explicit commit.

creating table if not exist pl/sql with oracle 12c

i need to create a script that do this thing:
check if the table exists, if exists truncate(or drop and create) table else create that table. i try to search on internet but some code work for half or not work at all.
this is one of script i found on internet
DECLARE
val INTEGER := 0;
BEGIN
SELECT COUNT(*) INTO val FROM user_tables WHERE table_name = 'tabella';
IF val = 1 THEN
EXECUTE IMMEDIATE ('TRUNCATE TABLE tabella');
ELSE
EXECUTE IMMEDIATE ('CREATE TABLE tabella(idTabella INTEGER NOT NULL, campo VARCHAR(50)');
END IF;
END;
You don't need to check if the table exists; just try to truncate the table and if the table does not exist then catch the exception and create the table:
DECLARE
table_not_exists EXCEPTION;
PRAGMA EXCEPTION_INIT( table_not_exists, -942 );
BEGIN
EXECUTE IMMEDIATE 'TRUNCATE TABLE tabella';
DBMS_OUTPUT.PUT_LINE( 'truncated' );
EXCEPTION
WHEN table_not_exists THEN
EXECUTE IMMEDIATE 'CREATE TABLE tabella ( idTabella INTEGER NOT NULL, campo VARCHAR(50) )';
DBMS_OUTPUT.PUT_LINE( 'created' );
END;
/
db<>fiddle
Since table names are saved as upper case strings, you should check them the same case. There are to ways you can do this:
You can write your table name in upper case like:
SELECT COUNT(*) INTO val FROM user_tables WHERE table_name = 'TABELLA';
You can lower case your table_name column so you can input it lower case all the time:
SELECT COUNT(*) FROM user_tables WHERE LOWER(table_name) = 'tabella';
Hope this helps.
The database defaults all names to UPPER_CASE. When you execute
CREATE TABLE tabella(...
the database actually creates the table with a name of TABELLA. This is fine - unless you quote the name of an object, by surrounding it in double-quotes, the database will automatically convert all names to upper case, and everything will work just fine. The only time you need to remember to use UPPER_CASE names is when you're accessing system tables or views, such as USER_TABLES. If you change the query in your script to
SELECT COUNT(*) INTO val FROM user_tables WHERE table_name = 'TABELLA';
I think you'll find it works just fine.

Result of Stored Procedure save in table variable

I have question: I have stored procedure A(return three out paramters). I want to call procedure A in loop and insert these three parameters into temporaty table and return this table.
DECLARE
Type TestTable IS TABE OF NUMBER; -- for example one parameter!!!
myTable TestTable;
BEGIN
LOOP
A(o_param1, o_param2, o_param3);
-- myTable insert o_param1,2,3;
-- insert into myTable values(99); - here I have error PL/SQL: ORA-00942: table or view does not exist
END LOOP;
SELECT * FROM myTable;
END;
I dont know how to do -- myTable insert o_param1,2,3;. Please help me.
write insert statement inside the loop. so for each loop you can have the values inserted to the table and give a commit after the loop.
But you cannot have a select * from table inside the anonymous block. Remove that from the block and after end; you can try running select * from table to see the output.
BEGIN
LOOP
A(o_param1, o_param2, o_param3);
-- myTable insert o_param1,2,3;
insert into myTable values (o_param1, o_param2, o_param3);
END LOOP;
commit;
--SELECT * FROM myTable;-
END;
SELECT * FROM myTable;
> Blockquote
First, you cannot insert data into myTable directly (insert into myTable) because Oracle table types, declared in a declare section of the script, are not visible in sql statements (exception - insert using 'bulk collect' with types, declared in Oracle dictionary).
Even if you insert data in myTable using myTable(idx)... you can not select it outside the script because myTable exists only inside the script.
I think the simpliest way is to create usual table or global temporary table. If you will use global temporary table create it with 'ON COMMIT PRESERVE ROWS' (if you use commit after insert)

How to display the updated values of different tables using Stored procedure displayed Oracle

// Below update statement is present in my Stored procedure. I am passing two parameters (parameter 1 and parameter 2) while executing the Stored procedure. Once executing the Stored procedure i want the different updated values to be displayed. please provide the code for the below example(my stored procedure)
CREATE OR REPLACE PROCEDURE UPDATE_TABLE(parameter1 IN NUMBER, parameter IN varchar2)
AS
BEGIN
UPDATE Table1 SET column_a = (parameter1 +2) WHERE id= parameter2;
update Table2 set column_b= parameter1 where id=parameter2;
END UPDATE_TABLE
Use returning clause + bulk collect. I don't know for what purpose you need this updated data to be displayed. Below approach for one of your table. You can share it to others.
DECLARE
TYPE t_type is table of VARCHAR2(250);
l_type t_type;
begin
UPDATE Table1 SET column_a = (parameter1 +2) RETURNING column_a BULK COLLECT INTO l_type;
FOR i IN 1..l_type.count
LOOP
DBMS_OUTPUT.PUT_LINE(l_type(i));
END LOOP;
END;

execute query defined in column as String

Hello again I need some help,
I have table where in column "query" is defined query statement. I would like to run it and as output get the result.For example:
Create table table1
(
ID Number,
Query Varchar2(400)
)
insert into table1(id,query) values (1,'select name from table2 where table2.id=table1.id and table2.type = variable');
create table table2
(ID number,
Name varchar2(400),
Type Varchar2(400)
)
insert into table2 values (1,'Mathew','M');
insert into table2 values (1,'Thomas','G');
insert into table2 values (2,'Jerry','P');
For now query :
'select name from table2 where table2.id=table1.id and table2.type = variable'
should return only "Mathew" (assuming variable as 'M' - procedure variable input)
As procedure input I want to have variable which I will replace somehow in query statement.
Could you give me some tips how to handle with that?
------------Edit
I did stmh like that:
create or replace procedure queryrun
(var1 varchar2) as
str VARCHAR2(200);
BEGIN
execute immediate 'select replace(query,''variable'','''||var1||''') from table1' into str;
dbms_output.put_line('Value is '||str);
END;
But as result it present query... no result of select statement...
You are only selecting your query, not running it; and you're replacing the string "'variable'" - including the single quotes - with your value, but your original query string doesn't have the single quotes around it - so nothing matches.
You should not really substitue a hard-coded value anyway. Change your stored query to include a bind variable placeholder instead:
insert into table1(id,query)
values (1,'select name from table2 where table2.id=table1.id and table2.type = :variable');
Although that query is invalid anyway - you don't have table1 defined in the from clause or a join clause. When you have a valid query you can run standalone, use that, but with a bind variable (denoted by the leading colon).
But let's assume you have a valid query string in your table, that will only return one row, say:
insert into table1(id,query)
values (1,'select name from table2 where type = :variable');
Your procedure then needs a local variable to hold that query string. You select your query into that using static SQL, and then use dynamic SQL via execute immediate to run the query from that string, and provide the bind value with the using clause. The result goes into another local variable, which you are already doing.
So a simple version might look like this:
create or replace procedure queryrun (p_var1 varchar2) as
l_query table1.query%type;
l_name table2.name%type;
begin
select query into l_query from table1 where id = 1;
execute immediate query into l_name using p_var1;
dbms_output.put_line('Value is ' || l_name);
end;
This is obviously rather contrived. If you have multiple queries in your table, and perhaps pass a second ID variable into the procedure to choose which one to run, they would all have to take a single bind variable, and would have to all be able to put the result into the same type and size of result variable. You're also restricted to queries that return exactly one row. You can adapt and extend this of course, but hopefully this will get you started.
You can have bind variable and use plsql execute immediate.
Examples:
http://www.dba-oracle.com/t_oracle_execute_immediate.htm

Resources