Précédent   Forum des professionnels en informatique > Bases de données > Oracle > Débuter
Débuter Forum d'entraide pour débuter avec Oracle
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 14/02/2008, 14h32   #1
Membre à l'essai
 
Inscription : septembre 2007
Messages : 109
Détails du profil
Informations forums :
Inscription : septembre 2007
Messages : 109
Points : 22
Points : 22
Par défaut executer une procedure distante

Bonjour,

j'ai une base oracle (8i) "A" qui 'surveille' mes autres bases oracle (ex:"B"). Cette base doit notement remonter les informations disques (un df sur "B" redirigé vers un fichier que la base "A" lit).
Pour cela, la procédure RapatrierInfosDisques de "A" doit éxécuter la procédure LINUXGetDiskInfo de "B".
Hors, je ne sais pas comment faire exécuter une procédure distante depuis une autre procédure.

Pouvez vous m'aider?
voici les codes en question:
sur "A":
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
Procedure RapatrierInfosDisques(OS IN varchar2, dblinkName IN varchar2) IS
requete varchar2(500);
CursorID integer;
dsk varchar2(30);
siz integer;
fre integer;
IGNORE integer;
err_msg varchar2(2000);
begin
  requete := NULL;
  trace('['||rtrim(OS)||']');
  IF rtrim(OS) = 'WIN' then
    requete := 'select distinct utl_surge.WinextractDrive(file_name) as disque from dba_data_files' || dblinkname ;
  elsif rtrim(OS) = 'LINUX' then
    requete := 'select distinct utl_surge.LinuxextractDrive(file_name) from dba_data_files' || dblinkname ;
	trace(requete);
  elsif rtrim(OS) = 'VMS' then
    requete := 'select distinct utl_surge.vmsextractdrive(file_name) from dba_data_files' || dblinkname;
  else
    raise_application_error(-20001, 'OS non pris en charge pour RapatrierInfosDisques : '||OS);
  end IF;
  IF requete IS NOT NULL then
    begin
	  trace('On purge InfoDsk');
      CursorID := dbms_sql.Open_Cursor;
      Dbms_Sql.Parse(Cursorid, requete, Dbms_Sql.Native);
	  Dbms_sql.Define_Column(CursorId, 1, dsk, 30);
	  IGNORE := Dbms_Sql.Execute(CursorId);
  	  DELETE FROM InfoDsk WHERE bas_id = CurrentBD;
	  Loop
	    IF Dbms_sql.Fetch_rows(CursorId)>0 then
	      Dbms_sql.Column_Value(CursorId, 1, dsk);
	      IF rtrim(OS) = 'WIN' then
	        SAGA.WinGetDiskInfo(dsk, siz, fre);
	      elsif rtrim(OS) = 'LINUX' then
		    trace(dsk);
		    trace('Récupération des informations disque');
	        LINUXGetDiskInfo (dsk, siz, fre);
	      elsif rtrim(OS) = 'VMS' then
	        VMSGetDiskInfo(dsk, siz, fre);
		  else
	        raise_application_error(-20001, 'Fonction de récupération de taille disque non supportée par l''OS '||OS);
	      end IF;
		  INSERT INTO InfoDsk (DSK_ID, DSK_FREE, DSK_SIZE, BAS_ID) VALUES (dsk, fre, siz, CurrentBD);
		else
		  exit;
		end IF;
	  end loop;
      Dbms_Sql.Close_Cursor(Cursorid);
    exception
      when others then
        err_msg := substr(sqlerrm, 1, 2000);
        trace(err_msg);
        Dbms_Sql.Close_Cursor(Cursorid);
    	raise;
    end;
  end IF;
end RapatrierInfosDisques;
sur "B"
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
Procedure LINUXGetDiskInfo(Disque IN varchar2, TotalBytes out integer, FreeBytes out integer) IS
filehandle utl_file.file_type;
s varchar2(500);
tmpdisk varchar2(30);
begin
  -- Lecture du fichier généré par la tâche planifiée (df)
  trace('ouverture du fichier');
  filehandle := utl_file.fopen(/home/oracle', 'LINUX.DSK', 'r');
  trace('fichier lu');
  -- Parser
  loop
    begin
	  trace('lecture fichier LINUX.DSK');
      utl_file.get_line(filehandle, s);
	exception
	  when no_data_found then
        utl_file.fclose(filehandle);
	    exit;
	  when others then
	    raise;
    end;
	tmpdisk := rtrim(substr(s, 57, length(s)));
	if tmpdisk = Disque then
	  FreeBytes := to_number(substr(s, 41, 10))*1024;
	  TotalBytes := to_number(substr(s, 31, 10))*1024 + FreeBytes;
      utl_file.fclose(filehandle);
	  exit;
	end if;
  end loop;
exception
  when utl_file.invalid_path then
    raise_application_error(-20002, 'Path invalide "'||Disque||':/" ; s''assurer de sa définition dans Init.Ora, Base '||to_char(CurrentBD)||' '||CurrentOS);
  when utl_file.invalid_mode then
	raise_application_error(-20002, 'Mode invalide (r)');
  when utl_file.invalid_operation then
	raise_application_error(-20002, 'Opération utl_file invalide!');
  when others then
	  raise;
end LINUXGetDiskInfo;
merci d'avance
moi26 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/02/2008, 14h39   #2
Rédacteur/Modérateur
 
Avatar de orafrance
 
Inscription : janvier 2004
Messages : 15 861
Détails du profil
Informations personnelles :
Âge : 35

Informations forums :
Inscription : janvier 2004
Messages : 15 861
Points : 16 212
Points : 16 212
http://www.developpez.net/forums/sho...%E9dure+dblink
orafrance est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/02/2008, 16h01   #3
Membre à l'essai
 
Inscription : septembre 2007
Messages : 109
Détails du profil
Informations forums :
Inscription : septembre 2007
Messages : 109
Points : 22
Points : 22
en fait, je suis complétement perdu:

j'essaye de faire comme dans l'exemple:
Code :
SELECT mafonction(monparam)@mondblink FROM...
devient:
Code :
SELECT utl_surge.LINUXGetDiskInfo(dsk, siz, fre)@dblinkname FROM...
oui mais from quoi?
désolé, je ne suis vraiment pas fort en pl/sql...
je ne vois pas les tables que l'ont peux attaquer.


sinon si je comprends le lien donné, dans la procédure RapatrierInfosDisques
au lieu de:
LINUXGetDiskInfo (dsk, siz, fre);
pour l'éxecuetr à distance, je remplace la ligne par:
r:=LINUXGetDiskInfo (dsk, siz, fre) || dblinkname;

mais ça ne marche pas non plus.

suis paumé la...
moi26 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/02/2008, 16h11   #4
Rédacteur/Modérateur
 
Avatar de orafrance
 
Inscription : janvier 2004
Messages : 15 861
Détails du profil
Informations personnelles :
Âge : 35

Informations forums :
Inscription : janvier 2004
Messages : 15 861
Points : 16 212
Points : 16 212
c'est le @dblink qu'il faut retenir, pour le reste ça fonctionne exactement comme une procédure locale
orafrance est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2008, 11h04   #5
Membre à l'essai
 
Inscription : septembre 2007
Messages : 109
Détails du profil
Informations forums :
Inscription : septembre 2007
Messages : 109
Points : 22
Points : 22
ok, merci!

je viens de comprendre mon probleme...qui en a soulevé un autre:
je veux executer ma procédure LINUXGetDiskInfo(dsk, siz, fre) à distance.

Le principe est donc de mettre LINUXGetDiskInfo@dblinkname(dsk, siz, fre);

sauf que dblinkname doit être un parametre (car j'ai plusieurs bases à surveiller)
j'ai donc essayé LINUXGetDiskInfo@dblinkname(dsk, siz, fre);
et je me retrouve lors de la compilation avec:
ORA-04054: lien base de données DBLINKNAME inexistant
j'ai essayé aussi :
LINUXGetDiskInfo||@dblinkname(dsk, siz, fre);
mais ne fais pas mieux.

Comment le mettre en parametre?
merci de vos aides
moi26 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2008, 11h06   #6
Rédacteur/Modérateur
 
Avatar de orafrance
 
Inscription : janvier 2004
Messages : 15 861
Détails du profil
Informations personnelles :
Âge : 35

Informations forums :
Inscription : janvier 2004
Messages : 15 861
Points : 16 212
Points : 16 212
regarde du coté de EXECUTE IMMEDIATE
orafrance est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2008, 14h16   #7
Membre à l'essai
 
Inscription : septembre 2007
Messages : 109
Détails du profil
Informations forums :
Inscription : septembre 2007
Messages : 109
Points : 22
Points : 22
Merci pour l'info,
mais je me retrouve avec une erreur ora-00900 avec la commande:
Code :
execute immediate 'LINUXGetDiskInfo'||dblinkname||'(dsk, siz, fre)';
dblinkname => @base.world

Je suppose que c'est un problème d'interprétation?
moi26 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2008, 14h19   #8
Rédacteur/Modérateur
 
Avatar de orafrance
 
Inscription : janvier 2004
Messages : 15 861
Détails du profil
Informations personnelles :
Âge : 35

Informations forums :
Inscription : janvier 2004
Messages : 15 861
Points : 16 212
Points : 16 212
manque EXEC.

Code :
EXECUTE IMMEDIATE(<code SQL>)
si tu colles :

Code :
LINUXGetDiskInfo@base.world(dsk, siz, fre)
dans SQL*Plus t'auras une erreur et c'est normal...

Code :
EXEC LINUXGetDiskInfo@base.world(dsk, siz, fre)
est correct
orafrance est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2008, 15h04   #9
Membre à l'essai
 
Inscription : septembre 2007
Messages : 109
Détails du profil
Informations forums :
Inscription : septembre 2007
Messages : 109
Points : 22
Points : 22
en fait, je ne l'éxecute pas à travers SQl plus mais toad:
cette procédure est appelé à l'intérieur d'une autre procédure:

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
Procedure RapatrierInfosDisques(OS in varchar2, dblinkName in varchar2) is
requete varchar2(500);
CursorID integer;
dsk varchar2(30);
siz integer;
fre integer;
ignore integer;
err_msg varchar2(2000);
begin
  requete := null;
  trace('['||rtrim(OS)||']');
  trace('['||rtrim(dblinkName)||']');
  if rtrim(OS) = 'WIN' then
    requete := 'select distinct utl_surge.WinextractDrive(file_name) as disque from dba_data_files' || dblinkname ;
  elsif rtrim(OS) = 'LINUX' then
  -- TODO : remplacer testlinux
    requete := 'select distinct utl_surge.LinuxextractDrive(file_name) from dba_data_files' || dblinkname ;
	trace(requete);
  elsif rtrim(OS) = 'VMS' then
  -- TODO : remplacer testvms
    requete := 'select distinct utl_surge.vmsextractdrive(file_name) from dba_data_files' || dblinkname;
  else
    raise_application_error(-20001, 'OS non pris en charge pour RapatrierInfosDisques : '||OS);
  end if;
  if requete is not null then
    begin
	  trace('On purge InfoDsk');
      CursorID := dbms_sql.Open_Cursor;
      Dbms_Sql.Parse(Cursorid, requete, Dbms_Sql.Native);
	  Dbms_sql.Define_Column(CursorId, 1, dsk, 30);
	  ignore := Dbms_Sql.Execute(CursorId);
  	  Delete from InfoDsk where bas_id = CurrentBD;
	  Loop
	    if Dbms_sql.Fetch_rows(CursorId)>0 then
	      Dbms_sql.Column_Value(CursorId, 1, dsk);
	      if rtrim(OS) = 'WIN' then
	        WinGetDiskInfo(dsk, siz, fre);
	      elsif rtrim(OS) = 'LINUX' then
		    trace(dsk);
		    trace('Récupération des informations disque');
		EXEC 'LINUXGetDiskInfo'||dblinkname||'(dsk, siz, fre)';
	      elsif rtrim(OS) = 'VMS' then
	        VMSGetDiskInfo(dsk, siz, fre);
		  else
	        raise_application_error(-20001, 'Fonction de récupération de taille disque non supportée par l''OS '||OS);
	      end if;
		  insert into InfoDsk (DSK_ID, DSK_FREE, DSK_SIZE, BAS_ID) values (dsk, fre, siz, CurrentBD);
		else
		  exit;
		end if;
	  end loop;
      Dbms_Sql.Close_Cursor(Cursorid);
    exception
      when others then
        err_msg := substr(sqlerrm, 1, 2000);
        trace(err_msg);
        Dbms_Sql.Close_Cursor(Cursorid);
    	raise;
    end;
  end if;
end RapatrierInfosDisques;
je met aussi l'exec?
j'ai essayé de tourné ça dans tous les sens mais j'ai toujours des erreurs de compil'
Code :
exec 'LINUXGetDiskInfo'||dblinkname||'(dsk, siz, fre)';
sauf pour:
Code :
execute immediate 'LINUXGetDiskInfo'||dblinkname||'(dsk, siz, fre)';
qui me retourne une erreur ora-00900 instruction sql non valide...
moi26 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2008, 15h10   #10
Rédacteur/Modérateur
 
Avatar de orafrance
 
Inscription : janvier 2004
Messages : 15 861
Détails du profil
Informations personnelles :
Âge : 35

Informations forums :
Inscription : janvier 2004
Messages : 15 861
Points : 16 212
Points : 16 212
Code :
execute immediate 'exec LINUXGetDiskInfo'||dblinkname||'(dsk, siz, fre)';
TOAD ou SQL*Plus ça change rien, ça reste du SQL
orafrance est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2008, 15h33   #11
Membre à l'essai
 
Inscription : septembre 2007
Messages : 109
Détails du profil
Informations forums :
Inscription : septembre 2007
Messages : 109
Points : 22
Points : 22
merci, je n'avais pas du tout compris ça comme ça.

Mais toujours pareil, erreur ora-00900
moi26 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/02/2008, 15h44   #12
Rédacteur/Modérateur
 
Avatar de orafrance
 
Inscription : janvier 2004
Messages : 15 861
Détails du profil
Informations personnelles :
Âge : 35

Informations forums :
Inscription : janvier 2004
Messages : 15 861
Points : 16 212
Points : 16 212
essaye :
Code :
1
2
3
4
5
6
7
8
9
DECLARE
stmt 			VARCHAR2(4000);
BEGIN
stmt := 'BEGIN' || CHR(10);
stmt := stmt || 'LINUXGetDiskInfo'||dblinkname||'(dsk, siz, fre);';
stmt := stmt || 'END;' || CHR(10) || CHR(10);
EXECUTE IMMEDIATE stmt;
END;
/
mais attend... dsk, siz et fre sont des variables...

Essaye plutôt :

Code :
EXECUTE IMMEDIATE 'EXEC LINUXGetDiskInfo'||dblinkname||'(:1, :2, :3)' USING dsk, siz, fre;
orafrance est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/02/2008, 14h14   #13
Membre à l'essai
 
Inscription : septembre 2007
Messages : 109
Détails du profil
Informations forums :
Inscription : septembre 2007
Messages : 109
Points : 22
Points : 22
...non plus.

en local (donc sans ajouter le dblinkname) la procédure s'execute sans souci
Code :
LINUXGetDiskInfo(dsk, siz, fre)
.

mais dès que je veux rajouter un lien dblink...
moi26 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/02/2008, 14h29   #14
Rédacteur/Modérateur
 
Avatar de orafrance
 
Inscription : janvier 2004
Messages : 15 861
Détails du profil
Informations personnelles :
Âge : 35

Informations forums :
Inscription : janvier 2004
Messages : 15 861
Points : 16 212
Points : 16 212
les variables sont probablement mal renseignées... merci de faire une recherche sur EXECUTE IMMEDIATE et faire les modifs en conséquence.
orafrance est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/03/2008, 15h00   #15
Membre à l'essai
 
Inscription : septembre 2007
Messages : 109
Détails du profil
Informations forums :
Inscription : septembre 2007
Messages : 109
Points : 22
Points : 22
Bonjour, ça fait 5 jours que je suis dessus et je ne trouve toujours pas de solution:

j'essaye donc de passer par du sql dynamique sans résultat:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
declare 
dsk varchar2(30);
siz integer;
fre integer;
toto varchar2(500);
dblinkname varchar2(50);
 
begin
dblinkname := '@dblink';
toto:= 'utl_surge.GetDiskInfo'||dblinkname||'(:1,:2,:3)';
execute immediate toto USING dsk, siz, fre;
end;
/
à chaque fois je me retrouve avec ora-00900 instruction sql non valide.
et ora-06512 à la ligne 13.
Pourtant toutes les variables sont bien déclarées.
j'ai l'impression qu'il me refuse le execute immediate

Quelqu'un peu t il m'aider?
je suis à cours de solution...
Merci d'avance
moi26 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/03/2008, 15h47   #16
Rédacteur/Modérateur
 
Avatar de orafrance
 
Inscription : janvier 2004
Messages : 15 861
Détails du profil
Informations personnelles :
Âge : 35

Informations forums :
Inscription : janvier 2004
Messages : 15 861
Points : 16 212
Points : 16 212
il manque le BEGIN et END dans la chaine du SQL dynamique
orafrance est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/03/2008, 17h01   #17
Membre à l'essai
 
Inscription : septembre 2007
Messages : 109
Détails du profil
Informations forums :
Inscription : septembre 2007
Messages : 109
Points : 22
Points : 22
Enfin!

je viens de trouver la solution:

Code :
1
2
3
4
 
requete2 := 'begin utl_surge.GetDiskInfo'||dblinkname;
requete2 := requete2 || '(:1,:2,:3);END;';
execute immediate requete2 USING IN dsk, OUT siz, OUT fre;
Encore merci pour vos aides.
M
moi26 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 19h14.


 
 
 
 
Partenaires

Hébergement Web