How to create multiple tables(like test1-test100 in a sequence) from a sourcetable 'test' in Athena? - sql

I know create table as select * from table (CTA)S works for 1 table here but, I need to CTAS 1-100 tables in a single command with no data,Can someone help here to give a script that works in ATHENA.
I tried a for loop that works with oracle but here in Athena it doesnt work as single statement
begin
for idx in 1..100 loop
execute immediate
'Create table test'|| idx ||' AS
Select *
FROM test2 WITH NO DATA'
end loop;
end;

Related

Postgresql - Union table values from different schemas in a database into one table

I have a Database called Knowledge in postgres. It has multiple schemas and every schema has same number of tables, table has same columns as well.
Now I want to create a new schema called Aggregate, table called aggregate.table1 and put values from schema1.table1 and schema2.table1 in it.
I need to add another column in Aggregate.table1 which holds the value representing schema.
If any value in schema1.table1 is updated then aggregate.table1 should get the updated values.
Question,
Is it possible in Postgresql? if so please help me with this.
I need this aggregated table for further processing
You can try writing an anonymous code block to iterate over all schemas and tables, so that you can import your data into the aggregate schema. The following block search for all tables contained in the schemas s1 and s2, creates a corresponding table in the schema s_agg and finally copies its records.
DO $$
DECLARE row record;
BEGIN
FOR row IN SELECT * FROM pg_tables WHERE schemaname IN ('s1','s2') LOOP
EXECUTE 'CREATE TABLE IF NOT EXISTS s_agg.'||quote_ident(row.tablename)||
' AS TABLE ' || quote_ident(row.schemaname)||'.'|| quote_ident(row.tablename) ||
' WITH NO DATA;';
EXECUTE 'INSERT INTO s_agg.' || quote_ident(row.tablename)
|| ' SELECT * FROM '||quote_ident(row.schemaname)||'.'||quote_ident(row.tablename);
END LOOP;
END;
$$;
Demo
CREATE SCHEMA s1;
CREATE SCHEMA s2;
CREATE SCHEMA s_agg;
CREATE TABLE s1.t1 (id int);
INSERT INTO s1.t1 VALUES (1);
CREATE TABLE s2.t1 (id int);
INSERT INTO s2.t1 VALUES (42);
DO $$
DECLARE row record;
BEGIN
FOR row IN SELECT * FROM pg_tables WHERE schemaname IN ('s1','s2') LOOP
EXECUTE 'CREATE TABLE IF NOT EXISTS s_agg.'||quote_ident(row.tablename)||
' AS TABLE ' || quote_ident(row.schemaname)||'.'|| quote_ident(row.tablename) ||
' WITH NO DATA;';
EXECUTE 'INSERT INTO s_agg.' || quote_ident(row.tablename)
|| ' SELECT * FROM '||quote_ident(row.schemaname)||'.'||quote_ident(row.tablename);
END LOOP;
END;
$$;
-- contains values of t1 from s1 and s2
SELECT * FROM s_agg.t1;
id
----
1
42
Note: This code works with the assumption that the aggregate schema is either empty or it has empty tables, otherwise data will be duplicated. If you run this periodically and the size of your tables isn't too large, you can add a DROP TABLE before the CREATE TABLE statement. To make it work on every commit on all tables of all schemas you have to take a look at TRIGGERS or even logical replication.

Delete all data from a table after selecting all data from the same table

All i want is to select all rows from a table and once it is selected and displayed, the data residing in table must get completely deleted. The main concern is that this must be done using sql only and not plsql. Is there a way we can do this inside a package and call that package in a select statement? Please enlighten me here.
Dummy Table is as follows:
ID NAME SALARY DEPT
==================================
1 Sam 50000 HR
2 Max 45000 SALES
3 Lex 51000 HR
4 Nate 66000 DEV
Any help would be greatly appreciated.
select * from Table_Name;
Delete from Table_Name
To select the data from a SQL query try using a pipelined function.
The function can define a cursor for the data you want (or all the data in the table), loop through the cursor piping each row as it goes.
When the cursor loop ends, i.e. all data has been consumed by your query, the function can perform a TRUNCATE table.
To select from the function use the following syntax;
SELECT *
FROM TABLE(my_function)
See the following Oracle documentation for information pipelined functions - https://docs.oracle.com/cd/B28359_01/appdev.111/b28425/pipe_paral_tbl.htm
This cannot be done inside a package, because " this must be done using sql only and not plsql". A package is PL/SQL.
However it is very simple. You want two things: select the table data and delete it. Two things, two commands.
select * from mytable;
truncate mytable;
(You could replace truncate mytable; with delete from mytable;, but this is slower and needs to be followed by commit; to confirm the deletion and end the transaction.)
Without pl/sql it's not possible.
Using pl/sql you can create a function which will populate a row, and then delete
Here is example :
drop table tempdate;
create table tempdate as
select '1' id from dual
UNION
select '2' id from dual
CREATE TYPE t_tf_row AS OBJECT (
id NUMBER
);
CREATE TYPE t_tf_tab IS TABLE OF t_tf_row;
CREATE OR REPLACE FUNCTION get_tab_tf RETURN t_tf_tab PIPELINED AS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
FOR rec in (select * from tempdate) LOOP
PIPE ROW(t_tf_row(rec.id));
END LOOP;
delete from tempdate ; commit;
END;
select * from table(get_tab_tf) -- it will populate and then delete
select * from tempdate --you can check here result of deleting
you can use below query
select * from Table_demo delete from Table_demo
The feature you seek is SERIALIZABLE ISOLATION LEVEL. This feature enables repeatable reads, which in particular guarantee that both SELECTand DELETEwill read and process the same identical data.
Example
Alter session set isolation_level=serializable;
select * from tempdate;
--- now insert from other session a new record
delete from tempdate ;
commit;
-- re-query the table old records are deleted, new recor preserved.

Create Populate, Then Delete a Table from Within a View (Oracle)

I have a view that compares the data in two tables (tableYesterday and tableToday) and outputs a result based on the comparison. Lets call this view: ViewComp.
I have a need to do more than this. WIthin a single view, I actually need to:
create or replace tableToday and pre-populate it.
execute the ViewComp query.
replace tableYesterday with tableToday.
I have researched things like nested views but I could not find a way to perform 1 and 3 from within the view. I would be grateful for any ideas. Thank you.
This is almost certainly a bad idea. Views shouldn't "do" anything.
For those extremely rare cases where this is required, it can be done with the tricks below. You will definitely want to document this code, to explain to other people what you're doing and why.
Sample schema and objects
--Create table.
create table tableYesterday(a number, b number);
--Create abstract data type to hold one row of data to be returned by the view.
create or replace type ViewComp_type is object
(
a number,
b number
);
--Create nested table to hold multiple rows of data to be returned by the view.
create or replace type ViewComp_nt is table of ViewComp_type;
Function to return results
--Create function to return data.
create or replace function ViewComp_function return ViewComp_nt authid current_user as
--This pragma is necessary for a function that will perform DML.
pragma autonomous_transaction;
v_results ViewComp_nt;
v_name_already_exists exception;
pragma exception_init(v_name_already_exists, -955);
begin
--Try to create today's table. Ignore errors if it exists.
begin
execute immediate 'create table tableToday(a number, b number)';
exception when v_name_already_exists then
execute immediate 'truncate table tableToday';
end;
--Populate today's table.
execute immediate 'insert into tableToday values(1,1)';
--Get the difference.
execute immediate q'[
select cast(collect(ViewComp_type(a,b)) as ViewComp_nt)
from
(
select * from tableToday
minus
select * from tableYesterday
)
]' into v_results;
--Remove yesterday's data.
execute immediate 'truncate table tableYesterday';
--Replace it with today's data.
execute immediate 'insert into tableYesterday select * from tableToday';
commit;
--Return the difference.
return v_results;
end;
/
Create the view to return the function's data
create or replace view ViewComp as
select * from table(ViewComp_function);
Test Run
--First execution:
select * from ViewComp;
A B
- -
1 1
--Second execution:
select * from ViewComp;
A B
- -
You can't do such things in view. You can either create PL/SQL procedure to perform your steps or create materialised view.

looping and executing dynamic query in Oracle

I'm having some trouble truncating some tables that get generated in my base.
The table names get saved and I can do it manually, but I wanted to see if it could be automated until its fixed.
What I've done so far is get all the table names and a id/number into my own help table. My errors begin around the loop/Execute immediate where im not sure how to use the data I've gotten in the syntax and i cant find any similar examples.
create table HlpTruncTable as SELECT SUBSTR(argument, 3) as tblName, rownum as Nr
FROM tblLogHlp
WHERE status = 'E' and argument like '0,awfh%' and LAST_UPDATE <= ADD_MONTHS(sysdate,-1);
for i in 1..(select max(nr) from HlpTruncTable) LOOP
execute immediate TRUNCATE TABLE (select tblName from HlpTruncTable where nr = (i));
END LOOP;
drop table hlpTruncTable;
I would do it like this:
declare
cursor HlpTruncTable is
SELECT SUBSTR(argument, 3) as tblName
FROM tblLogHlp
WHERE status = 'E' and argument like '0,awfh%' and LAST_UPDATE <= ADD_MONTHS(sysdate,-1);
BEGIN
FOR aTable IN HlpTruncTable LOOP
execute immediate 'TRUNCATE TABLE '||aTable.tblName;
END LOOP;
END;

How to execute sql query on a table whose name taken from another table

I have a table that store the name of other tables. Like
COL_TAB
--------------
TABLE_NAME
--------------
TAB1
TAB2
TAB3
What i want to do is that, i want to run a sql query on table like this,
SELECT * FROM (SELECT TABLE_NAME from COL_TAB WHERE TABLE_NAME = 'TAB1')
Thanks
An Oracle SQL query can use a dynamic table name, using Oracle Data Cartridge and the ANY* types. But before you use those advanced features, take a step back and ask yourself if this is really necessary.
Do you really need a SQL statement to be that dynamic? Normally this is better handled by an application that can submit different types of queries. There are many application programming languages and toolkits that can handle unexpected types. If this is for a database-only operation, then normally the results are stored somewhere, in which case PL/SQL and dynamic SQL are much easier.
If you're sure you've got one of those rare cases that needs a totally dynamic SQL statement, you'll need something like my open source project Method4. Download and install it and try the below code.
Schema Setup
create table tab1(a number);
create table tab2(b number);
create table tab3(c number);
insert into tab1 values(10);
insert into tab2 values(20);
insert into tab3 values(30);
create table col_tab(table_name varchar2(30), id number);
insert into col_tab values('TAB1', 1);
insert into col_tab values('TAB1', 2);
insert into col_tab values('TAB1', 3);
commit;
Query
select * from table(method4.dynamic_query(
q'[
select 'select * from '||table_name sql
from col_tab
where id = 1
]'));
Result:
A
--
10
You'll quickly discover that queries within queries are incredibly difficult. There's likely a much easier way to do this, but it may require a design change.
I don't have a database by hand to test this but I think you are looking for something like this:
DECLARE
-- Create a cursor on the table you are looking through.
CURSOR curTable IS
SELECT *
FROM MainTable;
recTable curTable%ROWTYPE;
vcQuery VARCHAR2(100);
BEGIN
-- Loop through all rows of MainTable.
OPEN curTable;
LOOP
FETCH curTable INTO recTable;
EXIT WHEN curTable%NOTFOUND;
-- Set up a dynamic query, with a WHERE example.
vcQuery := 'SELECT ColumnA, ColumnB FROM ' || recTable.Table_Name || ' WHERE 1 = 1';
-- Execute the query.
OPEN :dyn_cur FOR vcQuery;
END LOOP;
CLOSE curTable;
END;
/
Try this
CREATE OR REPLACE PROCEDURE TEST IS
sql_stmt VARCHAR2(200);
V_NAME VARCHAR2(20);
BEGIN
sql_stmt := 'SELECT * FROM ';
EXECUTE IMMEDIATE sql_stmt|| V_NAME;
END;
Update
select statement dont work in procedure.
in sql server you can try sql block
Declare #name varchar2(50)
Select #name='Select * from '+TABLE_NAME from COL_TAB WHERE TABLE_NAME = 'TAB1'
EXEC(#name);