execute immediate in creating a table PL/SQL - sql

I would just like to ask why this code does not create the table?
BEGIN
EXECUTE IMMEDIATE 'create table temp1 as (select * from table)';
COMMIT;
END;
when I try this, it creates the table but no record/data.
BEGIN
EXECUTE IMMEDIATE 'drop table temp1';
EXECUTE IMMEDIATE 'create table temp1 as (select * from table)';
COMMIT;
END;
the table is a global temp table that is why there are no data when I select, but when I run the report, the output has data.
I am trying to fix a duplicate data error that is why I need to create the temp table.

Data in a global temp table (GTT) is only accessible to the session that inserted it; other sessions will only see their own data. It's a common misunderstanding that the data in a global temporary table is not "global" - only the table definition is "global", the data in that table is local to the session that inserted it, and automatically cleared when the session ends (or commits, depending on what type of GTT it is).
If your report queries a GTT and finds data, there must have been a process which populated the global temp table first.
When you ran your "create table" statement (which, by the way, does not need to be explicitly committed), it queried the GTT and found no records because the session in which you created the table did not first populate the GTT with the data needed.

Related

Dropping a Table in a PostgreSQL Delete Trigger

I am working on a web application where users create copies of a table.
They choose the name of the original table in a dropdown and the application creates a copy with a random name in the schema copy_tables.
The name of the copy table is inserted into the table config.copy_tables into the column copy_table_name.
There is no way for users to delete the copies. However an admin might manually delete an entry from config.copy_tables.
When that happens I would like to also drop the corresponding table in the schema copy_tables.
You find my attempt below. The copy_tables.OLD.copy_table_name part causes issues and I am not sure how to fix that. Basically I would like to:
drop the table in the schema copy_tables
whose name appeared in the column copy_table_name (config.copy_tables) in the row that was just deleted
CREATE OR REPLACE FUNCTION drop_copy_table()
RETURNS TRIGGER AS
$$
BEGIN
DROP TABLE copy_tables.OLD.copy_table_name;
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
DROP TRIGGER IF EXISTS trigger_delete_copy_table ON config.copy_tables;
CREATE TRIGGER trigger_delete_copy_table
AFTER DELETE ON config.copy_tables
FOR EACH ROW
EXECUTE PROCEDURE drop_copy_table();

PostgreSQL FOUND for CREATE TABLE statements

I am creating a function that will create a new table and insert informations about that table into other tables.
To create that table I am using the
CREATE TABLE IF NOT EXISTS
statement. Sadly it does not update the FOUND special variable in PostgreSQL nor can i find any other variable that would be updated.
Is there any way in PL/PGSQL to know whether that statement created a table or not?
The target of it is to not to double the informations in the other tables.
You may use CREATE TABLE AS in combination with ON_ERROR_ROLLBACK:
BEGIN;
-- Do inital stuff
\set ON_ERROR_ROLLBACK on
CREATE TABLE my_table AS
SELECT id, name FROM (VALUES (1, 'Bob'), (2, 'Mary')) v(id, name);
\set ON_ERROR_ROLLBACK off
-- Do remaining stuff
END;
To put it bluntly, with \set ON_ERROR_ROLLBACK on postgres will create a savepoint before each statement and automatically rollback to this savepoint or releasing it depending on the success of that statement.
The code above will execute initial and remaining stuff even if the table creation fails.
No, there are not any information if this command created table or not. The found variable is updated after query execution - not after DDL command. There is guaranteed so after this command, the table will be or this command fails to an exception.

Should i commit at the end of the procedure which is called by an oracle scheduler job

I am running an oracle JOB which will run a PROCEDURE to CREATE TRUNCATE INSERT DROP some relevant tables.
Is this the best way to do a functionality like this ?
Should I Commit at the end of the procedure or not ?
CREATE OR REPLACE Procedure PR_NAME
IS
BEGIN
CREATE TABLE TABLE_1_BAC AS SELECT * FROM TABLE1_VIA_DBLINK;
TRUNCATE TABLE TABLE_1;
INSERT INTO TABLE_1 SELECT * FROM TABLE_1_BAC;
DROP TABLE TABLE_1_BAC;
--COMMIT;
EXCEPTION
WHEN OTHERS THEN
raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
END;
To create TABLE_1 only once for present data :
CREATE TABLE TABLE_1 AS SELECT * FROM TABLE1_VIA_DBLINK;
and creating an insert trigger for TABLE1_VIA_DBLINK, populating TABLE_1 through this trigger for new datas, and to get rid of this job and procedure seems more feasible.
As you stay in this job, perhaps you'll wait for huge data to be inserted.
By the way, if you insist on using this job, you don't need to issue commit, since and there's already an implicit commit exists inside job mechanism.
What kind of job do you use? JOB or SCHEDULER JOB?
I don't see any reason to DROP/CREATE the table. I don't see any reason why you use the intermediate table at all.
Simply make
CREATE OR REPLACE Procedure PR_NAME
IS
BEGIN
EXECUTE IMMEDIATE 'TRUNCATE TABLE TABLE_1';
INSERT INTO TABLE_1 SELECT * FROM TABLE1_VIA_DBLINK;
COMMIT;
END;
You don't need any exception handler. In case of JOB you will not see the exception anyway. In case of SCHEDULER JOB you can see exception in views
*_SCHEDULER_JOB_LOG
*_SCHEDULER_JOB_RUN_DETAILS
If you make just this kind of operation you should consider MATERIALIZED VIEW which basically make the same: TRUNCATE and INSERT INTO ... SELECT * FROM ...
No. You don't need to commit.
Those commands are DDL (Data Definition Language) in SQL. So Oracle Database will issue a commit together with the command.
DML (Data Manipulating Language) - like SELECT, UPDATE, INSERT, DELETE requires a commit.
In a scenario, where you will update, delete and insert records. Then you ran a create table command. The records inserted, updated and deleted will be committed (save) to the database.

Oracle Merge Sql with insert in destination and delete from source

I have a Scenario where i have 2 Tables 1st is source(my_data) and 2nd is destination(my_data_backup),I want to some kind of archiving of actual data and move that data into backup table on the daily basis and delete from source table using Merge SQL in oracle.
i.e.
my_data and my_data_backup both have same schema
my_data table contains 10 rows and my_data_backup contains 0 rows i want to insert 10 records into my_data_backup and delete those records from my_data.
MERGE is useful to do manipulation on the destination table, not source.
You can use an anonymous PLSQL block:
begin
delete from my_data_backup;
insert into my_data_backup
select *
from my_data;
delete from my_data;
commit;
exception
when others then
rollback;
-- handle here
end;
/
You can also put the above in a procedure and call the procedure.
You can think about using truncate statement instead of delete which will be faster when the table size is larger but be careful that it, being a DDL, will do an implicit commit.
execute immediate 'truncate table tablename';

Oracle Sql : Procedure which can create temporary tables inside it

I am new to Oracle Sql and facing an issue :
I want to create a temporary table inside procedure .
LIKE:
CREATE PROCEDURE P
AS
BEGIN
CREATE TEMPORARY TABLE A(ID int);
END P;
BUT THIS IS GIVING ME AN ERROR
How Can I Create a temporary table inside procedure.
I have seen other answers on stackoverflow but that doesn't answer my question properly
Can you please help me out ?
Why do you want to create a temporary table in a stored procedure in the first place?
It is relatively common to create temporary tables in other databases (SQL Server and MySQL, for example). It is very, very rare to do the same thing in Oracle. In almost every case where you are tempted to create a temporary table in Oracle, there is a better architectural approach. There is a thread over on the DBA stack that discusses alternatives to temporary tables and why they are not commonly needed in Oracle.
Programmatically, you can create objects using dynamic SQL
CREATE OR REPLACE PROCEDURE dont_do_this
AS
BEGIN
EXECUTE IMMEDIATE 'CREATE GLOBAL TEMPORARY TABLE a( id INTEGER )';
END;
If you create a temporary table dynamically, however, every reference to that table will also need to be via dynamic SQL-- you won't be able to write simple SELECT statements against the table. And the definition of a temporary table in Oracle is global so it is visible to every session. If you have two different sessions both trying to create the same table, the second session will get an error. If you expect the table to have a different definition in different sessions, you've got even more problems.
You could use Dynamic SQL with EXECUTE IMMEDIATE:
CREATE OR REPLACE
PROCEDURE p
AS
BEGIN
EXECUTE IMMEDIATE 'CREATE TEMPORARY TABLE A(id NUMBER)...etc';
END p;
Edit: Obviously you'll have to ensure your syntax is correct within the EXECUTE IMMEDIATE statement.
Hope it helps.
You must declare your procedure as:
create or replace PROCEDURE MYPROCEDURE AUTHID CURRENT_USER IS
script varchar(4000);
BEGIN
script:= 'CREATE GLOBAL TEMPORARY TABLE BNMCODIAGNOSTICASSOCIE_TEMP
ON COMMIT PRESERVE ROWS
as select ........';
EXECUTE IMMEDIATE script;
commit;
END;