【问题标题】:How to replace static "query" way of working by dynamic "queries"?如何用动态“查询”替换静态“查询”工作方式?
【发布时间】:2021-06-02 23:59:56
【问题描述】:

other question 中,我询问了如何处理可能定义或未定义表的情况。我试图遵循的建议解决方案是使用动态“查询”而不是静态查询。不幸的是,我不知道该怎么做,有人可以帮我吗?举个例子吧:

静态工作方式:

FIND Table1 WHERE Table1.field1          = 123
                AND Table1.field2        = Current-Table.field2
                AND UPPER(Table1.field3) = "Constant-string"
                AND Table1.field4        = temp-table.field4 NO-ERROR.
IF NOT AVAILABLE Table1
  THEN DO:
           CREATE Table1.
           ASSIGN Table1.field1 = 123
                  Table1.field2 = Current-Table.field2
                  Table1.field3 = "Constant-string"
                  Table1.field4 = temp-table.field4.
           RELEASE Table1.
       END.

动态工作方式:

CREATE BUFFER h-Table1 FOR TABLE "Table1" NO-ERROR.
IF VALID-HANDLE(h-Table1)
THEN DO:
         L-Found = h-Table1:FIND-FIRST("WHERE Table1.field1 = " + STRING(123) + 
                                         "AND Table1.field2   = " + STRING(Current-Table.field2) +
                                         "AND UPPER(Table1.field3) = 'Constant-string'" + 
                                         "AND Table1.field4 = " + temp-table.field4) NO-ERROR.
         IF NOT L-Found
         THEN DO:
                  h-Table1:BUFFER-CREATE("").
              END.
         ELSE MESSAGE "FOUND".
     END.

BUFFER-CREATE还是其他方法,参数怎么填(比如ASSIGN Table1.Field1 = 123),...?

【问题讨论】:

  • 请注意,您正在将静态 UNIQUE 查找替换为动态 FIRST 查找。此外,在连接查询时,您确实希望使用 SUBSTITUTE 和 QUOTER 来防止查询注入。
  • @StefanDrissen:我不明白你的意思,但我刚刚发现以下查询似乎不起作用:h-Table1:FIND-FIRST("WHERE Table1.field1 = " + STRING(field1_value) + "AND Table1.field2 = " + STRING(field2_value) + "AND UPPER(Table1.field3) = 'FIX_STRING'" + "AND Table1.field4 = " + temp_table.field4) NO-ERROR.,这是你在说什么,我该如何解决这使用了SUBSTITUTEQUOTER(最后不是错字吗?)?
  • 首先删除 NO-ERROR,因为这也会隐藏查询中的语法错误。 quoter 不是错字,我会在我的答案中添加您的 find-unique 应该是什么样的。
  • @StefanDrissen:基于QUOTER() 函数的查询(我还没有使用SUBSTITUE())工作正常,但是当我尝试删除表记录时,我陷入了运行时错误 335。为此,我创建了一个新的 StackOverflow 帖子:stackoverflow.com/questions/66489158/…

标签: openedge progress-4gl dynamicquery dynamic-queries


【解决方案1】:

用途:

def var hb as handle no-undo.

create buffer hb for table "mytable".
hb:buffer-create().
assign
   hb::myfield = 123
   hb::another = "ok"
   .
hb:buffer-release()

finally:
   delete object hb no-error.
end finally.

请注意,hb::myfield 是简写

hb:buffer-field('myfield'):buffer-value

还要注意,在使用动态对象时,您需要负责垃圾收集。如果你创建它,你需要删除它。

动态查找唯一部分:

def var hb     as handle  no-undo.
def var lfound as logical no-undo.

create buffer hb for table 'Table1'.

lfound = hb:find-uniqe(
            'where field1 = 123'
            +  ' and field2 = ' + quoter( current-table.field2 ) )
            +  ' and upper( field3 ) = "constant-string"'
            +  ' and field4 = ' + quoter( temp-table.field4 ) 
         ) no-error.

或使用替代品:

lfound = hb:find-unique(
            substitute(
               'where field1 = &1':u
               +  ' and field2 = &2':u
               +  ' and upper( field3 ) = &3':u
               +  ' and field4 = &4':u,
               123,
               quoter( current-table.field2 ),
               quoter( 'constant-string' ),
               quoter( temp-table.field4 )
            )
         ) no-error.

您很快就会想要创建一个查询构建器类/函数来处理创建查询并可能还处理您现在也负责的运行时验证。

【讨论】:

  • 您还要对事务控制负责,因为 AVM 不能自动为动态缓冲区划定事务范围。
  • 另外,CREATE BUFFER 语句仅在使用 BUFFER-NAME 子句时才像 DEFINE BUFFER 语句一样工作(在处理泄漏记录范围时发现)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-12
  • 2019-10-20
  • 2013-08-18
  • 2020-11-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多