Bonjour à tous,

Je travaille sur une BD 11g Entreprise Edition sous Windows XP.

J'ai écrit un petit package dont le but est de supprimer des enregistrements dans une table :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
CREATE OR REPLACE PACKAGE Maint_pack AS
	PROCEDURE Spy(cTexte VARCHAR2);
	FUNCTION PurgeTable(cSchema VARCHAR2,cTable VARCHAR2,cChamp VARCHAR2,nNbJ NUMBER) RETURN NUMBER;
END Maint_pack;
/
 
CREATE OR REPLACE PACKAGE BODY Maint_pack AS
 
	PROCEDURE Spy(cTexte VARCHAR2) IS
		cFileSpy VARCHAR2(100) :='Maint_pack_'||TO_CHAR(SYSDATE,'DD')||'.txt';
		nFileSpy UTL_FILE.FILE_TYPE;
		cLineSpy VARCHAR2(400);
	BEGIN
		nFileSpy:=UTL_FILE.FOPEN('MAINT_DIR',cFileSpy,'A');
		cLineSpy:='DATE : '||TO_CHAR(SYSDATE,'DD/MM/YY HH24:MI:SS')||'  '||cTexte;
		UTL_FILE.PUT_LINE(nFileSpy,cLineSpy);
		UTL_FILE.FCLOSE(nFileSpy);
	END Spy;
 
	FUNCTION PurgeTable(cSchema VARCHAR2,cTable VARCHAR2,cChamp VARCHAR2,nNbJ NUMBER) RETURN NUMBER IS
		nPurgeTable NUMBER :=1;
		dFirstJour DATE;
		dLastJour DATE;
		cRequete VARCHAR2(5000);
	BEGIN
		cRequete:='SELECT MIN('||cChamp||') FROM '||cSchema||'.'||cTable;
		EXECUTE IMMEDIATE cRequete INTO dFirstJour;
		cRequete:='SELECT MAX('||cChamp||') FROM '||cSchema||'.'||cTable;
		EXECUTE IMMEDIATE cRequete INTO dLastJour;
		IF dLastJour - nNbJ > dFirstJour THEN
			dLastJour:=dLastJour-nNbJ;
			dFirstJour:=dFirstJour+15;
			IF dFirstJour < dLastJour THEN
				cRequete:='DELETE FROM '||cSchema||'.'||cTable||' WHERE '||cChamp||' < TO_DATE('||CHR(39)||dFirstJour||CHR(39)||')';
			ELSE
				cRequete:='DELETE FROM '||cSchema||'.'||cTable||' WHERE '||cChamp||' < TO_DATE('||CHR(39)||dLastJour||CHR(39)||')';
			END IF;
			Spy(cRequete);
			EXECUTE IMMEDIATE cRequete;
			COMMIT;
		END IF;
		RETURN nPurgeTable;
	EXCEPTION
		WHEN OTHERS THEN
			ROLLBACK;
			Spy(SQLERRM);
			nPurgeTable:=0;
			RETURN nPurgeTable;
	END PurgeTable;
 
END Maint_pack;
/
J'ai créé un Program :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
BEGIN
DBMS_SCHEDULER.CREATE_PROGRAM(
program_name=>'PURGE_TABLE',
program_action=>'TEST.Maint_pack.PurgeTable',
program_type=>'STORED_PROCEDURE',
number_of_arguments=>4,
comments=>'Supprime les enregistrements dans une table.');
END;
/
BEGIN
DBMS_SCHEDULER.DEFINE_PROGRAM_ARGUMENT(
program_name=>'PURGE_TABLE',
argument_position=>1,
argument_name=>'SCH',
argument_type=>'VARCHAR2',
default_value=>'TEST');
END;
/
BEGIN
DBMS_SCHEDULER.DEFINE_PROGRAM_ARGUMENT(
program_name=>'PURGE_TABLE',
argument_position=>2,
argument_name=>'TAB',
argument_type=>'VARCHAR2',
default_value=>'DUAL');
END;
/
BEGIN
DBMS_SCHEDULER.DEFINE_PROGRAM_ARGUMENT(
program_name=>'PURGE_TABLE',
argument_position=>3,
argument_name=>'CHP',
argument_type=>'VARCHAR2',
default_value=>'JOUR');
END;
/
BEGIN
DBMS_SCHEDULER.DEFINE_PROGRAM_ARGUMENT(
program_name=>'PURGE_TABLE',
argument_position=>4,
argument_name=>'NBJ',
argument_type=>'NUMBER',
default_value=>90);
END;
/
BEGIN
DBMS_SCHEDULER.ENABLE('PURGE_TABLE');
END;
/
J'ai créé un Schedule :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
BEGIN
DBMS_SCHEDULER.CREATE_SCHEDULE(
schedule_name => 'DAILY_200000',
start_date => systimestamp at time zone 'Europe/Paris',
repeat_interval => 'FREQ=DAILY;BYHOUR=20;BYMINUTE=0;BYSECOND=0',
comments => 'Tous les jours a 20h00.');
END;
/
J'ai créé un job :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
BEGIN
DBMS_SCHEDULER.CREATE_JOB( 
job_name => 'PURGE_LIGNE_CMD',
program_name => 'PURGE_TABLE',
schedule_name => 'DAILY_200000');
END;
/
BEGIN
DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE (
job_name => 'PURGE_LIGNE_CMD',
argument_position => 1,
argument_value => 'TEST');
END;
/
BEGIN
DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE (
job_name => 'PURGE_LIGNE_CMD',
argument_position => 2,
argument_value => 'LIGNE_CMD');
END;
/
BEGIN
DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE (
job_name => 'PURGE_LIGNE_CMD',
argument_position => 3,
argument_value => 'JOUR');
END;
/
BEGIN
DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE (
job_name => 'PURGE_LIGNE_CMD',
argument_position => 4,
argument_value => 90);
END;
/
BEGIN
DBMS_SCHEDULER.ENABLE('PURGE_LIGNE_CMD');
END;
/
Le Job s'exécute bien mais j'ai, en retour, une erreur ORA-06576: ceci n'est pas un nom de fonction ou de procédure valide .

J'ai testé ma fonction sous SqlPlus :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
SQL> var myVar number;
SQL> call Maint_pack.PurgeTable('TEST','QUANTITE','JOUR',90) into :myVar;
Comment faire la même chose dans l'appel du PROGRAM ?

Est-ce une mauvaise technique ?

Faut-il faire cela autrement ?

Merci pour vos réponses.