progress-4gl
TEMP-TABELLA
Ricerca…
introduzione
TEMP-TABLE
è una funzionalità molto potente di Progress ABL. È una tabella temporanea in memoria (per lo più almeno) che può essere utilizzata per scrivere logica complessa. Può essere utilizzato come parametri di input / output per procedure, funzioni e altri programmi. Uno o più tabelle temporanee possono costituire le basi di un DATASET
(spesso chiamato ProDataset).
Quasi tutto ciò che può essere fatto con una tabella di database Progress nativa può essere fatto con una tabella temporanea.
Definire un semplice temp-table
Questa è la definizione di TEMP-TABLE
chiamata ttTempTable con tre campi. NO-UNDO
indica che non è necessaria alcuna operazione di annullamento (di solito è ciò che si vuole fare a meno che non si abbia realmente bisogno del contrario).
DEFINE TEMP-TABLE ttTempTable NO-UNDO
FIELD field1 AS INTEGER
FIELD field2 AS CHARACTER
FIELD field3 AS LOGICAL.
Una tabella temporanea con un indice
Le tabelle temporanee possono (e dovrebbero) essere create con indici se si prevede di eseguire query su di esse.
Questa tabella ha un indice (indice1) contenente un campo (campo1). Questo indice è primario e unico (il che significa che non due record possono avere lo stesso contenuto del campo1).
DEFINE TEMP-TABLE ttTempTable NO-UNDO
FIELD field1 AS INTEGER
FIELD field2 AS CHARACTER
FIELD field3 AS LOGICAL
INDEX index1 IS PRIMARY UNIQUE field1 .
Più indici - indici ...
È possibile definire più indici per ogni tabella temporanea. Se ne hai bisogno, definiscili. Fondamentalmente un indice che corrisponde alla tua query e / o al tuo ordinamento aiuterà le prestazioni!
DEFINE TEMP-TABLE ttWithIndex NO-UNDO
FIELD field1 AS INTEGER
FIELD field2 AS CHARACTER
FIELD field3 AS LOGICAL
INDEX field1 field1.
DEFINE TEMP-TABLE ttWithoutIndex NO-UNDO
FIELD field1 AS INTEGER
FIELD field2 AS CHARACTER
FIELD field3 AS LOGICAL.
DEFINE VARIABLE i AS INTEGER NO-UNDO.
DEFINE VARIABLE iWithCreate AS INTEGER NO-UNDO.
DEFINE VARIABLE iWithFind AS INTEGER NO-UNDO.
DEFINE VARIABLE iWithoutCreate AS INTEGER NO-UNDO.
DEFINE VARIABLE iWithoutFind AS INTEGER NO-UNDO.
ETIME(TRUE).
DO i = 1 TO 1000:
CREATE ttWithIndex.
ttWithIndex.field1 = i.
END.
iWithCreate = ETIME.
ETIME(TRUE).
DO i = 1 TO 1000:
CREATE ttWithoutIndex.
ttWithoutIndex.field1 = i.
END.
iWithoutCreate = ETIME.
RELEASE ttWithIndex.
RELEASE ttWithoutIndex.
ETIME(TRUE).
DO i = 1 TO 1000:
FIND FIRST ttWithIndex WHERE ttWithIndex.field1 = i NO-ERROR.
END.
iWithFind = ETIME.
ETIME(TRUE).
DO i = 1 TO 1000:
FIND FIRST ttWithoutIndex WHERE ttWithoutIndex.field1 = i NO-ERROR.
END.
iWithoutFind = ETIME.
MESSAGE
"With index took" iWithFind "ms to find and" iWithCreate "ms to create" SKIP
"Without index took" iWithoutFind "ms to find and" iWithoutCreate "ms to create"
VIEW-AS ALERT-BOX.
La ricerca con indice era circa 70 volte più veloce rispetto a nessun indice! Questa è solo una corsa, quindi non una prova scientifica, ma l'impostazione dell'indice avrà un impatto.
Inserimento e emissione di tabelle temporanee
È molto semplice passare le tabelle temporanee dentro e fuori dai programmi, dalle procedure e dalle funzioni.
Questo può essere utile se si desidera una procedura per elaborare un numero maggiore di dati rispetto a quelli che è possibile memorizzare facilmente in una stringa o simili. È possibile passare tabelle temporanee come dati INPUT
, OUTPUT
e INPUT-OUTPUT
.
Immissione di una tabella temporanea e uscita di un'altra:
DEFINE TEMP-TABLE ttRequest NO-UNDO
FIELD fieldA AS CHARACTER
FIELD fieldB AS CHARACTER.
/* Define a temp-table with the same fields and indices */
DEFINE TEMP-TABLE ttResponse NO-UNDO LIKE ttRequest.
/* A procedure that simply swap the values of fieldA and fieldB */
PROCEDURE swapFields:
DEFINE INPUT PARAMETER TABLE FOR ttRequest.
DEFINE OUTPUT PARAMETER TABLE FOR ttResponse.
FOR EACH ttRequest:
CREATE ttResponse.
ASSIGN
ttResponse.fieldA = ttRequest.fieldB
ttResponse.fieldB = ttRequest.fieldA.
END.
END PROCEDURE.
CREATE ttRequest.
ASSIGN ttRequest.fieldA = "A"
ttRequest.fieldB = "B".
CREATE ttRequest.
ASSIGN ttRequest.fieldA = "B"
ttRequest.fieldB = "C".
CREATE ttRequest.
ASSIGN ttRequest.fieldA = "C"
ttRequest.fieldB = "D".
/* Call the procedure */
RUN swapFields ( INPUT TABLE ttRequest
, OUTPUT TABLE ttResponse).
FOR EACH ttResponse:
DISPLAY ttResponse.
END.
Risultato:
fieldA--------fieldB--------
B A
C B
D C
Input-outputting di una tabella temporanea:
DEFINE TEMP-TABLE ttCalculate NO-UNDO
FIELD num1 AS INTEGER
FIELD num2 AS INTEGER
FIELD response AS DECIMAL.
PROCEDURE pythagoras:
DEFINE INPUT-OUTPUT PARAMETER TABLE FOR ttCalculate.
FOR EACH ttCalculate:
ttCalculate.response = SQRT( EXP(num1, 2) + EXP(num2, 2)).
END.
END PROCEDURE.
CREATE ttCalculate.
ASSIGN ttCalculate.num1 = 3
ttCalculate.num2 = 4.
CREATE ttCalculate.
ASSIGN ttCalculate.num1 = 6
ttCalculate.num2 = 8.
CREATE ttCalculate.
ASSIGN ttCalculate.num1 = 12
ttCalculate.num2 = 16.
/* Call the procedure */
RUN pythagoras ( INPUT-OUTPUT TABLE ttCalculate ).
FOR EACH ttCalculate:
DISPLAY ttCalculate.
END.
Risultato:
----------num1-- ----------num2-- -------response-
3 4 5.00
6 8 10.00
12 16 20.00
Passando alle funzioni
DEFINE TEMP-TABLE ttNumbers NO-UNDO
FIELD num1 AS INTEGER
FIELD num2 AS INTEGER
INDEX index1 num1 num2.
DEFINE VARIABLE iNum AS INTEGER NO-UNDO.
/* Forward declare the function */
FUNCTION hasAPair RETURNS LOGICAL (INPUT TABLE ttNumbers) FORWARD.
DO iNum = 1 TO 100:
CREATE ttNumbers.
ASSIGN ttNumbers.num1 = RANDOM(1,100)
ttNumbers.num2 = RANDOM(1,100).
END.
MESSAGE hasAPair(INPUT TABLE ttNumbers) VIEW-AS ALERT-BOX.
/* Function to check if two records has the same value in num1 and num2 */
FUNCTION hasAPair RETURNS LOGICAL (INPUT TABLE ttNumbers):
FIND FIRST ttNumbers WHERE ttNumbers.num1 = ttNumbers.num2 NO-ERROR.
IF AVAILABLE ttNumbers THEN
RETURN TRUE.
ELSE
RETURN FALSE.
END FUNCTION.
Passando ai file di programma
Passi i temp-tables da e verso altri programmi .p nello stesso modo in cui li passi ad altre procedure. L'unica differenza è che sia la chiamata che il programma chiamato devono avere la stessa dichiarazione di tabella temporanea. Un modo semplice è quello di memorizzare il programma temp-table in un terzo file - un inclusivo usato in entrambi i programmi.
Include file contenente la definizione di temp-table: / * ttFile.i * / DEFINE TEMP-TABLE ttFile NO-UNDO FIELD fName COME FORMATO CARATTERE "x (20)" CAMPO isADirectory AS LOGICAL.
Programma che controlla tutti i file in una tabella temporanea. Sono directory?
/* checkFiles.p */
{ttFile.i}
DEFINE INPUT-OUTPUT PARAMETER TABLE FOR ttFile.
FOR EACH ttFile:
FILE-INFO:FILE-NAME = ttFile.fName.
IF FILE-INFO:FILE-TYPE BEGINS "D" THEN
ttFile.isADirectory = TRUE.
END.
Programma principale:
{ttFile.i}
CREATE ttFile.
ASSIGN ttFile.fname = "c:\temp\".
CREATE ttFile.
ASSIGN ttFile.fname = "c:\Windows\".
CREATE ttFile.
ASSIGN ttFile.fname = "c:\Windoose\".
RUN checkFiles.p(INPUT-OUTPUT TABLE ttFile).
FOR EACH ttFile:
DISPLAY ttFile.
END.
Risultato:
fName----------------- isADirector
c:\temp\ yes
c:\Windows\ yes
c:\Windoose\ no