如何使用 Oracle PL/SQL 从给定的 Oracle 源 table 创建十个相似的 table
How to use Oracle PL/SQL to create ten similar tables from a given Oracle source table
我在 oracle 数据库中有一个 table 的数据,我想根据一栏的内容。
来源 table 是 all_data
,列数:
kind
、time_period
、amount
kind
是要拆分的行:每行中 kind
的值恰好是十个不同名称“peter”、“maria”、“eric”等中的一个。 .
现在我想创建十个 table,每个名字一个。名称“peter”的第一个 table 将在 SQL 中手动创建为:
CREATE TABLE peter_data AS (
SELECT p.kind, p.time_period, p.amount as amount_peter
FROM all_data
WHERE kind = 'peter'
)
;
如何使用 PL/SQL 创建所有十个 tables peter_data
、maria_data
、eric_data
等?
我试过了:
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;
但这给出了可以理解的错误“PLS-00103:遇到符号“CREATE”...”
您需要 dynamic SQL
,对于 Oracle,我们可以使用 execute immediate
来实现。
declare
type array_t is table of varchar2(10);
array array_t := array_t();
lo_stmt varchar2(2000);
begin
select distinct kind
bulk collect into array
from all_data;
for i in 1..array.count loop
--dbms_output.put_line(array(i));
lo_stmt :=
'create table '||array(i)||'_data '||
'as '||
'select kind,time_period,amount '||
' from all_data '||
' where kind = '''||array(i)||'''';
--dbms_output.put_line(lo_stmt);
execute immediate lo_stmt;
end loop;
end;
/
Demo可以看here
OR 用一条语句
declare
type array_t is table of varchar2(4000);
array array_t := array_t();
lo_stmt varchar2(2000);
begin
select distinct 'create table '||kind||'_data '||
'as '||
'select kind,time_period,amount '||
'from all_data '||
'where kind = '''||kind||''''
bulk collect into array
from all_data;
for i in 1..array.count loop
--dbms_output.put_line(array(i));
execute immediate array(i);
end loop;
end;
/
也有效 here
您只需将 DDL 语句包装在一个字符串中并调用 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;
/
(并删除 p.
,因为您没有在任何地方定义别名 p
。)
那么,如果你有 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;
然后你得到 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
我在 oracle 数据库中有一个 table 的数据,我想根据一栏的内容。
来源 table 是 all_data
,列数:
kind
、time_period
、amount
kind
是要拆分的行:每行中 kind
的值恰好是十个不同名称“peter”、“maria”、“eric”等中的一个。 .
现在我想创建十个 table,每个名字一个。名称“peter”的第一个 table 将在 SQL 中手动创建为:
CREATE TABLE peter_data AS (
SELECT p.kind, p.time_period, p.amount as amount_peter
FROM all_data
WHERE kind = 'peter'
)
;
如何使用 PL/SQL 创建所有十个 tables peter_data
、maria_data
、eric_data
等?
我试过了:
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;
但这给出了可以理解的错误“PLS-00103:遇到符号“CREATE”...”
您需要 dynamic SQL
,对于 Oracle,我们可以使用 execute immediate
来实现。
declare
type array_t is table of varchar2(10);
array array_t := array_t();
lo_stmt varchar2(2000);
begin
select distinct kind
bulk collect into array
from all_data;
for i in 1..array.count loop
--dbms_output.put_line(array(i));
lo_stmt :=
'create table '||array(i)||'_data '||
'as '||
'select kind,time_period,amount '||
' from all_data '||
' where kind = '''||array(i)||'''';
--dbms_output.put_line(lo_stmt);
execute immediate lo_stmt;
end loop;
end;
/
Demo可以看here
OR 用一条语句
declare
type array_t is table of varchar2(4000);
array array_t := array_t();
lo_stmt varchar2(2000);
begin
select distinct 'create table '||kind||'_data '||
'as '||
'select kind,time_period,amount '||
'from all_data '||
'where kind = '''||kind||''''
bulk collect into array
from all_data;
for i in 1..array.count loop
--dbms_output.put_line(array(i));
execute immediate array(i);
end loop;
end;
/
也有效 here
您只需将 DDL 语句包装在一个字符串中并调用 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;
/
(并删除 p.
,因为您没有在任何地方定义别名 p
。)
那么,如果你有 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;
然后你得到 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