在PL / SQL中的同一个包中编写许多查询是一个好习惯,如果没有,有没有一个好方法呢?

时间:2018-03-17 18:56:27

标签: sql oracle plsql

我正在编写一个PL / SQL包来填充表,它将根据公式计算几个指标(从不同的表中查询),但我最终得到的包中充满了来自不同表的select语句。 有没有其他方法可以将所有这些查询聚合在一起而不会使代码过于复杂(我喜欢简单)。

请建议。

- 陷入困境的开发者

1 个答案:

答案 0 :(得分:0)

使用游标。例如,您可能想要一个接一个地编写一堆语句,例如:

DECLARE
  nCurrent_balance    CUSTOMER_RUNNING_BALANCE.CURRENT_BALANCE%TYPE;
  nTotal_credit_line  CUSTOMER_CREDIT_LINE.TOTAL_CREDIT_LINE%TYPE;
  nAvailable_credit   CUSTOMER_CREDIT_LINE.AVAILABLE_CREDIT%TYPE;
  strLocation_name    CUSTOMER_ADDRESS.LOCATION_NAME%TYPE;
  strStreet_address_1 CUSTOMER_ADDRESS.STREET_ADDRESS_1%TYPE;
  strCity             CUSTOMER_ADDRESS.CITY%TYPE;
  strState            CUSTOMER_ADDRESS.CITY%TYPE;
  strZip              CUSTOMER_ADDRESS.CITY%TYPE;
BEGIN
  FOR aRow IN (SELECT CUSTOMER_ID FROM CUSTOMER)
  LOOP
    BEGIN
      SELECT CURRENT_BALANCE
        INTO nCurrent_balance
        FROM CUSTOMER_RUNNING_BALANCE rb
        WHERE rb.CUSTOMER_ID = aRow.CUSTOMER_ID;
    EXCEPTION
      WHEN NO_DATA_FOUND THEN
        nCurrent_balance := NULL;
    END;

    BEGIN
      SELECT TOTAL_CREDIT_LINE, AVAILABLE_CREDIT
        INTO nTotal_credit_Line, nAvailable_credit
        FROM CUSTOMER_CREDIT_LINE cl
        WHERE cl.CUSTOMER_ID = aRow.CUSTOMER_ID;
    EXCEPTION
      WHEN NO_DATA_FOUND THEN
        nTotal_credit_line := NULL;
        nAvailable_credit := NULL;
    END;

    BEGIN
      SELECT LOCATION_NAME,
             STREET_ADDRESS_1,
             CITY,
             STATE,
             ZIP
        INTO strLocation_name,
             strStreet_address_1,
             strCity,
             strState,
             strZip
        FROM CUSTOMER_ADDRESS ca
        WHERE ca.CUSTOMER_ID = aRow.CUSTOMER_ID AND
              ca.ADDRESS_TYPE = 'HEADQUARTERS';
    EXCEPTION
      WHEN NO_DATA_FOUND THEN
        strLocation_name := NULL;
        strStreet_address_1 := NULL;
        strCity := NULL;
        strState := NULL;
        strZip := NULL;
    END;

    // Do something useful with the data here
  END LOOP;
END;

伊克。这里我们有一个游标和一堆单独的SELECT语句,将来自三个额外源的数据拉入单独声明的变量中。这里有很多代码行,但大部分代码都没用 - 除了由于编写方式所有这些都是必需的 - AND 这是一个巨大的,明显的,可能致命的编码错误在这个,虽然代码可能运行得很好 - 你能发现吗? : - )

使用游标将表连接在一起会大大减少代码量,消除对所有这些异常处理程序的需要,并且完全消除了产生上述错误的机会:

BEGIN
  FOR aRow IN (SELECT c.CUSTOMER_ID,
                      rb.CURRENT_BALANCE,
                      cl.TOTAL_CREDIT_LINE,
                      cl.AVAILABLE_CREDIT,
                      ca.LOCATION_NAME,
                      ca.STREET_ADDRESS_1,
                      ca.CITY,
                      ca.STATE,
                      ca.ZIP
                 FROM CUSTOMER c
                 LEFT OUTER JOIN CUSTOMER_RUNNING_BALANCE rb
                   ON rb.CUSTOMER_ID = c.CUSTOMER_ID
                 LEFT OUTER JOIN CUSTOMER_CREDIT_LINE cl
                   ON cl.CUSTOMER_ID = c.CUSTOMER_ID
                 LEFT OUTER JOIN CUSTOMER_ADDRESS ca
                   ON ca.CUSTOMER_ID = c.CUSTOMER_ID AND
                      ca.ADDRESS_TYPE = 'HEADQUARTERS')
  LOOP
    // Do something useful with the data here
  END LOOP;
END;

所以 - 第一个例子中的59行代码,而第二个代码中的代码是22行。在第二个例子中,光标清楚地说明了表之间的关系。第一个例子中的错误(我写的时候实际上做的经典剪切和粘贴错误:-)在第二个例子中是不可能的。

构建关系数据库以快速有效地处理第二个示例中的游标等查询。通过使用查询,您可以减少

的次数