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