复制oracle序列来测试模式,转换为PL / Sql程序

时间:2012-07-26 07:49:31

标签: sql oracle sequence

我有这个sql,它复制(实际上是重新创建)从生产方案到Oracle中的测试方案的序列,我如何从中创建一个程序,我可以使用如下?假设所有授权都是正确的,并且测试方案中的所有名称都相同。

所需的语法

copy_sequence <name_of_sequence> <connectstring_prod_scheme> <connectstring_test_scheme> 

SQL

connect test/testpw@db.srv;

declare
 val    number(21);
 s_sql varchar2(200);
begin
 --use the select on the productive db to get the current value
 select prod.seq.nextval into val from dual;
 s_sql := 'drop sequence seq';
 execute immediate s_sql;
 s_sql := 'create sequence seq minvalue 1 maxvalue 999999999999999999999 start with '||val||' increment by 1';
 execute immediate s_sql;
end;
/

3 个答案:

答案 0 :(得分:4)

您可以使用DBMS_METADATA来提取序列的DDL:

declare
procedure copy_sequence(p_SequenceName in varchar2,
                                          p_SourceSchema in varchar2,
                                          p_TargetSchema in varchar2) is
  doc clob;
  h   number;
  th  number; -- handle
begin
  -- Specify the object type.
  h := DBMS_METADATA.OPEN('SEQUENCE');

  -- Use filters to specify the particular object desired.
  DBMS_METADATA.SET_FILTER(h,
                           'SCHEMA',
                           p_SourceSchema);
  DBMS_METADATA.SET_FILTER(h,
                           'NAME',
                           p_SequenceName);

  -- Request that the schema name be modified.
  th := DBMS_METADATA.ADD_TRANSFORM(h,
                                    'MODIFY');
  DBMS_METADATA.SET_REMAP_PARAM(th,
                                'REMAP_SCHEMA',
                                p_SourceSchema,
                                p_TargetSchema);

  -- Request that the metadata be transformed into creation DDL.
  th := DBMS_METADATA.ADD_TRANSFORM(h,
                                    'DDL');

  -- Fetch the object.
  doc := DBMS_METADATA.FETCH_CLOB(h);

  -- Release resources.
  DBMS_METADATA.CLOSE(h);
  -- debug output
  dbms_output.put_line(doc);
  -- execute it
  execute immediate doc;
end;


begin
  copy_sequence(sequence_name, source_schema, target_schema);
end;  

如果你想将它放入一个包装中,你可能需要额外的补助才能使它有效。

答案 1 :(得分:3)

假设您的测试/测试用户具有适当的权限(选择任何表,创建序列),并且模式位于同一数据库中:

create procedure copy_sequence(seq VARCHAR2, prod_scheme VARCHAR2, test_scheme VARCHAR2)
as
 val    number(21);
 s_sql varchar2(200);
begin
 --either use the select on the productive db to get the current value + 1 
 execute immediate 'select '||prod_scheme||'.'||seq||'.nextval from dual' INTO val;
 --or use the select on ALL_SEQUENCES.LAST_NUMBER to get the current value (from APC's comment)
 execute immediate 'select last_number from all_sequences where sequence_owner = upper('''||prod_scheme||''') and sequence_name = upper('''||seq||''')' INTO val;
 s_sql := 'drop sequence '||test_scheme||'.'||seq;
 execute immediate s_sql;
 s_sql := 'create sequence '||test_scheme||'.'||seq||' minvalue 1 maxvalue 999999999999999999999 start with '||val||' increment by 1';
 execute immediate s_sql;
end;
/

但你不会用连接字符串来调用它,而是使用模式名称:

-- first connect
connect test/testpw@db.srv;
-- then execute procedure
exec copy_sequence( <name_of_sequence>, <prod_scheme>, <test_scheme>);
-- or execute procedure more than once
begin
 copy_sequence( <name_of_sequence1>, <prod_scheme>, <test_scheme>);
 copy_sequence( <name_of_sequence2>, <prod_scheme>, <test_scheme>);
end;
/

答案 2 :(得分:1)

如果您有正确的拨款,可以使用:

CREATE PROCEDURE MIGRATE_SEQUENCE(
  in_sequence_name IN ALL_SEQUENCES.SEQUENCE_NAME%TYPE,
  in_current_owner IN ALL_SEQUENCES.SEQUENCE_OWNER%TYPE,
  in_new_owner     IN ALL_SEQUENCES.SEQUENCE_OWNER%TYPE
)
IS
  p_sql VARCHAR2(4000);
BEGIN
  SELECT 'CREATE SEQUENCE "' || in_new_owner || '"."' || sequence_name || '"'
         || ' MINVALUE ' || min_value
         || ' MAXVALUE ' || max_value
         || ' INCREMENT BY ' || increment_by
         || ' START WITH ' || ( last_number + 1 )
         || ' ' || CASE cycle_flag WHEN 'N' THEN 'NO' END || 'CYCLE'
         || ' ' || CASE order_flag WHEN 'N' THEN 'NO' END || 'ORDER'
         || ' ' || CASE cache_size WHEN 0 THEN 'NOCACHE' ELSE 'CACHE ' || cache_size END
  INTO   p_sql
  FROM   ALL_SEQUENCES
  WHERE  SEQUENCE_NAME  = in_sequence_name
  AND    SEQUENCE_OWNER = in_current_owner;

  -- DBMS_OUTPUT.PUT_LINE( p_sql );

  /*
  -- Delete the sequence if it already exists
  DECLARE
    SEQUENCE_NOT_EXIST EXCEPTION;
    PRAGMA EXCEPTION_INIT( SEQUENCE_NOT_EXIST, -2289 );
  BEGIN
    EXECUTE IMMEDIATE 'DROP SEQUENCE "' ||in_new_owner|| '"."' ||in_sequence_name|| '"';
  EXCEPTION
    WHEN SEQUENCE_NOT_EXIST THEN
      NULL;
  END;
  */

  EXECUTE IMMEDIATE p_sql;
EXCEPTION
  WHEN NO_DATA_FOUND THEN
    DBMS_OUTPUT.PUT_LINE(
      in_current_owner || '.' || in_sequence_name || ' does not exist.'
    );
END;
/
SHOW ERRORS;