在为并行处理创建的DB2函数中使用临时表。.

时间:2019-09-16 21:55:15

标签: db2 db2-400

编辑:我在原始问题的末尾添加了更多内容。

[原始问题]:

在DB2 SQL表函数中,是否可以将已声明的全局临时表的范围限制为该函数的当前实例。这是DB2-for-i v7r3m0。

我正在计划一个用于分析字符数据的表函数。为此,该函数需要一个临时表来缓存信息,然后该信息将以不同的方式反复循环遍历,直到达到结果为止。我首先想到的是使用一个声明的全局临时表,但是有一个“ global”这个词。

为了获得更高的效率,我想用ALLOW PARALLEL,可能还用NOT FENCED来编写函数,但是这两个选项似乎与DGTT的本质冲突。

此外,由于需要使用MODIFIES SQL DATA来写DGTT,所以我不确定是否可以使用ALLOW PARALLEL来使用table-name,即使对该函数进行了精心设计。

documentation使我有些困惑;也许我不明白什么?在开始的段落中说:

  

每个应用程序进程都定义一个已声明的临时表   具有相同名称的临时表具有其唯一的描述。

然后在-- THIS SCRIPT WAS NOT INTENDED TO BE THE FINAL PRODUCT, BUT MAY END UP CLOSE -- DGTTs AND MULTIPLE RESULT WINDOWS WERE INTENDED TO EXAMININE EACH STEP -- UNCOMMENT ANY OF THE SELECT STATEMENTS TO SEE WHAT'S GOING ON THERE -- THIS IS HARD-CODED TO PROCESS UP TO (9) WORDS -- IF RE-WRITTEN WITH LOOPS, IT'D BE MORE COMPACT AND SUPPORT ANY NUMBER OF WORDS DECLARE GLOBAL TEMPORARY TABLE SESSION.WORDS AS ( WITH PASS1 AS ( SELECT LPAD(TRIM(CHAR(BXUPCR)),14,'0') AS BXUPCR, UPPER(TRIM(REGEXP_SUBSTR(BXADDS,'[^ ]+',1,1,'i'))) AS W1, UPPER(TRIM(REGEXP_SUBSTR(BXADDS,'[^ ]+',1,2,'i'))) AS W2, UPPER(TRIM(REGEXP_SUBSTR(BXADDS,'[^ ]+',1,3,'i'))) AS W3, UPPER(TRIM(REGEXP_SUBSTR(BXADDS,'[^ ]+',1,4,'i'))) AS W4, UPPER(TRIM(REGEXP_SUBSTR(BXADDS,'[^ ]+',1,5,'i'))) AS W5, UPPER(TRIM(REGEXP_SUBSTR(BXADDS,'[^ ]+',1,6,'i'))) AS W6, UPPER(TRIM(REGEXP_SUBSTR(BXADDS,'[^ ]+',1,7,'i'))) AS W7, UPPER(TRIM(REGEXP_SUBSTR(BXADDS,'[^ ]+',1,8,'i'))) AS W8, UPPER(TRIM(REGEXP_SUBSTR(BXADDS,'[^ ]+',1,9,'i'))) AS W9 FROM F_CERTOB.BEERXT AS BEERT INNER JOIN F_CERTOB.INVENT AS INVEN ON BXITEM=IYITEM WHERE BXPACK > 999 AND BXUPCR > 0 AND BXUM = 'CB' AND IYWHSE = '1' AND IYSTAT IN ('A','B') ) --PASS #2: GROUP ITMES WITH IDENTICAL UPC & TEXT. THIS IS VERY FEW ITEMS OUT OF ALL. SELECT BXUPCR, W1, W2, W3, W4, W5, W6, W7, W8, W9, COUNT(*) AS C FROM PASS1 GROUP BY BXUPCR, W1, W2, W3, W4, W5, W6, W7, W8, W9 ) WITH DATA WITH REPLACE @ --SELECT * FROM SESSION.WORDS ORDER BY 1,2,3,4,5,6,7,8,9,10 @ --NUMBER OF ITEMS PER UPC DECLARE GLOBAL TEMPORARY TABLE SESSION.WCNT AS ( SELECT BXUPCR, COUNT(BXUPCR) AS UPC_COUNT FROM SESSION.WORDS GROUP BY BXUPCR ) WITH DATA WITH REPLACE @ --SELECT * FROM SESSION.WCNT ORDER BY 1 @ --FUNNEL CERTAIN ITEMS FOR TESTING ------------FOR DEV ONLY --THIS CAN BE REMOVED AND PATCHED AROUND LATER DECLARE GLOBAL TEMPORARY TABLE SESSION.FUNNEL AS ( SELECT A.BXUPCR, A.W1, A.W2, A.W3, A.W4, A.W5, A.W6, A.W7, A.W8, A.W9 FROM SESSION.WORDS AS A INNER JOIN SESSION.WCNT AS B ON A.BXUPCR=B.BXUPCR ) WITH DATA WITH REPLACE @ --SELECT * FROM SESSION.FUNNEL ORDER BY 1 @ --GROUPS OF (1) WORD: DECLARE GLOBAL TEMPORARY TABLE SESSION.GRP1 AS ( SELECT BXUPCR, W1, UPC_COUNT, COUNT(*) AS UPC_GROUP_COUNT, 1 AS THIS_GROUP FROM SESSION.FUNNEL INNER JOIN SESSION.WCNT USING(BXUPCR) WHERE (W1) IS NOT NULL GROUP BY BXUPCR, W1, UPC_COUNT HAVING UPC_COUNT = COUNT(*) ) WITH DATA WITH REPLACE @ --SELECT * FROM SESSION.GRP1 ORDER BY 1 @ --GROUPS OF (2) WORDS: DECLARE GLOBAL TEMPORARY TABLE SESSION.GRP2 AS ( SELECT BXUPCR, W1, W2, UPC_COUNT, COUNT(*) AS UPC_GROUP_COUNT, 2 AS THIS_GROUP FROM SESSION.FUNNEL INNER JOIN SESSION.WCNT USING(BXUPCR) WHERE (W1 || W2) IS NOT NULL GROUP BY BXUPCR, W1, W2, UPC_COUNT HAVING UPC_COUNT = COUNT(*) ) WITH DATA WITH REPLACE @ --SELECT * FROM SESSION.GRP2 ORDER BY 1 @ --GROUPS OF (3) WORDS: DECLARE GLOBAL TEMPORARY TABLE SESSION.GRP3 AS ( SELECT BXUPCR, W1, W2, W3, UPC_COUNT, COUNT(*) AS UPC_GROUP_COUNT, 3 AS THIS_GROUP FROM SESSION.FUNNEL INNER JOIN SESSION.WCNT USING(BXUPCR) WHERE (W1 || W2 || W3) IS NOT NULL GROUP BY BXUPCR, W1, W2, W3, UPC_COUNT HAVING UPC_COUNT = COUNT(*) ) WITH DATA WITH REPLACE @ --SELECT * FROM SESSION.GRP3 ORDER BY 1 @ --GROUPS OF (4) WORDS: DECLARE GLOBAL TEMPORARY TABLE SESSION.GRP4 AS ( SELECT BXUPCR, W1, W2, W3, W4, UPC_COUNT, COUNT(*) AS UPC_GROUP_COUNT, 4 AS THIS_GROUP FROM SESSION.FUNNEL INNER JOIN SESSION.WCNT USING(BXUPCR) WHERE (W1 || W2 || W3 || W4) IS NOT NULL GROUP BY BXUPCR, W1, W2, W3, W4, UPC_COUNT HAVING UPC_COUNT = COUNT(*) ) WITH DATA WITH REPLACE @ --SELECT * FROM SESSION.GRP4 ORDER BY 1 @ --GROUPS OF (5) WORDS: DECLARE GLOBAL TEMPORARY TABLE SESSION.GRP5 AS ( SELECT BXUPCR, W1, W2, W3, W4, W5, UPC_COUNT, COUNT(*) AS UPC_GROUP_COUNT, 5 AS THIS_GROUP FROM SESSION.FUNNEL INNER JOIN SESSION.WCNT USING(BXUPCR) WHERE (W1 || W2 || W3 || W4 || W5) IS NOT NULL GROUP BY BXUPCR, W1, W2, W3, W4, W5, UPC_COUNT HAVING UPC_COUNT = COUNT(*) ) WITH DATA WITH REPLACE @ --SELECT * FROM SESSION.GRP5 ORDER BY 1 @ --GROUPS OF (6) WORDS: DECLARE GLOBAL TEMPORARY TABLE SESSION.GRP6 AS ( SELECT BXUPCR, W1, W2, W3, W4, W5, W6, UPC_COUNT, COUNT(*) AS UPC_GROUP_COUNT, 6 AS THIS_GROUP FROM SESSION.FUNNEL INNER JOIN SESSION.WCNT USING(BXUPCR) WHERE (W1 || W2 || W3 || W4 || W5 || W6) IS NOT NULL GROUP BY BXUPCR, W1, W2, W3, W4, W5, W6, UPC_COUNT HAVING UPC_COUNT = COUNT(*) ) WITH DATA WITH REPLACE @ --SELECT * FROM SESSION.GRP6 ORDER BY 1 @ --GROUPS OF (7) WORDS: DECLARE GLOBAL TEMPORARY TABLE SESSION.GRP7 AS ( SELECT BXUPCR, W1, W2, W3, W4, W5, W6, W7, UPC_COUNT, COUNT(*) AS UPC_GROUP_COUNT, 7 AS THIS_GROUP FROM SESSION.FUNNEL INNER JOIN SESSION.WCNT USING(BXUPCR) WHERE (W1 || W2 || W3 || W4 || W5 || W6 || W7) IS NOT NULL GROUP BY BXUPCR, W1, W2, W3, W4, W5, W6, W7, UPC_COUNT HAVING UPC_COUNT = COUNT(*) ) WITH DATA WITH REPLACE @ --SELECT * FROM SESSION.GRP7 ORDER BY 1 @ --GROUPS OF (8) WORDS: DECLARE GLOBAL TEMPORARY TABLE SESSION.GRP8 AS ( SELECT BXUPCR, W1, W2, W3, W4, W5, W6, W7, W8, UPC_COUNT, COUNT(*) AS UPC_GROUP_COUNT, 8 AS THIS_GROUP FROM SESSION.FUNNEL INNER JOIN SESSION.WCNT USING(BXUPCR) WHERE (W1 || W2 || W3 || W4 || W5 || W6 || W7 || W8) IS NOT NULL GROUP BY BXUPCR, W1, W2, W3, W4, W5, W6, W7, W8, UPC_COUNT HAVING UPC_COUNT = COUNT(*) ) WITH DATA WITH REPLACE @ --SELECT * FROM SESSION.GRP8 ORDER BY 1 @ --GROUPS OF (9) WORDS: DECLARE GLOBAL TEMPORARY TABLE SESSION.GRP9 AS ( SELECT BXUPCR, W1, W2, W3, W4, W5, W6, W7, W8, W9, UPC_COUNT, COUNT(*) AS UPC_GROUP_COUNT, 9 AS THIS_GROUP FROM SESSION.FUNNEL INNER JOIN SESSION.WCNT USING(BXUPCR) WHERE (W1 || W2 || W3 || W4 || W5 || W6 || W7 || W8 || W9) IS NOT NULL GROUP BY BXUPCR, W1, W2, W3, W4, W5, W6, W7, W8, W9, UPC_COUNT HAVING UPC_COUNT = COUNT(*) ) WITH DATA WITH REPLACE @ --SELECT * FROM SESSION.GRP9 ORDER BY 1 @ --MERGE EVERYTHING TOGETHER: DECLARE GLOBAL TEMPORARY TABLE SESSION.UNIONX AS ( SELECT BXUPCR, W1 AS W1, '' AS W2, '' AS W3, '' AS W4, '' AS W5, '' AS W6, '' AS W7, '' AS W8, '' AS W9, 1 AS WC FROM SESSION.GRP1 UNION SELECT BXUPCR, W1 AS W1, W2 AS W2, '' AS W3, '' AS W4, '' AS W5, '' AS W6, '' AS W7, '' AS W8, '' AS W9, 2 AS WC FROM SESSION.GRP2 UNION SELECT BXUPCR, W1 AS W1, W2 AS W2, W3 AS W3, '' AS W4, '' AS W5, '' AS W6, '' AS W7, '' AS W8, '' AS W9, 3 AS WC FROM SESSION.GRP3 UNION SELECT BXUPCR, W1 AS W1, W2 AS W2, W3 AS W3, W4 AS W4, '' AS W5, '' AS W6, '' AS W7, '' AS W8, '' AS W9, 4 AS WC FROM SESSION.GRP4 UNION SELECT BXUPCR, W1 AS W1, W2 AS W2, W3 AS W3, W4 AS W4, W5 AS W5, '' AS W6, '' AS W7, '' AS W8, '' AS W9, 5 AS WC FROM SESSION.GRP5 UNION SELECT BXUPCR, W1 AS W1, W2 AS W2, W3 AS W3, W4 AS W4, W5 AS W5, W6 AS W6, '' AS W7, '' AS W8, '' AS W9, 6 AS WC FROM SESSION.GRP6 UNION SELECT BXUPCR, W1 AS W1, W2 AS W2, W3 AS W3, W4 AS W4, W5 AS W5, W6 AS W6, W7 AS W7, '' AS W8, '' AS W9, 7 AS WC FROM SESSION.GRP7 UNION SELECT BXUPCR, W1 AS W1, W2 AS W2, W3 AS W3, W4 AS W4, W5 AS W5, W6 AS W6, W7 AS W7, W8 AS W8, '' AS W9, 8 AS WC FROM SESSION.GRP8 UNION SELECT BXUPCR, W1 AS W1, W2 AS W2, W3 AS W3, W4 AS W4, W5 AS W5, W6 AS W6, W7 AS W7, W8 AS W8, W9 AS W9, 9 AS WC FROM SESSION.GRP9 GROUP BY BXUPCR, W1, W2, W3, W4, W5, W6, W7, W8, W9 ) WITH DATA WITH REPLACE @ --SELECT * FROM SESSION.UNIONX ORDER BY BXUPCR,W1,W2,W3,W4,W5,W6,W7,W8,W9 @ --FINAL RESULT: DECLARE GLOBAL TEMPORARY TABLE SESSION.PICKER AS ( SELECT BXUPCR, TRIM(W1 || ' ' || W2 || ' ' || W3 || ' ' || W4 || ' ' || W5 || ' ' || W6 || ' ' || W7 || ' ' || W8 || ' ' || W9) AS WORDS FROM SESSION.UNIONX INNER JOIN TABLE( SELECT BXUPCR, MAX(WC) AS WC FROM SESSION.UNIONX GROUP BY BXUPCR ) AS TMP USING(BXUPCR, WC) ) WITH DATA WITH REPLACE @ SELECT * FROM SESSION.PICKER ORDER BY 1 @ 下显示:

  

如果声明了临时表,或者是依赖的索引或视图   在声明的临时表上已经存在相同名称的   错误返回。

所以我想问:是否可以创建DGTT或任何其他类型的临时表,使其作用域仅限于该函数的当前实例。?

我可以使用DGTT的随机名称来解决问题,但这会使代码有些复杂。理想情况下,我只想使用一个名称。

我的另一种想法是在DGTT中有一组键列,这些键列由函数的输入参数填充。然后,该函数的所有实例都可以共享一个DGTT,但是只能访问它们自己的行。

有人有什么建议吗??

编辑:

好的,我已经连续进行了两天的工作,最后创建了一个有效的示例。 DGTT明显过量;这些最初是CTE,但我将它们全部转换以进行开发,以便在该过程的每个步骤之后都有一个结果窗口。

我的初衷是成为具有一个输入参数和一个输出的标量函数,我认为它可以非常令人满意地成为没有输入参数的表函数。

我最终得到的结果非常有效,并且比前几次尝试都快得多。实际上,我可以很容易地保持现状,但是我会将DGTT转换回CTE,以查看效率是否有变化。它可能我看不到任何变化,在这种情况下,将不会有DGTT,这将使我的整个操作无关紧要,大声笑。

话虽如此,正如任何人所看到的,创建循环有很多机会,这些循环将大大减少重复代码的数量和要处理的代码的数量,并且还将支持任意数量的单词... < / p>

import Toasted from 'vue-toasted'
import Vue from 'vue'

Vue.use(Toasted)

// Lets Register a Global Error Notification Toast.

// options to the toast
let errorOptions = {
  type: 'error',

  duration: 5000,
  position: 'top-center'
}

let successOptions = {
  type: 'success',

  duration: 5000,
  position: 'top-center'
}

// register the toast with the custom message
Vue.toasted.register('echarge_error',
  (payload) => {
    console.log('registrata')
    // if there is no message passed show default message
    if (!payload.message) {
      return 'Oops.. Something Went Wrong..'
    }

    // if there is a message show it with the message
    return payload.message
  },
  errorOptions
)

// register the toast with the custom message
Vue.toasted.register('echarge_success',
  (payload) => {
    // if there is no message passed show default message
    if (!payload.message) {
      return 'Oops.. Something Went Wrong..'
    }

    // if there is a message show it with the message
    return payload.message
  },
  successOptions
)

2 个答案:

答案 0 :(得分:0)

在QTEMP中实现了用Declare global temporary table创建的临时表,该临时表对于每个作业而不是每个线程都是唯一的。就是说,IBM i在后台执行缓存,并且它可能比您以前做的要好得多,因此,缓存数据的尝试通常只是浪费了周期,而内存缓存了已经缓存的事情。我建议尝试在不进行手动缓存的情况下执行过程,然后,如果需要在某个地方提高性能,请从索引开始。

SQL是一种声明性语言,而不是一种过程性语言。这意味着做事的最佳方法是只告诉您想要的结果,然后让优化器决定如何获得它。集合思考而不是程序思考。

答案 1 :(得分:0)

  

我想问:DGTT或任何其他类型的临时表可以   被创建,因此其范围仅限于当前的实例   功能..?

否。

  

如果声明了临时表,或者是依赖的索引或视图   在声明的临时表上已经存在相同名称的   错误返回。

您可以使用WITH REPLACE子句避免此类错误。在这种情况下,对应的DGTT会被静默删除并重新创建。
因此,如果不需要DGTT的旧内容,只需在DGTT声明中使用此子句即可。