Wenn ich ARRAYSIZE 1 in SQL * Plus einstelle, werden die Datensätze immer noch paarweise abgerufen. Warum?

7

Ich dachte darüber nach, ein einfaches tail -f Hilfsprogramm zu schreiben , um den Fortschritt einiger Zahlen in der Datenbank zu "verfolgen":

create or replace function tail_f return varchar2_tab pipelined as
   n number;
begin

    loop
      exit when ...

      select count(*) into n from ... where ...;

      pipe row(sysdate || ' n= ' || n);
      dbms_lock.sleep(60);
    end loop;

    return;
end tail_f;

Und dann möchte ich select * from table(tail_f)in SQL * Plus.

Um die Zeilen einzeln abzurufen, habe ich SET ARRAYSIZE 1. Die Datensätze (mit Ausnahme des ersten) werden jedoch paarweise abgerufen.

Gibt es eine Erklärung dafür und wie kann ich die Aufzeichnungen erhalten, sobald eine weitergeleitet wird?

René Nyffenegger
quelle

Antworten:

9

Metalink-Fehler 9103343 besagt:

Dies ist erwartetes Verhalten. SQL * Plus ist in oci geschrieben und oci hat einen Standard-Prefetch-Wert von 1 Zeile. Der Vorabruf beim Abrufen (im Gegensatz zum Ausführen) erfolgt jedoch nur, wenn Sie keinen Array-Abruf durchführen. Wenn also die Array-Größe 1 ist, beträgt der erste Abruf in der Ablaufverfolgung unabhängig von der Array-Größe immer 1 Zeile, da 1 Zeile vorab abgerufen wird die ausführen. Dann führt es entweder einen skalaren Abruf durch, also eine angeforderte Zeile plus eine vorabgerufene Zeile, oder es führt einen Array-Abruf durch, so dass Sie beispielsweise sehen: a) Arraysize = 1, Abrufe sind: 1, 2, 2, ... b) Arraysize = 2, Abrufe sind: 1, 2, 2, ... c) Arraysize = 5, Abrufe sind: 1, 5, 5, ...

Siehe auch Metalink doc 1265916.1

Philᵀᴹ
quelle
Vielen Dank, dass Sie meinen Verdacht mit der Metalink-Notiz bestätigt haben.
René Nyffenegger
5

Dies scheint eine Eigenart von SQL * Plus zu sein und keine arraysizePipeline-Funktionen - das Folgende zeigt den gleichen Effekt:

create or replace function pause return integer as
begin
  dbms_lock.sleep(2);
  return 1;
end;
/

select pause from dual connect by level<10;

Sie können das Problem (irgendwie) umgehen, indem Sie die Zeilen zweimal auswählen und jede zweite verwerfen:

select /*+ ordered first_rows(1) */ *
from table(tail_f) cross join (select level from dual connect by level<=2);
Jack sagt, versuchen Sie es mit topanswers.xyz
quelle