Bonjour,
Je lutte depuis hier avec un script que je suis entrain de faire afin de réaliser le partitionnement à chaud de plusieurs tables.
Je suis sur:
Citation:
Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production
With the Partitioning, Real Application Clusters, OLAP, Data Mining
and Real Application Testing options
|
Je dispose d'une liste de tables à partitionner. Le type de partition est toujours le même, par range de dates, par mois. Seuls la table et le nom de la colonne changent.
Du coup j'ai fait un petit script SQL*Plus générique, mais impossible de le faire fonctionner.
Voila de quoi créer un jeu de test:
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| CREATE TABLE &G_SCHEMA..&g_table
(
ID NUMBER NOT NULL
, MADATE DATE NOT NULL
, CONSTRAINT &g_table._PK PRIMARY KEY
(
ID
)
ENABLE
);
INSERT INTO &G_SCHEMA..&g_table (ID,MADATE) VALUES (1,TO_DATE('12/10/2008 15:58:14','DD/MM/YYYY hh24:mi:ss'));
INSERT INTO &g_schema..&g_table (ID,MADATE) VALUES (2,TO_DATE('12/10/2009 15:58:27','DD/MM/YYYY hh24:mi:ss'));
COMMIT;
exit |
Et voila mon script, qui est appelé par un script shell qui lui passe les bons arguments (nom du schéma, nom de la table, nom de la colonne a utiliser comme clé de partition):
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
| whenever sqlerror exit failure
SET feedback off
SET verify off
SET serveroutput ON size unlimited
define g_schema=&1;
define g_table=&2;
define g_colonne=&3;
define g_table_work=&g_table._WRK
Prompt Verification si partitionnement possible pour &g_schema..&g_table ...
BEGIN
DBMS_REDEFINITION.CAN_REDEF_TABLE('&g_schema','&g_table', dbms_redefinition.cons_use_pk);
END;
/
Prompt Verifiaction OK.
Prompt Création de la TABLE de travail &g_schema..&g_table_work
declare
l_cnt integer;
begin
SELECT count(*)
INTO l_cnt
FROM all_tables
WHERE owner = '&g_schema'
AND table_name = '&g_table_work';
IF l_cnt > 0 then
execute immediate 'drop table &g_schema..&g_table_work purge';
end IF;
end;
/
declare
ltmp varchar2(40);
strsql varchar2(32000);
begin
SELECT tablespace_name
INTO ltmp
FROM all_tables
WHERE table_name = '&g_table'
AND owner = '&g_schema';
strsql := q'#
CREATE TABLE &g_schema..&g_table_work tablespace #'|| ltmp ||q'#
PARTITION BY RANGE (&g_colonne)
(
PARTITION P_190001 VALUES LESS THAN (to_date('190002','YYYYMM')) NOCOMPRESS
)
AS SELECT * FROM &g_schema..&g_table
WHERE 0=1#';
execute immediate strsql;
end;
/
/*
Création des partitions sur la table de travail
ON partition suivant la colonne passée en paramètre, par mois
*/
Prompt Creation des partitions sur la TABLE de travail
declare
l_min_date date;
l_max_date date;
l_curr_date date;
strsql varchar2(32000);
begin
SELECT min(&g_colonne), max(&g_colonne) INTO l_min_date, l_max_date FROM &g_schema..&g_table;
l_curr_date := l_min_date;
while l_curr_date <= l_max_date loop
l_curr_date := add_months(l_curr_date, 1);
strsql := q'#ALTER TABLE &g_schema..&g_table_work ADD PARTITION P_#'||to_char(add_months(l_curr_date,-1),'YYYYMM')||q'# VALUES LESS THAN (to_date('#'|| to_char(l_curr_date,'YYYYMM') ||q'#','YYYYMM')) NOCOMPRESS#';
execute immediate strsql;
end loop;
execute immediate 'ALTER TABLE &g_schema..&g_table_work ADD PARTITION P_MAX VALUES LESS THAN (MAXVALUE) NOCOMPRESS';
exception
when others then
dbms_output.put_line(DBMS_UTILITY.FORMAT_ERROR_STACK() || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE());
raise_application_error(-20000,'Erreur fatale lors du partitionnement de &g_table. Operation annulee.');
end;
/
/*
Début de la redéfinition
*/
ALTER session force parallel dml parallel 3;
ALTER session force parallel query parallel 3;
Prompt Debut de la redefinition
BEGIN
DBMS_REDEFINITION.START_REDEF_TABLE('&g_schema', '&g_table','&g_table_work', NULL, dbms_redefinition.cons_use_pk);
END;
/
-- Transfert des objets dépendants (indexes, contraintes, grant, triggers...)
Prompt Copie des objets dependants de la TABLE
DECLARE
num_errors PLS_INTEGER:=0;
BEGIN
dbms_redefinition.copy_table_dependents(
uname => '&g_schema',
orig_table => '&g_table',
int_table => '&g_table_work',
copy_indexes => dbms_redefinition.cons_orig_params,
copy_triggers => TRUE,
copy_constraints => TRUE,
copy_privileges => TRUE,
ignore_errors => TRUE,
num_errors => num_errors,
copy_statistics => TRUE
);
IF nvl(num_errors,0) != 0 then
dbms_output.put_line('*** num_errors='||num_errors);
dbms_redefinition.abort_redef_table('&g_schema', '&g_table', '&g_table_work');
dbms_output.put_line('*** Des erreurs ont ete detectees lors de la copie des objets dependants de la table.');
dbms_output.put_line('*** Ces erreurs peuvent être visualisees via: SELECT object_name, base_table_name, ddl_txt FROM DBA_REDEFINITION_ERRORS;');
-- raise_application_error(-20000,'Erreur fatale lors du partitionnement de &g_table. Operation annulee.');
end IF;
END;
/
Prompt Synchronisation TABLE de travail
BEGIN
DBMS_REDEFINITION.SYNC_INTERIM_TABLE('&g_schema','&g_table', '&g_table_work');
END;
/
Prompt Finalisation de la redefinition
BEGIN
DBMS_REDEFINITION.FINISH_REDEF_TABLE('&g_schema','&g_table', '&g_table_work');
END;
/
-- suppression de la table intermédiaire
DROP TABLE &g_schema..&g_table_work cascade constraints;
exit |
Tout fonctionne comme prévu jusqu'au premier truc bizarre, ligne 129, après l'appel à dbms_redefinition.copy_table_dependents(). num_error n'est pas égal à 0, mais il n'y a rien dans DBA_REDEFINITION_ERRORS?
Ensuite, l'appel à DBMS_REDEFINITION.SYNC_INTERIM_TABLE() provoque une ORA-12093:
Citation:
ORA-12093: table provisoire "TEST"."ADA_TEST1_WRK" non valide
ORA-06512: à "SYS.DBMS_REDEFINITION", ligne 119
ORA-06512: à "SYS.DBMS_REDEFINITION", ligne 1740
ORA-06512: à ligne 2
|
Si je ne fait pas l'appel à DBMS_REDEFINITION.SYNC_INTERIM_TABLE() , alors l'exception est levée sur DBMS_REDEFINITION.FINISH_REDEF_TABLE().
Je ne comprends pas vraiment, les tables ont la même structure à part les partitions, si l'on regarde la table de travail, tout est correct. Je n'ai rien vu de pertinent dans la doc ou ailleurs sur le net, dans tout les exemples que j'ai vu, tout fonctionne comme sur des roulettes...
Si quelqu'un voit mon erreur et veux bien me mettre sur la voie...
Merci
Edit: J'ai oublié de préciser que je lance ce script avec l'utilisateur SYSTEM