Adding row from FOR EACH to TEMP-TABLE - openedge

I'm trying to create a temp-table which is exactly like an already existing table in the database. How do I add each row to the temp table?
DEFINE TEMP-TABLE o_ttProducts.
FOR EACH Product:
/*Add current row to the o_ttProducts temp table*/
END.

DEFINE TEMP-TABLE o_ttProducts no-undo like Product.
FOR EACH Product
no-lock:
/*Add current row to the o_ttProducts temp table*/
create o_ttProducts.
buffer-copy Product to o_ttProducts.
END.

Related

how to create a temp-table for code_mstr in progress 4gl?

I want to create a temp-table for generalized code maintenance(code_mstr) such that the input I give in GCM does not hit the database but instead is stored in a temporary table from where I can update or delete the records. which has the fields
code_fldname
code_value
code_cmmt
code_group
I am very new to progress and this task is a little daunting as I am not understanding how to begin, I have been going through examples and syntax of temp-table, the only thing I managed to write so far is this code which Im not sure is correct or not
define temp-table tt_gcm no-undo
field tt_fldname like code_fldname
field tt_value like code_value
field tt_cmmt like code_cmmt
field tt_group like code_group
field tt_domain like global_domain
index tt_idx
tt_domain
tt_fldname
tt_value.
and after this I defined a form for the same
form
code_fldname
code_value
code_cmmt
code_group
with frame a side-labels
now suppose if I enter a particular record in code_mstr, I want only that one particular record to be visible in the temp-table rather than all the records that are in code_mstr, any help on how to proceed with that would be appreciated.
Something along these lines will fill your temp-table:
for each code_mstr no-lock:
create tt_gcm.
assign
tt_gcm.tt_fldname = code_mstr.code_fldname
tt_gcm.tt_value = code_mstr.code_value
tt_gcm.tt_cmmt = code_mstr.code_cmmt
tt_gcm.tt_group = code_mstr.code_group
tt_gcm.tt_domain = code_mstr.global_domain
.
end.
and this will display the data in the form that you created:
for each tt_gcm:
display tt_gcm with frame a.
end.
If you can keep your temp-table field names the same as your database field names, you can use the buffer-copy statement. It will copy all matching fields from one to the other.
define temp-table tt_gcm no-undo
field global_domain like code_mstr.global_domain
field code_fldname like code_mstr.code_fldname
field code_value like code_mstr.code_value
field code_cmmt like code_mstr.code_cmmt
field code_group like code_mstr.code_group
index tt_idx // add is unique?
global_domain
code_fldname
code_value
.
for each code_mstr no-lock:
create tt_gcm.
buffer-copy code_mstr to tt_gcm.
end.

How to fix Dynamic Query error for progress 4gl?

I am new to progress 4GL. I have written logic for buffer by adding multiple tables into a single query and finding the records from another table by using table field names. I am not sure why I am getting errors. Please help to change the logic
DEFINE VARIABLE ix AS INTEGER NO-UNDO.
DEFINE VARIABLE qh AS HANDLE NO-UNDO.
DEFINE VARIABLE bh AS HANDLE NO-UNDO.
DEFINE VARIABLE fh AS HANDLE NO-UNDO EXTENT 10.
DEFINE VARIABLE cQuery AS CHARACTER NO-UNDO.
CREATE BUFFER bh FOR TABLE "Customer, Invoice".
CREATE QUERY qh.
ASSIGN
cQuery = "FOR EACH Customer NO-LOCK, EACH Invoice WHERE Invoice.Cust-Num = Customer.Cust-
Num NO-LOCK: ".
qh:SET-BUFFERS(bh).
qh:QUERY-PREPARE(cQuery).
qh:QUERY-OPEN().
qh:GET-FIRST().
/* Field Invoice.Cust-Num is already defined in cQuery*/
FIND Order WHERE Order.Cust-Num = Invoice.Cust-Num NO-LOCK NO-ERROR.
IF NOT AVAILABLE Order THEN DO:
FIND Ref-Call WHERE Ref-Call.Cust-Num = Invoice.Cust-Num NO-LOCK NO-ERROR.
DISPLAY Ref-Call.Cust-Num.
END.
qh:QUERY-CLOSE().
bh:BUFFER-RELEASE().
DELETE OBJECT bh.
DELETE OBJECT qh.
Looking at the field names, you're using the classic Sports Database for your training. There's a "newer" Sports2000 demo database with a little bit more of data that might be worth playing with.
There are multiple issues in that program.
First, you cannot define a single dynamic buffer for two tables (Customer, Invoice). This would be causing an error at runtime. You need to:
DEFINE VARIABLE bh1 AS HANDLE NO-UNDO.
DEFINE VARIABLE bh2 AS HANDLE NO-UNDO.
CREATE BUFFER bh1 FOR TABLE "Customer".
CREATE BUFFER bh2 FOR TABLE "Invoice".
and then
qh:ADD-BUFFER(bh1).
qh:ADD-BUFFER(bh2).
The second issue (your compile error), is because the compiler does not see that you're accessing the table Invoice already. bh2 will only at runtime be known to be a buffer for the Invoice table. So you need to access the Cust-Num field dynamically:
FIND Order WHERE Order.Cust-Num = bh2::Cust-Num NO-LOCK NO-ERROR.
Note: You're accessing a single Order by the Cust-Num of the invoice here - I assume, you want to do something like accessing the Order by the Invoice's Order-Num field. That would be a logical mistake, not a syntax error.
However, nothing in your program justifies the need for a dynamic query. That just adds in this case unneeded complexity. You program is not yet iterating the records in the dynamic-query qh - but I assume that's the goal. So this simple static FOR EACH block does the same:
FOR EACH Customer NO-LOCK, EACH Invoice WHERE Invoice.Cust-Num = Customer.Cust-
Num NO-LOCK:
FIND Order WHERE Order.Cust-Num = Invoice.Cust-Num NO-LOCK NO-ERROR.
IF NOT AVAILABLE Order THEN DO:
FIND Ref-Call WHERE Ref-Call.Cust-Num = Invoice.Cust-Num NO-LOCK NO-ERROR.
DISPLAY Ref-Call.Cust-Num.
END /* NOT AVAILABLE */.
END. /* FOR EACH */
Lastly, here:
DELETE OBJECT bh.
DELETE OBJECT qh.
DELETE OBJECT statements belong by their nature into a FINALLY
block.
You need to check validity of the handles before deleting
them:
FINALLY:
IF VALID-HANDLE (bh1) THEN DELETE OBJECT bh1.
IF VALID-HANDLE (bh2) THEN DELETE OBJECT bh2.
IF VALID-HANDLE (qh) THEN DELETE OBJECT qh.
END.
Here is a working example - my changes to your code can generally be identified by being in lower case.
DEFINE VARIABLE qh AS HANDLE NO-UNDO.
DEFINE VARIABLE bhc AS HANDLE NO-UNDO.
DEFINE VARIABLE bhi AS HANDLE NO-UNDO.
DEFINE VARIABLE cQuery AS CHARACTER NO-UNDO.
CREATE BUFFER bhc FOR TABLE "Customer".
create buffer bhi for table "Invoice".
CREATE QUERY qh.
cQuery = "FOR EACH Customer NO-LOCK,"
+ "EACH Invoice WHERE Invoice.CustNum = Customer.CustNum no-lock".
qh:SET-BUFFERS(bhc,bhi).
qh:QUERY-PREPARE(cQuery).
qh:QUERY-OPEN().
do while qh:get-next().
message bhc::CustNum bhi::InvoiceNum.
FIND Order WHERE Order.CustNum = bhi::CustNum NO-LOCK NO-ERROR.
IF NOT AVAILABLE Order THEN DO:
FIND RefCall WHERE RefCall.CustNum = bhi::CustNum NO-LOCK NO-ERROR.
if available RefCall then
message RefCall.CustNum.
END.
end.
finally:
DELETE OBJECT bhc no-error.
DELETE OBJECT bhi no-error.
DELETE OBJECT qh no-error.
end finally.
Watch the example run in ABLdojo.

Finding maximum and minimum value from a field

I have a temp table ttsales which contains a field name t_sales of integer type, I want to find out the maximum and minimum value from a t_sales And on a button click those maximum and minimum value will show. what can I do?
One possibility is to sort the temp-table in ascending and descending order. Adding an index will help. If you cant change the temp-table and its large this might not be the best solution.
DEFINE TEMP-TABLE ttsales NO-UNDO
FIELD t_sales AS INTEGER
INDEX sales t_sales.
DEFINE VARIABLE iMin AS INTEGER NO-UNDO.
DEFINE VARIABLE iMax AS INTEGER NO-UNDO.
CREATE ttsales.
ASSIGN ttsales.t_sales = 10.
CREATE ttsales.
ASSIGN ttsales.t_sales = 1.
CREATE ttsales.
ASSIGN ttsales.t_sales = 130.
CREATE ttsales.
ASSIGN ttsales.t_sales = 2.
/* Get minimum value */
FOR EACH ttsales BY ttsales.t_sales:
iMin = ttsales.t_sales.
LEAVE.
END.
/* Get maximum value */
FOR EACH ttsales BY ttsales.t_sales DESCENDING:
iMax = ttsales.t_sales.
LEAVE.
END.
DISPLAY iMin iMax.
DEFINE QUERY qry FOR tsales.
OPEN QUERY qry FOR EACH tsales BY t_sales.
GET FIRST qry.
MESSAGE tsales.t_sales.
GET LAST qry.
MESSAGE tsales.t_sales.
Depending on size of table, add an index on the field.

How to give an error message if none of the records are matching in FOR EACH loop?

I have written a program for matching one records to another records in FOR Each loop but i don't know how to give an error message if none of the records are matching. Let me share my codes
DEFINE VARIABLE cPos AS INTEGER NO-UNDO.
DEFINE TEMP-TABLE tt_data NO-UNDO
FIELD cPosition AS CHARACTER FORMAT "X(60)"
FIELD cEndCode AS CHARACTER
FIELD cShotCode AS CHARACTER.
/*so many records are stored in tt_data and below is one of the records for your understanding*/
CREATE tt_data.
ASSIGN
tt_data.cPosition ="S$$$^^^^^^^^^^$$$^^^MC^^^^^^^^^^^^R^^^^^^^^^^^^^^^^^^^^^^^^^"
tt_data.cEndCode = 10
tt_data.cShotCode = "S".
cPos = integer( tt_data.cEndCode / 10 ).
/* Consider 60 records available in tt_data */
FOR EACH tt_data.
FIND FIRST tt_date WHERE tt_data.cShotCode =
SUBSTRING(tt_data.cPosition,cPos,1) NO-LOCK NO-ERROR.
DISPLAY tt_data.cShotCode. /* Displayed Value is S */
IF NOT AVAILABLE tt_date THEN
MESSAGE "NONE OF THE RECORDS MATCHING WITH tt_data.cPosition "
LEAVE.
END.
I can get at least one record matching in tt_data. Here the problem is I don't want to LEAVE if any one record is matching but I want to get an error message with LEAVE statement if none of the records are matching. Could you please help this case?
I think this might be what you are trying to do:
DEFINE VARIABLE cPos AS INTEGER NO-UNDO.
DEFINE TEMP-TABLE tt_data NO-UNDO
FIELD cPosition AS CHARACTER FORMAT "X(60)"
FIELD cEndCode AS CHARACTER
FIELD cShotCode AS CHARACTER.
/*so many records are stored in tt_data and below is one of the records for your understanding*/
CREATE tt_data.
ASSIGN
tt_data.cPosition ="S$$$^^^^^^^^^^$$$^^^MC^^^^^^^^^^^^R^^^^^^^^^^^^^^^^^^^^^^^^^"
tt_data.cEndCode = 10
tt_data.cShotCode = "S".
cPos = integer( tt_data.cEndCode / 10 ).
/* Consider 60 records available in tt_data */
FOR EACH tt_data: /* although it 'works', "." is not appropriate, FOR EACH should end with a ":" */
FIND FIRST tt_date WHERE tt_data.cShotCode = SUBSTRING(tt_data.cPosition,cPos,1) NO-LOCK NO-ERROR.
/* changes start here */
IF AVAILABLE tt_date THEN
do:
DISPLAY tt_data.cShotCode. /* Displayed Value is S */ /* only display this when it is available! */
end.
else
do:
MESSAGE "NONE OF THE RECORDS MATCHING WITH tt_data.cPosition ". /* a "." was missing */
/* LEAVE. */
end.
END.
I would personally try to do the error check before you ever get in the FOR EACH block. Sometimes you can't, but based on your sample code I think you could examine the temp-table first and provide an error message. But I'm not completely sure what you are going for based on the sample.
DEFINE VARIABLE cPos AS INTEGER NO-UNDO.
DEFINE TEMP-TABLE tt_data NO-UNDO
FIELD cPosition AS CHARACTER FORMAT "X(60)"
FIELD cEndCode AS CHARACTER
FIELD cShotCode AS CHARACTER.
/*so many records are stored in tt_data and below is one of the records for your understanding*/
CREATE tt_data.
ASSIGN
tt_data.cPosition ="S$$$^^^^^^^^^^$$$^^^MC^^^^^^^^^^^^R^^^^^^^^^^^^^^^^^^^^^^^^^"
tt_data.cEndCode = 10
tt_data.cShotCode = "S".
cPos = integer( tt_data.cEndCode / 10 ).
/* Add check here */
IF can-find( FIRST tt_date WHERE
tt_data.cShotCode = SUBSTRING(tt_data.cPosition,cPos,1 ) )
THEN
message "ERROR message".
ELSE DO:
/* Consider 60 records available in tt_data */
FOR EACH tt_data.
/* DO thing */
END.
END.

SQLITE: How to create table as another table and set default value?

the code i use:
$query = "CREATE TABLE `new_form` as select * from `form`
but new_form can't have default value
like column ID can't auto_increment.
This is not possible with CREATE TABLE … AS SELECT ….
You have to create the new table manually before copying the data.

Resources