简体   繁体   English

我可以在 Progress-4GL 中创建缓冲区时指定缓冲区的内容吗?

[英]Can I specify the contents of the buffer while creating it in Progress-4GL?

Noob to Progress here and self-taught while working so sorry if I missed some obvious things.菜鸟在这里进步和自学,如果我错过了一些明显的事情,我很抱歉。 I learned about buffers yesterday and I'd like to know if it's possible to delimit the scope of what the buffer will search.我昨天了解了缓冲区,我想知道是否可以将缓冲区搜索的 scope 分隔开。 Below, an example of what I want to know.下面,一个我想知道的例子。

DEFINE BUFFER ex1 FOR emit WHERE emit.id > 50000.

FOR EACH ex1:
    DISP ex1.id ex1.name.
end.

I know I could put the WHERE on the FOR EACH part in this example, but I'd like to know if and how can I delimit the buffer so I can do what I intend to in my code here.我知道我可以在这个例子中将 WHERE 放在 FOR EACH 部分,但我想知道是否以及如何分隔缓冲区,以便我可以在这里的代码中做我想做的事情。

Thanks for the help.谢谢您的帮助。

EDIT: I'll put the code I wrote here so it's easier to understand what I meant.编辑:我会把我写的代码放在这里,这样更容易理解我的意思。 I really don't see any other solutions besides using temp-tables and it makes everything so much slower.除了使用临时表之外,我真的没有看到任何其他解决方案,它让一切变得如此缓慢。 I'll keep my code like this but if anyone knows of a better solution, just give me a shout.我会这样保留我的代码,但如果有人知道更好的解决方案,请大声告诉我。 Thanks again for your time.感谢你的宝贵时间。

def var contador as int.
def var contador2 as int.
def var contador3 as int.

def temp-table tt-min-oper 
field it-codigo like operacao.it-codigo
field num-id-operacao like operacao.num-id-operacao
field op-codigo like operacao.op-codigo
.

def temp-table tt-oper 
field it-codigo like operacao.it-codigo
field op-codigo like operacao.op-codigo
.

def temp-table tt-valida-oper 
field it-codigo like operacao.it-codigo
.

for each operacao NO-LOCK
break by operacao.it-codigo by operacao.num-id-operacao:
    IF FIRST-OF (operacao.it-codigo) THEN DO:
        
        CREATE tt-min-oper.
        ASSIGN
        tt-min-oper.it-codigo = operacao.it-codigo
        tt-min-oper.num-id-operacao = operacao.num-id-operacao
        tt-min-oper.op-codigo = operacao.op-codigo
        .
    END.
END.

FOR EACH tt-min-oper WHERE tt-min-oper.op-codigo <> 10 NO-LOCK:
    create tt-oper.
    assign tt-oper.it-codigo = tt-min-oper.it-codigo.
END.


FOR EACH operacao NO-LOCK,
    EACH tt-oper
    WHERE operacao.it-codigo = tt-oper.it-codigo
    AND operacao.op-codigo = 10 NO-LOCK:
       
        create tt-valida-oper.
        assign
        tt-valida-oper.it-codigo = operacao.it-codigo.
    
END.

You limit results in the query, the FOR EACH statement in your case, so您在查询中限制结果,在您的情况下是 FOR EACH 语句,所以

DEFINE BUFFER ex1 FOR emit .

FOR EACH ex1 WHERE ex1.id > 50000:
    DISP ex1.id ex1.name.
end.

Answer to the extended question of the OP.回答 OP 的扩展问题。

Answering this without knowing your use-case and details about the table relations is always difficult.在不知道您的用例和有关表关系的详细信息的情况下回答这个问题总是很困难的。 But from your code:但从你的代码:

In the final FOR EACH, you're only iterating operacao records where first the it-codigo is unique (then you put it into tt-min-oper).在最后的 FOR EACH 中,您只需要迭代 opacao 记录,其中首先 it-codigo 是唯一的(然后将其放入 tt-min-oper 中)。 Then you filter tt-min-oper for op-codigo <> 10 and add the resulting records into tt-oper.然后过滤 tt-min-oper 为 op-codigo <> 10 并将结果记录添加到 tt-oper。

So at this time tt-oper should contain records with unique it-codigo values and op-codigo <> 10.所以此时 tt-oper 应该包含具有唯一 it-codigo 值和 op-codigo <> 10 的记录。

So at the minimum you don't need this loop here:所以至少你在这里不需要这个循环:

FOR EACH tt-min-oper WHERE tt-min-oper.op-codigo <> 10 NO-LOCK:
    create tt-oper.
    assign tt-oper.it-codigo = tt-min-oper.it-codigo.
END.

as in the initial FOR EACH you could filter on op-codigo <> 10 as well:与最初的 FOR EACH 一样,您也可以过滤 op-codigo <> 10 :

for each operacao WHERE operacao.op-codigo <> 10 NO-LOCK
break by operacao.it-codigo by operacao.num-id-operacao:

How many records are in the able operacao?能干的歌剧有多少条记录? And is there an index with it-codigo as the first field?是否有以 it-codigo 作为第一个字段的索引? The FOR EACH with BREAK-BY will still retrieve all records in the table, but only process the FIRST-OF (it-codigo) ones.带有 BREAK-BY 的 FOR EACH 仍将检索表中的所有记录,但仅处理 FIRST-OF (it-codigo) 记录。 That may be a very heavy operation.这可能是一个非常繁重的操作。

In large tables, if may be better to do something like this instead of a FOR EACH with BREAK-BY.在大表中,如果做这样的事情而不是使用 BREAK-BY 的 FOR EACH 可能会更好。 My Order table has 700000 records, so this here processes all 700000 records:我的 Order 表有 700000 条记录,所以这里处理所有 700000 条记录:

FOR EACH Order BREAK BY Order.Salesrep:
        
    IF FIRST-OF (Order.Salesrep) THEN
    DO:
        DISPLAY Order.Salesrep . 
    END.
END.

And this here get'S the same result, but only reads 10 records (there are 10 Salesreps in the DB).这在这里得到相同的结果,但只读取 10 条记录(数据库中有 10 个销售代表)。 But this is only possible as there is an index for the Salesrep field.但这只有在 Salesrep 字段有索引时才有可能。

DEFINE VARIABLE cPrevious-Salesrep AS CHARACTER NO-UNDO . 

FIND FIRST Order WHERE Order.Salesrep > cPrevious-Salesrep
    NO-LOCK NO-ERROR . 
    
DO WHILE AVAILABLE (Order):
    DISPLAY Order.Salesrep WITH DOWN . 
    DOWN 1 .
    
    ASSIGN cPrevious-Salesrep = Order.Salesrep. 

    FIND NEXT Order WHERE Order.Salesrep > cPrevious-Salesrep
        NO-LOCK NO-ERROR . 
END.

So to optimize your code, you need to know your DB schema and actual data.因此,要优化您的代码,您需要了解您的数据库架构和实际数据。

The code I posted before took several minutes to compile.我之前发布的代码需要几分钟才能编译。 I managed to reduce it a lot by putting a FOR EACH inside another (now it only takes 25 seconds).我通过将 FOR EACH 放入另一个中来设法减少了很多(现在只需要 25 秒)。 Unfortunately, I can't filter op-codigo <> 10 in the first FOR EACH because it changes the results.不幸的是,我无法在第一个 FOR EACH 中过滤 op-codigo <> 10,因为它会改变结果。 I didn't use USE-INDEX because I read Tom Bascom saying it wasn't good, but we have indexes in the tables we're using.我没有使用 USE-INDEX 因为我读到 Tom Bascom 说它不好,但是我们在使用的表中有索引。 I don't know a lot about the tables, because I'm fairly new here and I'm still learning a lot.我对桌子了解不多,因为我在这里还很新,而且我还在学习很多东西。

So my code became like the example below.所以我的代码变成了下面的例子。 I don't know if it's good to put a FOR EACH inside another and I always avoided it, but all my colleagues do it.我不知道将 FOR EACH 放在另一个里面是否好,我总是避免这样做,但我所有的同事都这样做。

DEF TEMP-TABLE tt-min-oper 
FIELD it-codigo         LIKE operacao.it-codigo
FIELD num-id-operacao   LIKE operacao.num-id-operacao
FIELD op-codigo         LIKE operacao.op-codigo
.

DEF TEMP-TABLE tt-valida-oper 
FIELD it-codigo LIKE operacao.it-codigo
FIELD num-id-operacao   LIKE operacao.num-id-operacao
.


FOR EACH operacao NO-LOCK
BREAK BY operacao.it-codigo BY operacao.num-id-operacao:
    IF FIRST-OF (operacao.it-codigo) THEN DO:
    CREATE tt-min-oper.
       ASSIGN
       tt-min-oper.it-codigo = operacao.it-codigo
       tt-min-oper.num-id-operacao = operacao.num-id-operacao
       tt-min-oper.op-codigo = operacao.op-codigo
       .          
     END.
 END.

FOR EACH tt-min-oper
WHERE tt-min-oper.op-codigo <> 10 NO-LOCK:
    FOR EACH operacao
    WHERE operacao.it-codigo = tt-min-oper.it-codigo
    AND operacao.op-codigo = 10 NO-LOCK:
        CREATE tt-valida-oper.
        ASSIGN
        tt-valida-oper.it-codigo = operacao.it-codigo
        tt-valida-oper.num-id-operacao = tt-min-oper.num-id-operacao
        .
    END.
END.

I couldn't find a solution for buffers like I wanted, but I managed to do it in a way I've never done before, so I see this as a victory.我找不到我想要的缓冲区解决方案,但我设法以我以前从未做过的方式做到了,所以我认为这是一场胜利。 Thanks for your time and suggestions Mike and if there's any other suggestion, I'm all open to it.感谢您的时间和建议迈克,如果有任何其他建议,我都愿意接受。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM