Oracle 更新日数列';使用动态更新查询的分类账统计表中的值

Oracle 更新日数列';使用动态更新查询的分类账统计表中的值,oracle,plsql,toad,Oracle,Plsql,Toad,我有一个表LEDGER\u STAT\u,其中有一个月内每天的列(day\u 01表示第1天,day\u 02,…..,day\u 31)。目前,我正在使用case语句更新Day列的值,如下所示 CASE DAY(V_DATE) WHEN 1 THEN UPDATE /*+ index(a LEDGER_STAT_DLY_IDX02_IN) */ LEDGER_STAT_DLY A SET

我有一个表
LEDGER\u STAT\u
,其中有一个月内每天的列(
day\u 01
表示第1天,
day\u 02
,…..,day\u 31)。目前,我正在使用case语句更新
Day
列的值,如下所示


CASE DAY(V_DATE)
                WHEN 1 THEN
                UPDATE /*+ index(a LEDGER_STAT_DLY_IDX02_IN) */ LEDGER_STAT_DLY A
                    SET DAY_01 =  NVL(DAY_01,0) + NVL(V_AMOUNT,0)
                    WHERE IDENTITY_CODE =  NVL(V_IDENTITY_CODE,0)
                            AND YEAR_S =  NVL(V_YEAR_S,0)
                            AND MONTH_NO = NVL(V_MONTH,0)
                            AND CONSOLIDATION_CD =  NVL(V_CONSOLIDATION_CD,0)
                            AND FINANCIAL_ELEM_ID = NVL(V_FINANCIAL_ELEM_ID,0)
                            AND ORG_UNIT_ID   = NVL(V_ORG_UNIT_ID,0)
                            AND GL_ACCOUNT_ID = NVL(V_GL_ACCOUNT_ID,0)
                            AND COMMON_COA_ID = NVL(V_COMMON_COA_ID,0)
                            AND PRODUCT_1_ID  = NVL(V_PRODUCT_1_ID,0)
                            AND PRODUCT_ID    = NVL(V_PRODUCT_ID,0)
                            AND PRODUCT_3_ID  = NVL(V_PRODUCT_3_ID,0)
                            AND COST_TYPE_ID    = NVL(V_MEMO_GL_ACCOUNT_ID,0)
                            AND BALANCE_TYPE_CD = NVL(V_BALANCE_TYPE_CD,0);

                WHEN 2 THEN
                UPDATE /*+ index(a LEDGER_STAT_DLY_IDX02_IN) */ LEDGER_STAT_DLY A
                    SET DAY_02 =  NVL(DAY_02,0) + NVL(V_AMOUNT,0)
                    WHERE IDENTITY_CODE =  NVL(V_IDENTITY_CODE,0)
                            AND YEAR_S =  NVL(V_YEAR_S,0)
                            AND MONTH_NO = NVL(V_MONTH,0)
                            AND CONSOLIDATION_CD =  NVL(V_CONSOLIDATION_CD,0)
                            AND FINANCIAL_ELEM_ID = NVL(V_FINANCIAL_ELEM_ID,0)
                            AND ORG_UNIT_ID   = NVL(V_ORG_UNIT_ID,0)
                            AND GL_ACCOUNT_ID = NVL(V_GL_ACCOUNT_ID,0)
                            AND COMMON_COA_ID = NVL(V_COMMON_COA_ID,0)
                            AND PRODUCT_1_ID  = NVL(V_PRODUCT_1_ID,0)
                            AND PRODUCT_ID    = NVL(V_PRODUCT_ID,0)
                            AND PRODUCT_3_ID  = NVL(V_PRODUCT_3_ID,0)
                            AND COST_TYPE_ID    = NVL(V_MEMO_GL_ACCOUNT_ID,0)
                            AND BALANCE_TYPE_CD = NVL(V_BALANCE_TYPE_CD,0);

-- and so forth, I have written 31 blocks
虽然工作正常,但过程中的代码非常长。您能建议我如何使用动态查询来更新它,这样代码就减少到更少的行/单个块,而不是31个单独的case语句。 提前感谢您的帮助


PS:正在使用
day()
函数从
V_DATE
提取日期。逻辑是,无论何时
day(v_date)
匹配
day_number(01,02,03…
分类账统计表的
列,都会相应地更新该列的值。

很抱歉,但最好的办法是规范化该表,去掉重复的
day_01
day_02
等字段。这将使你的工作简单得多

显然你的桌子现在看起来像

CREATE TABLE LEDGER_STAT_DLY 
  (IDENTITY_CODE      NUMBER,
   YEAR_S             NUMBER,
   MONTH_NO           NUMBER,
   CONSOLIDATION_CD   NUMBER,
   FINANCIAL_ELEM_ID  NUMBER,
   ORG_UNIT_ID        NUMBER,
   GL_ACCOUNT_ID      NUMBER,
   COMMON_COA_ID      NUMBER,
   PRODUCT_ID         NUMBER,
   PRODUCT_1_ID       NUMBER,
   PRODUCT_3_ID       NUMBER,
   COST_TYPE_ID       NUMBER,
   BALANCE_TYPE_CD    NUMBER,
   DAY_01             NUMBER,
   DAY_02             NUMBER,
   ...
   DAY_31             NUMBER);
我建议用

CREATE TABLE LEDGER_STAT_DLY 
  (IDENTITY_CODE      NUMBER,
   YEAR_S             NUMBER,
   MONTH_NO           NUMBER,
   CONSOLIDATION_CD   NUMBER,
   FINANCIAL_ELEM_ID  NUMBER,
   ORG_UNIT_ID        NUMBER,
   GL_ACCOUNT_ID      NUMBER,
   COMMON_COA_ID      NUMBER,
   PRODUCT_ID         NUMBER,
   PRODUCT_1_ID       NUMBER,
   PRODUCT_3_ID       NUMBER,
   COST_TYPE_ID       NUMBER,
   BALANCE_TYPE_CD    NUMBER,
   DAY_NUMBER         NUMBER,
   DAY_VALUE          NUMBER);

DAY\u NUMBER
成为当月的天数,因此其值为1-31<代码>日值
被分配用于进入日01、日02的值,等等。如果你想一想你正在写重复代码块来处理所有单独的DAY_xx字段的所有地方,你就会意识到这种规范化结构将更容易处理。

我同意Bob Jarvis在回答中表达的观点,但是如果重构基础表不是你的选择,这可以通过动态SQL实现

在提供的示例中,似乎有一个变量(
DAY\u 01
/
DAY\u 02
/
DAY\u 03
..字段)需要在两个位置使用。因此,需要将此字段替换为静态语句的其余部分

CREATE OR REPLACE PROCEDURE UPDATE_LEDGER_STAT_DLY(V_IDENTITY_CODE NUMBER,
                                                   V_CONSOLIDATION_CD NUMBER,
                                                   V_FINANCIAL_ELEM_ID NUMBER,
                                                   V_ORG_UNIT_ID NUMBER,
                                                   V_GL_ACCOUNT_ID NUMBER,
                                                   V_COMMON_COA_ID NUMBER,
                                                   V_PRODUCT_1_ID NUMBER,
                                                   V_PRODUCT_ID NUMBER,
                                                   V_PRODUCT_3_ID NUMBER,
                                                   V_DATE DATE,
                                                   V_AMOUNT NUMBER,
                                                   V_MEMO_GL_ACCOUNT_ID NUMBER DEFAULT 0,
                                                   V_POSTINGTYPE CHAR DEFAULT 'N',
                                                   V_BALANCE_TYPE_CD NUMBER DEFAULT 0)
    IS

    V_CNT    NUMBER;
    V_D      NUMBER;
    V_DAY    CHAR(6);
    V_MONTH  CHAR(2);
    V_MO     NUMBER;
    V_YEAR_S NUMBER;

BEGIN

    IF V_POSTINGTYPE = 'N' THEN

        IF NVL(V_AMOUNT, 0) <> 0 THEN

            V_MO := (MONTH(V_DATE));
            V_MONTH := LPAD(V_MO, 2, '0');
            V_YEAR_S := (YEAR(V_DATE));
            V_D := (DAY(V_DATE));
            V_DAY := 'DAY_' || lpad(V_D, 2, '0');


            EXECUTE IMMEDIATE UTL_LMS.FORMAT_MESSAGE('UPDATE /*+ index(a LEDGER_STAT_DLY_IDX02_IN) */ LEDGER_STAT_DLY A
                           SET %s =  NVL(%s,0) + NVL(:THE_AMOUNT,0)
                           WHERE IDENTITY_CODE =  NVL(:THE_IDENTITY_CODE,0)
                              AND YEAR_S =  NVL(:THE_YEAR_S,0)
                              AND MONTH_NO = NVL(:THE_MONTH,0)
                              AND CONSOLIDATION_CD =  NVL(:THE_CONSOLIDATION_CD,0)
                              AND FINANCIAL_ELEM_ID = NVL(:THE_FINANCIAL_ELEM_ID,0)
                              AND ORG_UNIT_ID   = NVL(:ORG_UNIT_ID,0)
                              AND GL_ACCOUNT_ID = NVL(:THE_GL_ACCOUNT_ID,0)
                              AND COMMON_COA_ID = NVL(:THE_COMMON_COA_ID,0)
                              AND PRODUCT_1_ID  = NVL(:THE_PRODUCT_1_ID,0)
                              AND PRODUCT_ID    = NVL(:THE_PRODUCT_ID,0)
                              AND PRODUCT_3_ID  = NVL(:THE_PRODUCT_3_ID,0)
                              AND COST_TYPE_ID    = NVL(:THE_MEMO_GL_ACCOUNT_ID,0)
                              AND BALANCE_TYPE_CD = NVL(:THE_BALANCE_TYPE_CD,0)', V_DAY, V_DAY)
                USING V_AMOUNT, V_IDENTITY_CODE, V_YEAR_S, V_MONTH, V_CONSOLIDATION_CD,
                V_FINANCIAL_ELEM_ID, V_ORG_UNIT_ID, V_GL_ACCOUNT_ID,
                V_COMMON_COA_ID, V_PRODUCT_1_ID, V_PRODUCT_ID, V_PRODUCT_3_ID, V_MEMO_GL_ACCOUNT_ID, V_BALANCE_TYPE_CD;

        END IF;

    END IF;

END;
/
下面是一个例子

首先,添加一个变量来保存目标字段名。(这其实不是必需的,只是为了可读性)

由于日数1、2、3和字段
日数01
日数02
日数03
之间的现有切换中存在有序转换,因此可通过直接分配确定

然后,在开关当前使用的过程体中,您可以使用
executeimmediate
,将语句中的列名替换为目标
DAY\u 01
DAY\u 02
等,其中列名位于语句中

CREATE OR REPLACE PROCEDURE UPDATE_LEDGER_STAT_DLY(V_IDENTITY_CODE NUMBER,
                                                   V_CONSOLIDATION_CD NUMBER,
                                                   V_FINANCIAL_ELEM_ID NUMBER,
                                                   V_ORG_UNIT_ID NUMBER,
                                                   V_GL_ACCOUNT_ID NUMBER,
                                                   V_COMMON_COA_ID NUMBER,
                                                   V_PRODUCT_1_ID NUMBER,
                                                   V_PRODUCT_ID NUMBER,
                                                   V_PRODUCT_3_ID NUMBER,
                                                   V_DATE DATE,
                                                   V_AMOUNT NUMBER,
                                                   V_MEMO_GL_ACCOUNT_ID NUMBER DEFAULT 0,
                                                   V_POSTINGTYPE CHAR DEFAULT 'N',
                                                   V_BALANCE_TYPE_CD NUMBER DEFAULT 0)
    IS

    V_CNT    NUMBER;
    V_D      NUMBER;
    V_DAY    CHAR(6);
    V_MONTH  CHAR(2);
    V_MO     NUMBER;
    V_YEAR_S NUMBER;

BEGIN

    IF V_POSTINGTYPE = 'N' THEN

        IF NVL(V_AMOUNT, 0) <> 0 THEN

            V_MO := (MONTH(V_DATE));
            V_MONTH := LPAD(V_MO, 2, '0');
            V_YEAR_S := (YEAR(V_DATE));
            V_D := (DAY(V_DATE));
            V_DAY := 'DAY_' || lpad(V_D, 2, '0');


            EXECUTE IMMEDIATE UTL_LMS.FORMAT_MESSAGE('UPDATE /*+ index(a LEDGER_STAT_DLY_IDX02_IN) */ LEDGER_STAT_DLY A
                           SET %s =  NVL(%s,0) + NVL(:THE_AMOUNT,0)
                           WHERE IDENTITY_CODE =  NVL(:THE_IDENTITY_CODE,0)
                              AND YEAR_S =  NVL(:THE_YEAR_S,0)
                              AND MONTH_NO = NVL(:THE_MONTH,0)
                              AND CONSOLIDATION_CD =  NVL(:THE_CONSOLIDATION_CD,0)
                              AND FINANCIAL_ELEM_ID = NVL(:THE_FINANCIAL_ELEM_ID,0)
                              AND ORG_UNIT_ID   = NVL(:ORG_UNIT_ID,0)
                              AND GL_ACCOUNT_ID = NVL(:THE_GL_ACCOUNT_ID,0)
                              AND COMMON_COA_ID = NVL(:THE_COMMON_COA_ID,0)
                              AND PRODUCT_1_ID  = NVL(:THE_PRODUCT_1_ID,0)
                              AND PRODUCT_ID    = NVL(:THE_PRODUCT_ID,0)
                              AND PRODUCT_3_ID  = NVL(:THE_PRODUCT_3_ID,0)
                              AND COST_TYPE_ID    = NVL(:THE_MEMO_GL_ACCOUNT_ID,0)
                              AND BALANCE_TYPE_CD = NVL(:THE_BALANCE_TYPE_CD,0)', V_DAY, V_DAY)
                USING V_AMOUNT, V_IDENTITY_CODE, V_YEAR_S, V_MONTH, V_CONSOLIDATION_CD,
                V_FINANCIAL_ELEM_ID, V_ORG_UNIT_ID, V_GL_ACCOUNT_ID,
                V_COMMON_COA_ID, V_PRODUCT_1_ID, V_PRODUCT_ID, V_PRODUCT_3_ID, V_MEMO_GL_ACCOUNT_ID, V_BALANCE_TYPE_CD;

        END IF;

    END IF;

END;
/
创建或替换程序更新分类账统计(V\u标识码、,
V_合并_CD编号,
V_财务要素ID号,
V_组织单位ID号,
V_总账账户ID号,
V_公共_COA_ID编号,
V_产品1_标识号,
V_产品识别号,
V_产品3_标识号,
V_日期,
V_金额编号,
V_备忘录\u总账\u账户ID号默认为0,
V_POSTINGTYPE字符默认值为'N',
V_余额_类型_CD编号默认为0)
是
V_CNT数;
V_D数;
V_DAY CHAR(6);
V_月字符(2);
V_-MO数;
V_年份编号;
开始
如果V_POSTINGTYPE='N',则
如果NVL(V_金额,0)0,则
V_MO:=(月(V_日期));
V_月:=LPAD(V_月,2,'0');
V_年S:=(年(V_日期));
V_D:=(天(V_日期));
V_-DAY:='DAY|lpad(V_-D,2,'0');
立即执行UTL LMS.FORMAT消息('UPDATE/*+索引(分类账统计数据中的IDX02)*/LEDGER统计数据中的a)
设置%s=NVL(%s,0)+NVL(:金额,0)
其中IDENTITY\u CODE=NVL(:IDENTITY\u CODE,0)
年份=NVL(:年份,0)
月份号=NVL(:月份,0)
和合并\u CD=NVL(:合并\u CD,0)
和财务要素ID=NVL(:财务要素ID,0)
并且组织单元ID=NVL(:组织单元ID,0)
总账账户ID=NVL(:总账账户ID,0)
和COMMON_COA_ID=NVL(:THE_COMMON_COA_ID,0)
和产品\u 1\u ID=NVL(:产品\u 1\u ID,0)
产品标识=NVL(:产品标识,0)
产品3\u ID=NVL(:产品3\u ID,0)
成本类型标识=NVL(:备忘账户标识,0)
和余额类型CD=NVL(:余额类型CD,0),V天,V天)
使用V_金额、V_标识代码、V_年、V_月、V_合并CD、,
V_财务要素ID、V_组织单位ID、V_总账账户ID、,
V_普通_COA_ID、V_产品_1_ID、V_产品_ID、V_产品_3_ID、V_备忘_总账_账户_ID、V_余额_类型_CD;
如果结束;
如果结束;
结束;
/

我收到错误SQL命令未正确结束错误。如果有错误,请确认/发现。我也在测试它。谢谢@SachinSharma。这可能是动态语句中的一个尾随分号(示例中的剪切/粘贴错误)。它已在中删除