动态创建表,然后动态插入数据

时间:2020-01-14 15:05:38

标签: sql oracle

我想创建一个过程来动态创建表,用户输入的列数为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

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

2 个答案:

答案 0 :(得分:2)

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

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;
/

输出:

CREATE TABLE TABLS(COL1 VARCHAR2(50), COL2 VARCHAR2(50), COL3 VARCHAR2(50)) 
INSERT INTO "TABLS"
SELECT "COL1","COL2","COL3"
FROM   (
  SELECT val,
         MOD( ROWNUM - 1, 3 ) + 1 AS col,
         FLOOR( ( ROWNUM - 1 ) / 3 ) + 1 AS rn
  FROM   data
)
PIVOT ( MAX( val ) FOR col IN ( 1 AS "COL1",2 AS "COL2",3 AS "COL3"))

SELECT * FROM tabls;

输出:

COL1 | COL2 | COL3
:--- | :--- | :---
A    | B    | C   
D    | E    | F   
G    | H    | null

db <>提琴here

答案 1 :(得分:0)

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

---
 - hosts: localhost

   vars:
     current_date_operation: "{{ ansible_date_time.date }}"
     previous_date_operation : "{{ '%Y-%m-%d' | strftime(ansible_date_time.epoch | int - 2592000) }}"

   tasks:
     - debug:
         var: current_date_operation
     - debug:
         var: previous_date_operation