【问题标题】:Dynamically create a table and then insert the data dynamically动态创建表,然后动态插入数据
【发布时间】:2020-01-14 15:05:38
【问题描述】:

我想创建一个过程来动态创建一个表,用户输入的列数从 1 到 n。我使用下面的脚本来动态创建表格 -

CREATE OR REPLACE PROCEDURE TABLES(COLS IN NUMBER)
AS
TABLE_STMT VARCHAR2(100);
TABLE_COLS VARCHAR2(100);
BEGIN
     TABLE_STMT := 'CREATE TABLE TABLS(COL';
     FOR I IN 1..COLS LOOP
         IF I = COLS THEN
             TABLE_STMT := TABLE_STMT || I || ' VARCHAR2(50)) ';
         ELSE
             TABLE_STMT := TABLE_STMT || I || ' VARCHAR2(50), COL';
         END IF;
     END LOOP;
     EXECUTE IMMEDIATE TABLE_STMT;
     DBMS_OUTPUT.PUT_LINE(TABLE_STMT);
END;
/

Demo.

我有另一张桌子 -

VAL
A
B
C
D
E
F
G
H

需要在上表中创建的列之间拆分哪些行。如果用户输入 2 列,则输出应为 -

col1  |  col2
A     |  B
C     |  D
E     |  F
G     |  H

如果用户输入 3 列,输出应该是 -

col1  |  col2  |  col3
A     |  B     |  C
D     |  E     |  F
G     |  H

我已成功创建表,但坚持在其中插入数据。任何帮助表示赞赏。

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    使用动态枢轴将行转换为列:

    CREATE PROCEDURE insert_data(
      i_table_name IN VARCHAR2
    )
    IS
      p_sql CLOB;
    BEGIN
      SELECT 'INSERT INTO "' || i_table_name || '"
    SELECT ' || LISTAGG( '"' || column_name || '"', ',' )
                  WITHIN GROUP ( ORDER BY Column_id ) || '
    FROM   (
      SELECT val,
             MOD( ROWNUM - 1, ' || COUNT(*) || ' ) + 1 AS col,
             FLOOR( ( ROWNUM - 1 ) / ' || COUNT(*) || ' ) + 1 AS rn
      FROM   data
    )
    PIVOT ( MAX( val ) FOR col IN ( '
             || LISTAGG( Column_ID || ' AS "' || column_name || '"', ',' )
                  WITHIN GROUP ( ORDER BY Column_id )
             || '))'
      INTO   p_sql
      FROM   USER_TAB_COLUMNS
      WHERE  table_name = i_table_name;
    
      EXECUTE IMMEDIATE p_sql;
      DBMS_OUTPUT.PUT_LINE( p_sql );
    END;
    /
    

    然后

    DECLARE
      cols INTEGER := 3;
    BEGIN
      TABLES( cols );
      insert_data( 'TABLS' );
    END;
    /
    

    输出:

    创建表表(COL1 VARCHAR2(50),COL2 VARCHAR2(50),COL3 VARCHAR2(50)) 插入“表格” 选择“COL1”、“COL2”、“COL3” 从 ( 选择值, MOD( ROWNUM - 1, 3 ) + 1 AS col, 楼层 ( ( ROWNUM - 1 ) / 3 ) + 1 作为 rn 从数据 ) PIVOT ( MAX( val ) FOR col IN (1 AS "COL1",2 AS "COL2",3 AS "COL3"))

    SELECT * FROM tabls;
    

    输出:

    COL1 | COL2 | COL3 :--- | :--- | :--- 一个 |乙| C D | E | F 克| H |

    db小提琴here

    【讨论】:

      【解决方案2】:

      如果您不喜欢带有 pivot 的解决方案,您可以生成带有分析功能的代码:

      with la as (select chr(level+64)c from dual connect by level <= 8)
      , pv as (select c
                     ,lead(c) over (partition by 1 order by rownum) c2
                     ,lead(c,2)over (partition by 1 order by rownum) c3
                     , mod(rownum,3)r 
                  from la)
      select c,c2,c3  from pv 
      where r = 1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-24
        • 1970-01-01
        • 2015-12-10
        • 2018-06-04
        • 2010-10-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多