【问题标题】:Strange code behavior when runned in a stored procedure, but work fine when taken outside it在存储过程中运行时出现奇怪的代码行为,但在存储过程之外运行良好
【发布时间】:2018-05-20 14:27:05
【问题描述】:

查看演示here

存储过程返回:

|-------------|------------|
|   test_set  |  is_sovlp  |
|-------------|------------|
|   1         |  1         |
|   2         |  1         |
|-------------|------------|

虽然预期的结果是:

|-------------|------------|
|   test_set  |  is_sovlp  |
|-------------|------------|
|   1         |  0         |
|   2         |  1         |
|-------------|------------|

令人惊讶的是,在存储过程之外,返回的值是正确的。

但在存储过程中,它们不是。

有人知道吗?

注意:更多信息here

代码:

create or replace PROCEDURE IS_OVLP AS

is_sovlp VARCHAR2(1);
test_set NUMBER := 1;

BEGIN

    DBMS_UTILITY.EXEC_DDL_STATEMENT('TRUNCATE TABLE TEMP_OUTPUT_OVLP');

    --------------------------------------
    -- Populate TEMP_OUT_OVLP
    --------------------------------------

    INSERT INTO TEMP_OUTPUT_OVLP 
    SELECT ESD, 
           'E', 
           TEST_SET
    FROM   TEMP_INPUT_OVLP 
    WHERE  ESD IS NOT NULL 
    AND TEST_SET = test_set
    UNION ALL 
    SELECT TD, 
           CASE IS_DB 
             WHEN 0 THEN 'S' 
             WHEN 1 THEN 'H' 
           END AS FLAG,
           TEST_SET
    FROM   TEMP_INPUT_OVLP 
    WHERE  TD IS NOT NULL AND TEST_SET = test_set;

    -------------------------------------------------------------
    -- Lookup for pattern like HH|EE|HS|SE
    -- in aggregated result.
    -- Example: 
    -- EHESSHES   => 0
    -- EHEEESHEHH => 1
    -------------------------------------------------------------
    SELECT COUNT(*) into is_sovlp
    FROM (SELECT listagg(FLAG) WITHIN GROUP (ORDER BY DT) as flags
          FROM TEMP_OUTPUT_OVLP
          WHERE TEST_SET = test_set
         ) x
    WHERE regexp_like(flags, 'HH|EE|HS|SE');

    dbms_output.put_line('Soft Overlap: ' || is_sovlp);

END IS_OVLP;

输入数据:

|----------|----------|----------|----------|----------|
|    ID    |   ESD    |  TD      |   IS_DB  | TEST_SET |
|----------|----------|----------|----------|----------|
|    1     |   10     |  20      |   1      |  1       |
|    2     |   30     |  (null)  |   0      |  1       |
|    3     |   (null) |  40      |   0      |  1       |
|    4     |   (null) |  50      |   0      |  1       |
|    5     |   (null) |  60      |   1      |  1       |
|    6     |   70     |  (null)  |   0      |  1       |
|    7     |   (null) |  100     |   0      |  1       |
|    8     |   10     |  20      |   1      |  2       |
|    9     |   30     |  (null)  |   0      |  2       |
|    10    |   40     |  (null)  |   0      |  2       |
|    11    |   50     |  60      |   0      |  2       |
|    12    |   (null) |  70      |   1      |  2       |
|    13    |   75     |  100     |   1      |  2       |
|    14    |   (null) |  80      |   1      |  2       |
|----------|----------|----------|----------|----------|

【问题讨论】:

  • TEST_SET = test_set 对于test_set 不为空的每一行都为真。我的猜测是您使用了“在存储过程之外”TEST_SET = 1
  • 没错,解决了我的问题!所以将 var 声明替换为v_test_set NUMBER := 2; 而不是test_set NUMBER := 2;。我不擅长 SQL,认为 SQL 将能够区分两者。再次感谢!

标签: sql plsql oracle11g


【解决方案1】:

假设TEMP_INPUT_OVLP 中的每一行都有一个TEST_SET 的值,并且PL/SQL 标识符不区分大小写,那么谓词

TEST_SET = test_set

对于每一行都是正确的。可能当您自己测试 SQL 时,您使用了类似的东西

TEST_SET = 1

尝试将其更改为:

TEST_SET = is_ovlp.test_set

否则重命名局部变量。通常的做法是为局部变量使用命名约定,例如 l_ 前缀,例如l_test_set.

【讨论】:

    猜你喜欢
    • 2020-05-17
    • 2020-08-26
    • 1970-01-01
    • 1970-01-01
    • 2015-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多