如何使用 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,列数:

kindtime_periodamount

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_datamaria_dataeric_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