Oracle用随机数据填充表


同样来自AskTom的脚本,可以对一个表填充随机数据

create or replace
 procedure gen_data( p_tname in varchar2, p_records in number )
 -- This routine is designed to be installed ONCE pre database, hence
 -- the CURRENT_USER AUTHORIZATION.
 authid current_user
 as
    l_insert long;
    l_rows  number default 0;
 begin
    -- dbms_random can be very cpu intensive. I use dbms_application_info
    -- to instrument this routine, so I can monitor how far along it is
    -- from another session. Every bulk insert will update v$session for us.
    dbms_application_info.set_client_info( 'gen_data ' || p_tname );
   
    -- The beginning of our insert into statement. Using a direct path
    -- insert, if you alter your table to be nologging in an archive
    -- log mode database, it'll generate no redo (assuming the table
    -- is not indexed).
    l_insert := 'insert /*+ append */ into ' || p_tname ||
                ' select ';


    -- Now, we build the rest of our insert. We select the datatype
    -- and size of each column. MAXVAL is used for numbers only. Using
    -- the precision defined for the column, we determine the maximum number
    -- that we can stuff in there.
    for x in
    ( select data_type, data_length,
    nvl(rpad( '9',data_precision,'9')/power(10,data_scale),9999999999) maxval
        from user_tab_columns
        where table_name = upper(p_tname)
        order by column_id )
    loop
        -- If number, generate a number in the range 1 .. maxval.
        if ( x.data_type in ('NUMBER', 'FLOAT' ))
        then
            l_insert := l_insert ||
                        'dbms_random.value(1,' || x.maxval || '),';


        -- if a date/timestamp type, add some random number to sysdate.
        elsif ( x.data_type = 'DATE' or x.data_type like 'TIMESTAMP%' )
        then
            l_insert := l_insert ||
                  'sysdate+dbms_random.value(1,1000),';


        -- If a string, generate a random string between 1 and data length.
        -- bytes in length
        else
            l_insert := l_insert || 'dbms_random.string(''A'',
                    trunc(dbms_random.value(1,' || x.data_length || '))),';
        end if;
    end loop;
    l_insert := rtrim(l_insert,',') ||
                  ' from all_objects where rownum <= :n';


    -- Now, wo just execute the insert into as many times as needed
    -- in order to put L_ROWS rows in the table. Since we are direct path
    -- loading, we must commit after each insert. In this case, since
    -- we are generating test data, it is OK from a transactional perspective.
    -- And since this operation should generate little redo in all cases,
    -- it will not affect our performance as well.
    loop
        execute immediate l_insert using p_records - l_rows;
        l_rows := l_rows + sql%rowcount;
        commit;
        dbms_application_info.set_module
        ( l_rows || ' rows of ' || p_records, '' );
        exit when ( l_rows >= p_records );
    end loop;
 end;
 /


以Hr的depertment表为例,
SQL> create table dept as select * from departments where 1=0;

 Table created.

但是需要注意的是 字段的取值范围不能小于1
以HR的employees表的COMMISSION_PCT字段为例,


执行到过程的第36行

 最大值应该是0.99
但是实际执行的结果却是 超过了最大值,导致溢出。


解决这个问题,可以将下限设置为0

相关内容

    暂无相关文章