获取指定用户表结构创建语句含索引和约束

通常我们可以使用dbms_metadata.get_ddl来获取表的ddl信息,但是此方法返回的是CLOB类型,不方便使用,并且需要相应的授权,这里我们直接使用all_tab_columns和all_constraints
、all_cons_columns字典视图来获取表的创建语句。

 

create or replace procedure p_get_tableddl(table_name  varchar2, table_owner varchar2) AS
  CURSOR cur_columns(iv_table_name VARCHAR2, iv_owner VARCHAR2) IS
    SELECT column_name,
           data_type,
           data_length,
           data_precision,
           data_scale,
           nullable,
           column_id,
           data_default
      FROM all_tab_columns
     WHERE table_name = iv_table_name
       AND owner = iv_owner
     ORDER BY column_id;
  rec_columns cur_columns%ROWTYPE;
  --
  CURSOR cur_constraint(iv_table_name VARCHAR2, iv_owner VARCHAR2) IS
    SELECT constraint_name,
           constraint_type,
           search_condition,
           r_owner,
           r_constraint_name,
           delete_rule,
           status
      FROM all_constraints
     WHERE table_name = iv_table_name
       AND owner = iv_owner;
  --
  CURSOR cur_cons_columns(iv_constraint_name VARCHAR2, iv_owner VARCHAR2) IS
    SELECT column_name, table_name
      FROM all_cons_columns
     WHERE constraint_name = iv_constraint_name
       AND owner = iv_owner
     ORDER BY position;
  --
  CURSOR cur_index(iv_table_name VARCHAR2, iv_owner VARCHAR2) IS
    SELECT index_name, lower(tablespace_name) tablespace_name
      FROM all_indexes
     WHERE table_name = iv_table_name
       AND owner = iv_owner;
  --
  CURSOR cur_ind_columns(iv_index_name VARCHAR2, iv_owner VARCHAR2) IS
    SELECT lower(column_name) column_name
      FROM all_ind_columns
     WHERE index_name = iv_index_name
       AND index_owner = iv_owner
     ORDER BY index_name, column_position;
  --
  v_table_name      all_tables.table_name%TYPE;
  v_owner           all_tables.owner%TYPE;
  v_tablespace_name all_tables.tablespace_name%TYPE;
  v_pre_column_name all_tab_columns.column_name%TYPE;
  v_pre_column      VARCHAR2(200);
  v_constraint      VARCHAR2(200);
  v_index           VARCHAR2(200);
  v_r_table_name    all_cons_columns.table_name%TYPE;
BEGIN
  v_table_name := upper(table_name);
  v_owner      := upper(table_owner);
  --
  SELECT lower(tablespace_name)
    INTO v_tablespace_name
    FROM all_tables
   WHERE table_name = v_table_name
     AND owner = v_owner;
  -- --------------- --
  -- get all columns --
  -- --------------- --
  OPEN cur_columns(v_table_name, v_owner);
  LOOP
    FETCH cur_columns
      INTO rec_columns;
    --
    IF v_pre_column_name IS NOT NULL THEN
      IF v_pre_column_name = lower(rec_columns.column_name) THEN
        dbms_output.put_line(v_pre_column);
        dbms_output.put_line(') tablespace ' || v_tablespace_name);
        dbms_output.put_line('/');
      ELSIF rec_columns.column_id = 2 THEN
        dbms_output.put_line('create table ' || lower(v_table_name) || ' (');
        dbms_output.put_line(v_pre_column || ',');
      ELSE
        dbms_output.put_line(v_pre_column || ',');
      END IF;
    END IF;
    --
    EXIT WHEN cur_columns%NOTFOUND;
    --
    v_pre_column_name := lower(rec_columns.column_name);
    v_pre_column      := rpad(lower(rec_columns.column_name), 31, ' ');
    IF rec_columns.data_type = 'NUMBER' THEN
      IF rec_columns.data_precision IS NULL THEN
        v_pre_column := v_pre_column || 'number';
      ELSIF rec_columns.data_scale = 0 THEN
        v_pre_column := v_pre_column || 'number(' ||
                        to_char(rec_columns.data_precision) || ')';
      ELSE
        v_pre_column := v_pre_column || 'number(' ||
                        to_char(rec_columns.data_precision) || ',' ||
                        to_char(rec_columns.data_scale) || ')';
      END IF;
    ELSIF instr(rec_columns.data_type, 'CHAR') > 0 THEN
      v_pre_column := v_pre_column || lower(rec_columns.data_type) || '(' ||
                      to_char(rec_columns.data_length) || ')';
    ELSE
      v_pre_column := v_pre_column || lower(rec_columns.data_type);
    END IF;
    --
    IF rec_columns.data_default IS NOT NULL THEN
      v_pre_column := rpad(v_pre_column, 46, ' ') || ' default ' ||
                      rtrim(rec_columns.data_default);
    END IF;
    --
    IF rec_columns.nullable = 'N' THEN
      IF length(v_pre_column) > 46 THEN
        v_pre_column := v_pre_column || ' not null';
      ELSE
        v_pre_column := rpad(v_pre_column, 46, ' ') || ' not null';
      END IF;
    END IF;
    --
  END LOOP;
  CLOSE cur_columns;
  --
  FOR rec_c IN cur_constraint(v_table_name, v_owner) LOOP
    IF rec_c.constraint_type = 'P' THEN
      v_constraint := ' (';
      FOR rec_column IN cur_cons_columns(rec_c.constraint_name, v_owner) LOOP
        v_constraint := v_constraint || lower(rec_column.column_name) || ', ';
      END LOOP;
      v_constraint := substr(v_constraint, 1, length(v_constraint) - 2) || ')';
      dbms_output.put_line('alter table ' || lower(v_table_name));
      dbms_output.put_line(' add constraint ' || rec_c.constraint_name ||
                           ' primary key');
      dbms_output.put_line(v_constraint);
      --
      SELECT lower(tablespace_name)
        INTO v_tablespace_name
        FROM all_indexes
       WHERE table_name = v_table_name
         AND index_name = rec_c.constraint_name
         AND owner = v_owner;
      dbms_output.put_line(' using index tablespace ' || v_tablespace_name);
      dbms_output.put_line('/');
    ELSIF rec_c.constraint_type = 'R' THEN
      v_constraint := ' (';
      FOR rec_column IN cur_cons_columns(rec_c.constraint_name, v_owner) LOOP
        v_constraint := v_constraint || lower(rec_column.column_name) || ', ';
      END LOOP;
      v_constraint := substr(v_constraint, 1, length(v_constraint) - 2) || ')';
      dbms_output.put_line('alter table ' || lower(v_table_name));
      dbms_output.put_line(' add constraint ' || rec_c.constraint_name ||
                           ' foreign key');
      dbms_output.put_line(v_constraint);
      v_constraint := ' (';
      FOR rec_column IN cur_cons_columns(rec_c.r_constraint_name, v_owner) LOOP
        v_constraint   := v_constraint || lower(rec_column.column_name) || ', ';
        v_r_table_name := lower(rec_column.table_name);
      END LOOP;
      v_constraint := substr(v_constraint, 1, length(v_constraint) - 2) || ')';
      dbms_output.put_line(' references ' || v_r_table_name);
      dbms_output.put_line(v_constraint);
      dbms_output.put_line('/');
    ELSIF rec_c.constraint_type = 'U' THEN
      v_constraint := ' (';
      FOR rec_column IN cur_cons_columns(rec_c.constraint_name, v_owner) LOOP
        v_constraint := v_constraint || lower(rec_column.column_name) || ', ';
      END LOOP;
      v_constraint := substr(v_constraint, 1, length(v_constraint) - 2) || ')';
      dbms_output.put_line('alter table ' || lower(v_table_name));
      dbms_output.put_line(' add constraint ' || rec_c.constraint_name ||
                           ' unique');
      dbms_output.put_line(v_constraint);
      --
      SELECT lower(tablespace_name)
        INTO v_tablespace_name
        FROM all_indexes
       WHERE table_name = v_table_name
         AND index_name = rec_c.constraint_name
         AND owner = v_owner;
      dbms_output.put_line(' using index tablespace ' || v_tablespace_name);
      dbms_output.put_line('/');
    ELSIF rec_c.constraint_type = 'C' AND
          instr(rec_c.search_condition, 'IS NOT NULL') = 0 THEN
      dbms_output.put_line('alter table ' || lower(v_table_name));
      dbms_output.put_line(' add constraint ' || rec_c.constraint_name ||
                           ' check');
      dbms_output.put_line(' (' || ltrim(rtrim(rec_c.search_condition)) || ')');
      dbms_output.put_line('/');
    END IF;
  END LOOP;
  --
  FOR rec_i IN cur_index(v_table_name, v_owner) LOOP
    dbms_output.put_line('create index ' || rec_i.index_name);
    v_index := ' on ' || lower(v_table_name) || ' (';
    FOR rec_c IN cur_ind_columns(rec_i.index_name, v_owner) LOOP
      v_index := v_index || rec_c.column_name || ', ';
    END LOOP;
    v_index := substr(v_index, 1, length(v_index) - 2) || ')';
    dbms_output.put_line(v_index);
    dbms_output.put_line(' tablespace ' || rec_i.tablespace_name);
    dbms_output.put_line('/');
  END LOOP;
EXCEPTION
  WHEN no_data_found THEN
    dbms_output.put_line('No this table!');
  WHEN OTHERS THEN
    dbms_output.put_line(SQLCODE || SQLERRM);
END;

  

posted @ 2015-10-23 10:32  miniprince  阅读(309)  评论(0编辑  收藏  举报