3

我对 PL/SQL 很陌生,我必须稍微使用它。我必须制作一些非常相似的功能。我为这个问题简化了它。

我有 2 个表(在本例中称为 TABLE1、TABLE2),其中包含一些数据。我必须修剪、验证数据并将其插入到其他表中。

表 1 -> 表 3 表 2 -> 表 4

TABLE1 有一些订单,而 TABLE2 每个订单有几个位置。正如我所说的那样,它被简化了,所以我没有发布异常或打开/关闭游标等内容。 Atm 它的工作原理是这样的,但我认为这种结构并不接近“最佳实践”,但我没有找到网络上任何涵盖此问题的 PL/SQL 代码,尽管它一定很常见。

我猜 COMMIT 可能在外循环的末尾,甚至可能在整个函数之后。

所以你能告诉我这样可以还是完全愚蠢,我应该/可以改变什么以及为什么。我不想习惯“糟糕”的编码风格,所以我想在我还是初学者的时候以正确的方式学习它。

这是简化的代码:

BEGIN
    SAVEPOINT SAVE_Stufe_5;
    LOOP
        SAVEPOINT SAVE_LOOP;
        FETCH CURSOR1 INTO RECORD1;
        EXIT WHEN CURSOR1%NOTFOUND OR CURSOR1%NOTFOUND IS NULL;
        vError  := 0;
        RECORD1 := CURSOR1;
        -- DATAVALIDATION (vError will be the Errorcode)
        IF (vError = 0) THEN
            retcode := InsertTABLE3(RECORD1);
            IF (retcode != DATABASE_OK) THEN
                ROLLBACK TO SAVE_LOOP;
            END IF;
        END IF;
        LOOP
            FETCH CURSOR2 INTO CURSOR2;
            EXIT WHEN CURSOR2%NOTFOUND OR CURSOR2%NOTFOUND IS NULL OR vError != 0 OR retcode != DATABASE_OK;
            RECORD2 := CURSOR2;
            -- DATAVALIDATION (vError will be the Errorcode)
            IF (vError = 0) THEN
                retcode := InsertTABLE4(RECORD2);
                IF (retcode = DATABASE_OK) THEN
                    UPDATE TABLE2
                    SET    TABLE2.Status = 20
                    WHERE  TABLE2.ID     = CURSOR2.ID;
                ELSE
                    ROLLBACK TO SAVE_LOOP;
                END IF;
            END IF;
        END LOOP;
        IF (vError = 0) THEN
            UPDATE TABLE1
            SET    TABLE1.Status = 20
            WHERE  TABLE1.ID     = CURSOR1.ID
        ELSE
            ROLLBACK TO SAVE_LOOP;
            UPDATE TABLE1
            SET    TABLE1.Status = vError
            WHERE  TABLE1.ID     = CURSOR1.ID

            UPDATE TABLE2
            SET    TABLE2.Status = vError
            WHERE  TABLE2.ID     = CURSOR2.ID
        END IF;
    END LOOP;
END;

小更新:

我设法进行了基于验证集的操作,尽管我真的不知道如何将我的数据放入另一个表中。我尝试了一个带有修剪的插入选择,但它只插入一行。如果我按照建议使用隐式游标,我仍然必须循环,我不会循环游标,但 SELECT INTO 就隐式游标只有一行。

我想我真的需要一个片段或一些链接来帮助我。这是我尝试的简化版本:

INSERT INTO TABLE3
(
  val1,
  val2,
  val3
)
SELECT TRIM(val1),
       TRIM(val2),
       TRIM(val3),
FROM   TABLE1
WHERE  STATUS = 10
AND    (TRIM(PK1) || TRIM(PK2)) NOT IN (SELECT (TABLE3.PK1 || TABLE3.PK2) FROM TABLE3);
4

1 回答 1

0

一般来说,通过循环在 SQL 中做事是不好的风格。与基于集合的解决方案相比,这样的循环将非常慢。除了所有这些循环之外,最好使用单个insertormerge语句将所有表 1 复制到表 3 中,或者如果您的验证很复杂并且需要一些中间步骤,则可能使用一些语句。

您想要执行的大多数类型的修剪和数据验证都可以这样处理。几乎从不需要嵌套循环。有例外,但很少见。那些刚接触 SQL 的人倾向于使用循环,因为这是我们从其他语言中知道的。不久前我属于那个类别。但要真正使用语言的力量,你必须超越它。

除了这一点之外,如果我们对表格或您正在执行的验证一无所知,则无法提供太多具体帮助。

何时应该commit还取决于您的特定设计以及您要完成的工作。

于 2012-12-13T13:36:28.103 回答