Как создать таблицу со случайным количеством полей в Oracle, используя PL / SQL? - PullRequest
5 голосов
/ 06 сентября 2010

Мне нужно создать таблицы Oracle со случайным количеством столбцов для нагрузочного тестирования. Я просто хочу указать количество столбцов с типом NUMBER, количество столбцов с типом VARCHAR2 и т. Д., И поля должны быть созданы автоматически. Также я буду заполнять таблицы случайными данными, для которых я буду использовать dbms_random.

Как мне этого добиться?

Ответы [ 3 ]

9 голосов
/ 06 сентября 2010

"Я просто хочу указать количество столбцов с типом NUMBER, количество столбцов с типом VARCHAR2 и т. Д., И поля должны быть сгенерированы автоматически."

Следующая процедура делает именно это,Обратите внимание, что это довольно просто;Вы можете захотеть сделать его более сложным, например, изменив длину столбцов varchar2:

SQL> create or replace procedure bld_table
  2      ( p_tab_name in varchar2
  3        , no_of_num_cols in pls_integer
  4        , no_of_var_cols in pls_integer
  5        , no_of_date_cols in pls_integer
  6      )
  7  as
  8  begin
  9      execute immediate 'create table '||p_tab_name||' ('
 10                        ||' pk_col number not null'
 11                        ||', constraint '||p_tab_name||'_pk primary key (pk_col) using index)';
 12      << numcols >>
 13      for i in 1..no_of_num_cols loop
 14          execute immediate 'alter table '||p_tab_name||' add '
 15                            ||' col_n'||trim(to_char(i))||' number';
 16      end loop numcols;
 17      << varcols >>
 18      for i in 1..no_of_var_cols loop
 19          execute immediate 'alter table '||p_tab_name||' add '
 20                            ||' col_v'||trim(to_char(i))||' varchar2(30)';
 21      end loop varcols;
 22      << datcols >>
 23      for i in 1..no_of_date_cols loop
 24          execute immediate 'alter table '||p_tab_name||' add '
 25                            ||' col_d'||trim(to_char(i))||' date';
 26      end loop datcols;
 27  end bld_table;
 28  /

Procedure created.

SQL>

Вот оно в действии:

SQL> exec bld_table ('T23', 2, 3, 0)

PL/SQL procedure successfully completed.

SQL> desc t23
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 PK_COL                                    NOT NULL NUMBER
 COL_N1                                             NUMBER
 COL_N2                                             NUMBER
 COL_V1                                             VARCHAR2(30 CHAR)
 COL_V2                                             VARCHAR2(30 CHAR)
 COL_V3                                             VARCHAR2(30 CHAR)

SQL>

Мы также можем использовать динамический SQLзаполнить таблицу строками случайных данных.

SQL> create or replace procedure pop_table
  2          ( p_tab_name in varchar2
  3        , p_no_of_rows in pls_integer
  4      )
  5  as
  6   stmt varchar2(32767);
  7  begin
  8   stmt := 'insert into '||p_tab_name
  9                || ' select rownum ';
 10        for r in ( select column_name
 11                          , data_type
 12                          , data_length
 13                   from user_tab_columns
 14                   where table_name = p_tab_name
 15                  and column_name != 'PK_COL' )
 16        loop
 17            case r.data_type
 18           when 'VARCHAR2' then
 19               stmt := stmt ||', dbms_random.string(''a'', '||r.data_length||')';
 20           when 'NUMBER' then
 21               stmt := stmt ||', dbms_random.value(0, 1000)';
 22           when 'DATE' then
 23               stmt := stmt ||', sysdate + dbms_random.value(-1000, 0)';
 24            end case;
 25        end loop;
 26        stmt := stmt || ' from dual connect by level <= '||p_no_of_rows;
 27        execute immediate stmt;
 28  end pop_table;
 29  /

Procedure created.

SQL>

Обратите внимание, что первичный ключ заполняется ROWNUM, поэтому он, скорее всего, потерпит неудачу, если таблица уже содержит строки.

SQL> exec pop_table('T23', 4)

PL/SQL procedure successfully completed.

SQL> select * from t23
  2  /

    PK_COL     COL_N1     COL_N2 COL_V1                         COL_V2                         COL_V3
---------- ---------- ---------- ------------------------------ ----------------------------- ------------------------------
         1 913.797432 934.265814 NUtxjLoRQMCTLNMPKVGbTZwJeYaqnXTkCcWu WFRSHjXdLfpgVYOjzrGrtUoX jIBSoYOhSdhRFeEeFlpAxoanPabvwK
         2 346.879815 104.800387 NTkvIlKeJWybCTNEdvsqJOKyidNkjgngwRNN PPIOInbzInrsVTmFYcDvwygr RyKFoMoSiWTmjTqRBCqDxApIIrctPu
         3 93.1220275 649.335267 NTUxzPRrKKfFncWaeuzuyWzapmzEGtAwpnjj jHILMWJlcMjnlboOQEIDFTBG JRozyOpWkfmrQJfbiiNaOnSXxIzuHk
         4 806.709357 857.489387 ZwLLkyINrVeCkUpznVdTHTdHZnuFzfPJbxCB HnoaErdzIHXlddOPETzzkFQk dXWTTgDsIeasNHSPbAsDRIUEyPILDT

4 rows selected.

SQL>

Опять же, есть множество способов улучшить сложность данных.


Кроме того, использование таких видов пулов данных для нагрузочного тестирования не всегдахорошая идея.Проблемы с производительностью часто вызваны перекосами в распределении значений данных, которые вы просто не собираетесь получить с помощью DBMS_RANDOM.Это особенно верно для некоторых столбцов даты - например, START_DATE - которые обычно бывают сгруппированы в реальной жизни, но описанная выше процедура не будет генерировать этот шаблон.Аналогичным образом, максимальное использование столбцов varchar2 приведет к тому, что таблицы будут занимать больше памяти, чем при реальном использовании.

Короче говоря, случайные данные лучше, чем ничего, но нам нужно понять их слабые стороны.

2 голосов
/ 06 сентября 2010

Два подхода

1) Напишите код для генерации текстовых файлов, содержащих команды CREATE TABLE, которые вам нужны для запуска и заполнения таблиц, затем выполните их с использованием SQL * Plus.

2)Использовать динамический SQL, встроенный в PL / SQL -

 PROCEDURE create_random_table 
      (pTableName IN VARCHAR2,
       pNumberOfColumns IN INTEGER)
 IS  
     PRAGMA AUTONOMOUS_TRANSACTION;
     lCommand VARCHAR2(32000);
 BEGIN
     lCommand := 
     'CREATE TABLE '||pTableName||'(';
     FOR i IN 1..pNumberOfColumns LOOP
        append your column definition here
     END LOOP;
     lCommand := lCommand||';';
     --
     EXECUTE IMMEDIATE lCommand;
 END;

Вы также можете использовать «CREATE TABLE AS SELECT» для одновременного заполнения таблицы (см. Другой ответ).

Это должнодать вам хорошую отправную точку - в системе нет ничего, что могло бы делать то, что вы хотите, без написания кода.

1 голос
/ 06 сентября 2010

Вы можете создать такую ​​таблицу самостоятельно.

Создать таблицу с необходимыми типами данных:

  Create Table RandomTable
  AS
  Select dbms_random.string('A', 1) CharField,
         dbms_random.string('a', 20) VarCharField,
         TRUNC(dbms_random.value(0, 35000)) IntField,
         dbms_random.value(0, 35000) NumberField,
         Level SequenceField,
         sysdate + dbms_random.value(-3500, 3500) DateField
  from dual connect by level < 1000

(Вы можете изменить 1000 на номера необходимых строк и добавить необходимые типы данных)

После этого вы можете создавать или заполнять таблицы случайными данными из RandomTable

  Create Table TestTable1
  AS
  SELECT CharField as a, NumberField as b
  from RandomTable

  INSERT INTO TestTable2(DateFrom, Quantity)
  SELECT DateField, IntField 
  from RandomTable
  Where SequenceField <= 500
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...