L'utilisation de DBMS_LOB est-elle nécessaire lors du renvoi de CLOB à partir d'une procédure PL / SQL?

StackOverflow https://stackoverflow.com/questions/1613408

Question

J'aimerais créer des procédures PL / SQL qui renvoient XML en tant que paramètres CLOB. Je veux juste faire ceci (ce qui fonctionne bien avec des tests simples):

create or replace procedure p_xml_test_1(
  p_xml out nocopy clob
) is
begin
  p_xml := '<?xml version="1.0" encoding="utf8" ?>' ||
    '<test><something>some value</something></test>';
end p_xml_test_1;

Mais j'ai accès à un autre code source qui fait essentiellement ceci:

create or replace procedure p_xml_test_2(
  p_xml out nocopy clob
) is
  lv_xml clob;
begin
  dbms_lob.createtemporary(
    lob_loc => p_xml,
    cache   => true
  );

  lv_xml := '<?xml version="1.0" encoding="utf8" ?>' ||
    '<test><something>some value</something></test>';

  dbms_lob.writeappend(
    lob_loc => p_xml,
    amount  => length(lv_xml),
    buffer  => lv_xml
  );
end p_xml_test_2;

Je me demande si la première méthode me causera des problèmes plus tard. Est-ce correct de le faire de cette façon? Quel est l'avantage, le cas échéant, de la deuxième méthode? Merci!

Était-ce utile?

La solution

Je pense que vous devriez mesurer les performances des deux méthodes en les exécutant plusieurs fois en boucle. Je pense que la performance est la seule différence. Votre bloc xml est court, mais lorsque vous concaténez un gros bloc xml, il est plus rapide de concaténer avec dbms_low.writeappend que d'utiliser ||.

(Au moins dans Oracle 9, la différence de performances est moindre dans Oracle 10.)

Autres conseils

J'ai exécuté les procédures suivantes pour comparer le temps d'exécution:

Version 1

create or replace procedure p_xml_test_1(
  p_xml out nocopy clob
) is
  lv_i number;
begin
  for lv_i in 1 .. 999999 loop
    p_xml := p_xml || 'a';
  end loop;
end p_xml_test_1;

Version 2

create or replace procedure p_xml_test_2(
  p_xml out nocopy clob
) is
  lv_xml clob;
  lv_i   number;
begin
  dbms_lob.createtemporary(
    lob_loc => p_xml,
    cache   => true
  );

  for lv_i in 1 .. 999999 loop
    lv_xml := 'a';

    dbms_lob.writeappend(
      lob_loc => p_xml,
      amount  => length(lv_xml),
      buffer  => lv_xml
    );
  end loop;
end p_xml_test_2;

La différence est négligeable. Tous deux arrivent à environ 0,2 seconde de façon constante.

Si je modifie les procédures en boucle en 999999 au lieu de 10 000, les performances de la version 1 commencent à décliner quelque peu (environ 39 secondes par rapport à 32 secondes pour la version 2).

Je ne vois aucune raison pour laquelle vous voudriez utiliser le second.

Si lv_xml était un VARCHAR2 plutôt qu'un CLOB, je vois une très bonne raison (la longueur maximale d'un littéral de chaîne par rapport à la longueur maximale d'un CLOB).

Merci pour les réponses. D'après ce que j'ai lu sur le site indiqué ci-dessous, je vais supposer que c'est en fait une bonne chose d'utiliser dbms_lob.writeappend. Si je ne le fais pas, je pourrais aussi bien utiliser VARCHAR2 (qui ne sera pas assez gros dans certains cas).

  

Si vous avez une variable CLOB appelée "l_clob", et que vous faites quelque chose comme "l_clob: = l_clob || l_some_string_to_concatenate; "", il convertira la valeur l_clob située à droite de l'équation en un VARCHAR2 avant la concaténation, ce qui pourrait vous donner des résultats incorrects ou une erreur.

http://www.maristream.org/srea/Huge_Strings_Using_LOBs.htm

Il existe une autre option que vous ne mentionnez pas: utiliser la fonctionnalité XML intégrée d'Oracle (en supposant que vous disposiez d'une version de base de données de 9i ou supérieure). Par exemple, la génération d'un document XML à partir d'une requête est une capture avec DBMS_XMLGEN.getXML () ou DBMS_XMLGEN.getXMLType () .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top