空值加载到光标?

Posted

技术标签:

【中文标题】空值加载到光标?【英文标题】:Null values loaded into Cursor? 【发布时间】:2013-08-27 13:30:32 【问题描述】:

所以我创建了几个游标来存储正在加载到表中的数据。数据一次加载一个,我需要对整个数据集进行验证,而不仅仅是单个记录。所以会有这样的数据(但它只会单独加载,而不是整体加载)

form_no  |  type
---------------
5155-55  |  -1
5155-55  |  -1
5155-55  |   2
5155-55  |   1
         |
4568-98  |  -1
4568-98  |  -1
4568-98  |  -1
4568-98  |   2
4568-98  |   1   

3302-48  |  1
3302-45  |  2 
3302-45  | -1

因此,游标会获取总和或每种类型,然后将其与不同的 form_no 配对。然后在底部检查以确保每个 form_no 总是有一个 1 和 -1(即 form_no 5155-55 至少有一个类型 1 和一个类型 -1)

DECLARE
 error VARCHAR2(1) := 'N';

CURSOR XXX IS
SELECT form_no, sum(type) as sum_type_neg
  FROM my_table
 WHERE type = -1
 GROUP BY form_no;

CURSOR YYY IS
SELECT form_no, sum(type) as sum_type_pos
  FROM my_table
 WHERE type = 1
 GROUP BY form_no;

CURSOR ZZZ(xx_form_no VARCHAR2, yy_form_no VARCHAR2) IS
SELECT form_no
  FROM my_table
 WHERE form_no = xx_form_no
   AND form_no = vv_form_no
 GROUP BY form_no;

x_form  XXX%ROWTYPE;
y_form  YYY%ROWTYPE;
ZZZRow  ZZZ%ROWTYPE;

BEGIN
OPEN XXX;
LOOP
  FETCH XXX
    INTO x_form;
  EXIT WHEN XXX%NOTFOUND;

  OPEN YYY;
  LOOP
    FETCH YYY
      INTO y_form;
    EXIT WHEN YYY%NOTFOUND;

    OPEN ZZZ(x_form.form_no, y_form.form_no);
    LOOP
      FETCH ZZZ
        INTO ZZZRow;
      EXIT WHEN ZZZ%NOTFOUND;
      dbms_output.put_line('Distinct: ' || x_form.form_no);
      dbms_output.put_line('SUM x:    ' || x_form.sum_type_neg);
      dbms_output.put_line('SUM y:    ' || y_form.sum_type_pos);
      dbms_output.put_line('----------------------------');
    END LOOP;
    CLOSE ZZZ;
  END LOOP;
  CLOSE YYY;
END LOOP;
CLOSE XXX;

IF x_form.sum_type_neg = O or y_form.sum_type_pos = 0 THEN
  v_error_in_process := 'Y';
  dbms_output.put_line('ERROR MESSAGE');
ELSE
  dbms_output.put_line('GREATE JOB');
END IF;

END;

输出会是这样的

 Distinct : 5155-55
 SUM x:    -2
 SUM y:     1
 ----------------------------
 Distinct: 4568-98
 SUM x:    -3
 SUM y:     1
 ----------------------------
 Distinct: 3302-48
 SUM x:    -1
 SUM y:     1
 ----------------------------
 GREAT JOB!

效果很好,除非 form_no 没有 -1 或 1 示例输入:

form_no  |  type
---------------
5155-55  |  -1
5155-55  |  -1
5155-55  |   2
5155-55  |   1
         |
4568-98  |  -1
4568-98  |  -1
4568-98  |  -1
4568-98  |   2
4568-98  |   1 

3302-48  |   1
3302-48  |   2

请注意,form_no 3302-48 没有 -1。那么输出会是这样的

 Distinct: 5155-55
 SUM x:    -2
 SUM y:     1
 ----------------------------
 Distinct: 4568-98
 SUM x:    -3
 SUM y:     1
 ----------------------------
 GREAT JOB!

除了我希望它是这样的

 Distinct: 5155-55
 SUM x:    -2
 SUM y:     1
 ----------------------------
 Distinct: 4568-98
 SUM x:    -3
 SUM y:     1
 ----------------------------
 Distinct: 3302-48
 SUM x:     0
 SUM y:     1
 ----------------------------
 ERROR MESSAGE

谁能告诉我该怎么做。我不确定游标是否可以接受空值(即,当没有 1 或 -1 时,游标中不会加载任何内容)。

【问题讨论】:

【参考方案1】:

真的不需要PL/SQL的处理,只用SQL就可以达到预期的效果:

SQL> select col
  2       , val
  3    from ( select form_no as "Distinct:"
  4                , to_char(sum(case when type1 = -1 then type1 else 0 end)) as sumx
  5                , to_char(sum(case when type1 = 1  then type1 else 0 end)) as sumy
  6            from t1
  7           group by form_no
  8         )
  9  unpivot(
 10     val for col in ("Distinct:", sumx, sumy)
 11   )
 12  ;

结果:

COL       VAL
--------- ----------
Distinct: 5155-55
SUMX      -2
SUMY      1

Distinct: 4568-98
SUMX      -3
SUMY      1

Distinct: 3302-48
SUMX      0
SUMY      1

9 rows selected 

注意。 Unpivot 运算符在Oracle 11g 版本中已经引入,在上述查询中仅用于数据格式化。如果您的 Oracle 版本早于 11g,您可以使用 PL/SQL 进行子查询(内联视图)并根据需要格式化输出。

SQLFiddle Demo

【讨论】:

以上是关于空值加载到光标?的主要内容,如果未能解决你的问题,请参考以下文章

设定默认值,光标落在上面就使该值变成空值

BigQuery - 加载具有空值的 JSON 字段

CSV 到 BQ:空字段而不是空值

与空值合并

Typhead 空值应重置另一个选择对象的选项

如何在 oracle 中使用空值检查 last_modified 日期