I have data in one table in a oracle database and I want to “split” this table in SQLplus into ten tables based on the content of one column.
Source table is all_data
with columns:
kind
, time_period
, amount
kind
is the row to split on: the value of kind
In each row is exactly one of ten different names “peter”, “maria”, “eric”, etc…
Now I want to create ten tables, one for each name. The first table for name “peter” would be created manually in SQL as:
CREATE TABLE peter_data AS ( SELECT p.kind, p.time_period, p.amount as amount_peter FROM all_data WHERE kind = 'peter' ) ;
How can I use PL/SQL to create all ten tables peter_data
, maria_data
, eric_data
, etc.?
I tried:
DECLARE TYPE array_t IS VARRAY(3) OF VARCHAR2(10); ARRAY array_t := array_t('peter', 'maria', 'eric'); BEGIN FOR i IN 1..ARRAY.COUNT LOOP CREATE TABLE ARRAY(i) AS ( SELECT p.kind, p.time_period, p.amount as amount_peter FROM all_data WHERE kind = ARRAY(i) ) ; END LOOP; END;
but this gives understandably the error “PLS-00103: Encountered the symbol “CREATE”…”
Advertisement
Answer
You just need to wrap your DDL statement in a string and call EXECUTE IMMEDIATE
:
DECLARE TYPE array_t IS VARRAY(3) OF VARCHAR2(10); ARRAY array_t := array_t('peter', 'maria', 'eric'); BEGIN FOR i IN 1..ARRAY.COUNT LOOP EXECUTE IMMEDIATE 'CREATE TABLE ' || ARRAY(i) || ' ( kind, time_period, amount_' || ARRAY(i) || ' ) AS' || ' SELECT kind, time_period, amount' || ' FROM all_data WHERE kind = ''' || ARRAY(i) || ''''; END LOOP; END; /
(and remove p.
as you didn’t define the alias p
anywhere.)
Then, if you have the table:
CREATE TABLE all_data ( kind, time_period, amount ) AS SELECT 'peter', DATE '2020-01-01', 23 FROM DUAL UNION ALL SELECT 'maria', DATE '2020-02-01', 42 FROM DUAL UNION ALL SELECT 'eric', DATE '2020-03-01', 11 FROM DUAL;
Then you get the tables:
SELECT * FROM peter;
KIND | TIME_PERIOD | AMOUNT_PETER :---- | :------------------ | -----------: peter | 2020-01-01 00:00:00 | 23
SELECT * FROM maria;
KIND | TIME_PERIOD | AMOUNT_MARIA :---- | :------------------ | -----------: maria | 2020-02-01 00:00:00 | 42
SELECT * FROM eric;
KIND | TIME_PERIOD | AMOUNT_ERIC :--- | :------------------ | ----------: eric | 2020-03-01 00:00:00 | 11
db<>fiddle here