1

我有这个 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;
/
4

3 回答 3

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;  

如果您想将其放入一个包中,您可能需要额外的资助才能使其工作。

于 2012-07-26T09:01:28.567 回答
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;
/
于 2012-07-26T07:56:06.957 回答
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;
于 2017-04-20T10:57:05.433 回答