我正在为某些维度编写一些DDL / PLSQL,因此我可以将它作为备份方便使用,并且我使用过程/函数来自动执行所有操作。对于我的问题,我专注于日期维度。 我遇到的问题是,当我尝试从另一个存储过程运行一个存储过程时,我收到一些错误消息,例如
我还应该指出,其中一个存储过程调用了一堆函数来处理将插入到日期维度表中的日期维值。
这是第一个存储过程DATE_DIM_CREATE的代码,它调用NEW_DATE:
create or replace
PROCEDURE DATE_DIM_CREATE
AUTHID CURRENT_USER
IS
V_START_DATE DATE := TO_DATE('01/01/1900','MM/DD/YYYY');
V_CURRENT_DATE DATE := V_START_DATE;
V_END_DATE DATE := TO_DATE('12/31/2099','MM/DD/YYYY');
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE "DATE_DIM" PURGE';
EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_LANGUAGE = ''AMERICAN'' ';
EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_TERRITORY = ''AMERICA'' ';
EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_CALENDAR = ''GREGORIAN'' ';
EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_DATE_FORMAT = ''MM/DD/YYYY'' ';
EXECUTE IMMEDIATE
'CREATE TABLE DATE_DIM
(
DATE_KEY NUMBER(8, 0) NOT NULL,
DATE_TYPE VARCHAR2(14),
FULL_DATE DATE,
FULL_DATE_REVERSE VARCHAR2(10),
FULL_DATE_DESCRIPTION VARCHAR2(31),
DAY_NUMBER NUMBER(2, 0),
DAY_NAME VARCHAR2(9),
DAY_SHORT VARCHAR2(3),
FIRST_DAY_IN_MONTH DATE,
LAST_DAY_IN_MONTH DATE,
FIRST_DAY_IN_PREVIOUS_MONTH DATE,
LAST_DAY_IN_PREVIOUS_MONTH DATE,
FIRST_DAY_IN_NEXT_MONTH DATE,
LAST_DAY_IN_NEXT_MONTH DATE,
FIRST_DAY_IN_CALENDAR_QTR DATE,
LAST_DAY_IN_CALENDAR_QTR DATE,
FIRST_DAY_IN_PREV_CALENDAR_QTR DATE,
LAST_DAY_IN_PREV_CALENDAR_QTR DATE,
FIRST_DAY_IN_NEXT_CALENDAR_QTR DATE,
LAST_DAY_IN_NEXT_CALENDAR_QTR DATE,
FIRST_DAY_IN_CALENDAR_YEAR DATE,
LAST_DAY_IN_CALENDAR_YEAR DATE,
DAY_NUMBER_IN_CALENDAR_YEAR NUMBER(3, 0),
FIRST_DAY_IN_FISCAL_QTR DATE,
LAST_DAY_IN_FISCAL_QTR DATE,
FIRST_DAY_IN_PREV_FISCAL_QTR DATE,
LAST_DAY_IN_PREV_FISCAL_QTR DATE,
FIRST_DAY_IN_NEXT_FISCAL_QTR DATE,
LAST_DAY_IN_NEXT_FISCAL_QTR DATE,
FIRST_DAY_IN_FISCAL_YEAR DATE,
LAST_DAY_IN_FISCAL_YEAR DATE,
DAY_NUMBER_IN_FISCAL_YEAR NUMBER(3, 0),
IS_WEEKDAY VARCHAR2(1),
IS_WEEKEND VARCHAR2(1),
WEEK_IN_MONTH NUMBER(1, 0),
WEEK_IN_CALENDAR_YEAR_ISO NUMBER(2, 0),
WEEK_IN_FISCAL_YEAR_ISO NUMBER(2, 0),
BEGIN_FULL_WEEK DATE,
END_FULL_WEEK DATE,
BEGIN_WORK_WEEK DATE,
END_WORK_WEEK DATE,
MONTH_NUMBER NUMBER(2, 0),
MONTH_NAME VARCHAR(9),
MONTH_SHORT VARCHAR(3),
CALENDAR_QUARTER NUMBER(1, 0),
CALENDAR_QUARTER_NAME VARCHAR2(11),
CALENDAR_QUARTER_YEAR VARCHAR2(9),
FISCAL_QUARTER NUMBER(1, 0),
FISCAL_QUARTER_NAME VARCHAR2(11),
FISCAL_QUARTER_YEAR VARCHAR2(9),
CALENDAR_YEAR_NUMBER NUMBER(4, 0),
CALENDAR_YEAR VARCHAR2(6),
FISCAL_YEAR_NUMBER NUMBER(4, 0),
FISCAL_YEAR VARCHAR2(6),
IS_HOLIDAY VARCHAR2(1),
IS_BUSINESS_DAY VARCHAR2(1),
CONSTRAINT DATE_KEY_PK PRIMARY KEY (DATE_KEY)
)';
EXECUTE IMMEDIATE
'COMMENT ON TABLE DATE_DIM
IS ''Date dimension table used for storing date attributes.'' ';
EXECUTE IMMEDIATE
'COMMENT ON COLUMN DATE_DIM.DATE_KEY
IS ''Date key is the primary/surrogate key for the date dimension table.'' ';
WHILE V_CURRENT_DATE <= V_END_DATE LOOP
NEW_DATE(V_CURRENT_DATE);
V_CURRENT_DATE := V_CURRENT_DATE + INTERVAL '1' DAY;
END LOOP;
NEW_DATE(TO_DATE('12/29/9999', 'MM/DD/YYYY'));
NEW_DATE(TO_DATE('12/30/9999', 'MM/DD/YYYY'));
NEW_DATE(TO_DATE('12/31/9999', 'MM/DD/YYYY'));
END DATE_DIM_CREATE;
这里是NEW_DATE过程,它将值插入表中并调用所有函数:
create or replace
PROCEDURE NEW_DATE(P_DATE IN DATE)
AUTHID CURRENT_USER
IS
BEGIN
INSERT INTO DATE_DIM
(
DATE_KEY,
DATE_TYPE,
FULL_DATE,
FULL_DATE_REVERSE,
FULL_DATE_DESCRIPTION,
DAY_NUMBER,
DAY_NAME,
DAY_SHORT,
FIRST_DAY_IN_MONTH,
LAST_DAY_IN_MONTH,
FIRST_DAY_IN_PREVIOUS_MONTH,
LAST_DAY_IN_PREVIOUS_MONTH,
FIRST_DAY_IN_NEXT_MONTH,
LAST_DAY_IN_NEXT_MONTH,
FIRST_DAY_IN_CALENDAR_QTR,
LAST_DAY_IN_CALENDAR_QTR,
FIRST_DAY_IN_PREV_CALENDAR_QTR,
LAST_DAY_IN_PREV_CALENDAR_QTR,
FIRST_DAY_IN_NEXT_CALENDAR_QTR,
LAST_DAY_IN_NEXT_CALENDAR_QTR,
FIRST_DAY_IN_CALENDAR_YEAR,
LAST_DAY_IN_CALENDAR_YEAR,
DAY_NUMBER_IN_CALENDAR_YEAR,
FIRST_DAY_IN_FISCAL_QTR,
LAST_DAY_IN_FISCAL_QTR,
FIRST_DAY_IN_PREV_FISCAL_QTR,
LAST_DAY_IN_PREV_FISCAL_QTR,
FIRST_DAY_IN_NEXT_FISCAL_QTR,
LAST_DAY_IN_NEXT_FISCAL_QTR,
FIRST_DAY_IN_FISCAL_YEAR,
LAST_DAY_IN_FISCAL_YEAR,
DAY_NUMBER_IN_FISCAL_YEAR,
IS_WEEKDAY,
IS_WEEKEND,
WEEK_IN_MONTH,
WEEK_IN_CALENDAR_YEAR_ISO,
WEEK_IN_FISCAL_YEAR_ISO,
BEGIN_FULL_WEEK,
END_FULL_WEEK,
BEGIN_WORK_WEEK,
END_WORK_WEEK,
MONTH_NUMBER,
MONTH_NAME,
MONTH_SHORT,
CALENDAR_QUARTER,
CALENDAR_QUARTER_NAME,
CALENDAR_QUARTER_YEAR,
FISCAL_QUARTER,
FISCAL_QUARTER_NAME,
FISCAL_QUARTER_YEAR,
CALENDAR_YEAR_NUMBER,
CALENDAR_YEAR,
FISCAL_YEAR_NUMBER,
FISCAL_YEAR,
IS_HOLIDAY,
IS_BUSINESS_DAY
)
VALUES
(
DATE_KEY_FX(P_DATE), --DATE_KEY
DATE_TYPE_FX(P_DATE), --DATE_TYPE
P_DATE, --FULL_DATE
FULL_DATE_REVERSE_FX(P_DATE), --FULL_DATE_REVERSE
FULL_DATE_DESCRIPTION_FX(P_DATE), --FULL_DATE_DESCRIPTION
DAY_NUMBER_FX(P_DATE), --DAY_NUMBER
DAY_NAME_FX(P_DATE), --DAY_NAME
DAY_SHORT_FX(P_DATE), --DAY_SHORT
DAY_IN_MONTH_FX(P_DATE, 0, 0), --FIRST_DAY_IN_MONTH
DAY_IN_MONTH_FX(P_DATE, 1, 0), --LAST_DAY_IN_MONTH
DAY_IN_MONTH_FX(P_DATE, 0, -1), --FIRST_DAY_IN_PREVIOUS_MONTH
DAY_IN_MONTH_FX(P_DATE, 1, -1), --LAST_DAY_IN_PREVIOUS_MONTH
DAY_IN_MONTH_FX(P_DATE, 0, 1), --FIRST_DAY_IN_NEXT_MONTH
DAY_IN_MONTH_FX(P_DATE, 1, 1), --LAST_DAY_IN_NEXT_MONTH
DAY_IN_QTR_FX(P_DATE, 0, 0, 0), --FIRST_DAY_IN_CALENDAR_QTR
DAY_IN_QTR_FX(P_DATE, 1, 0, 0), --LAST_DAY_IN_CALENDAR_QTR
DAY_IN_QTR_FX(P_DATE, 0, -1, 0), --FIRST_DAY_IN_PREV_CALENDAR_QTR
DAY_IN_QTR_FX(P_DATE, 1, -1, 0), --LAST_DAY_IN_PREV_CALENDAR_QTR
DAY_IN_QTR_FX(P_DATE, 0, 1, 0), --FIRST_DAY_IN_NEXT_CALENDAR_QTR
DAY_IN_QTR_FX(P_DATE, 1, 1, 0), --LAST_DAY_IN_NEXT_CALENDAR_QTR
DAY_IN_YEAR_FX(P_DATE, 0, 0), --FIRST_DAY_IN_CALENDAR_YEAR
DAY_IN_YEAR_FX(P_DATE, 1, 0), --LAST_DAY_IN_CALENDAR_YEAR
DAY_NUMBER_IN_YEAR_FX(P_DATE, 0), --DAY_NUMBER_IN_CALENDAR_YEAR
DAY_IN_QTR_FX(P_DATE, 0, 0, 1), --FIRST_DAY_IN_FISCAL_QTR
DAY_IN_QTR_FX(P_DATE, 1, 0, 1), --LAST_DAY_IN_FISCAL_QTR
DAY_IN_QTR_FX(P_DATE, 0, -1, 1), --FIRST_DAY_IN_PREV_FISCAL_QTR
DAY_IN_QTR_FX(P_DATE, 1, -1, 1), --LAST_DAY_IN_PREV_FISCAL_QTR
DAY_IN_QTR_FX(P_DATE, 0, 1, 1), --FIRST_DAY_IN_NEXT_FISCAL_QTR
DAY_IN_QTR_FX(P_DATE, 1, 1, 1), --LAST_DAY_IN_NEXT_FISCAL_QTR
DAY_IN_YEAR_FX(P_DATE, 0, 1), --FIRST_DAY_IN_FISCAL_YEAR
DAY_IN_YEAR_FX(P_DATE, 1, 1), --LAST_DAY_IN_FISCAL_YEAR
DAY_NUMBER_IN_YEAR_FX(P_DATE, 1), --DAY_NUMBER_IN_FISCAL_YEAR
IS_WEEKDAY_FX(P_DATE), --IS_WEEKDAY
IS_WEEKEND_FX(P_DATE), --IS_WEEKEND
WEEK_IN_MONTH_FX(P_DATE), --WEEK_IN_MONTH
WEEK_IN_YEAR_ISO_FX(P_DATE, 0), --WEEK_IN_CALENDAR_YEAR_ISO
WEEK_IN_YEAR_ISO_FX(P_DATE, 1), --WEEK_IN_FISCAL_YEAR_ISO
WEEK_POINT_FX(P_DATE, 0, 0), --BEGIN_FULL_WEEK
WEEK_POINT_FX(P_DATE, 1, 0), --END_FULL_WEEK
WEEK_POINT_FX(P_DATE, 0, 1), --BEGIN_WORK_WEEK
WEEK_POINT_FX(P_DATE, 1, 1), --END_WORK_WEEK
MONTH_NUMBER_FX(P_DATE), --MONTH_NUMBER
MONTH_NAME_FX(P_DATE), --MONTH_NAME
MONTH_SHORT_FX(P_DATE), --MONTH_SHORT
QUARTER_FX(P_DATE, 0), --CALENDAR_QUARTER
QUARTER_NAME_FX(P_DATE, 0), --CALENDAR_QUARTER_NAME
QUARTER_YEAR_FX(P_DATE, 0), --CALENDAR_QUARTER_YEAR
QUARTER_FX(P_DATE, 1), --FISCAL_QUARTER
QUARTER_NAME_FX(P_DATE, 1), --FISCAL_QUARTER_NAME
QUARTER_YEAR_FX(P_DATE, 1), --FISCAL_QUARTER_YEAR
YEAR_NUMBER_FX(P_DATE, 0), --CALENDAR_YEAR_NUMBER
YEAR_FORMAT_FX(P_DATE, 0), --CALENDAR_YEAR
YEAR_NUMBER_FX(P_DATE, 1), --FISCAL_YEAR_NUMBER
YEAR_FORMAT_FX(P_DATE, 1), --FISCAL_YEAR
IS_HOLIDAY_FX(P_DATE), --IS_HOLIDAY
IS_BUSINESS_DAY_FX(P_DATE) --IS_BUSINESSDAY
);
END NEW_DATE;
我不确定是否需要在EXECUTE IMMEDIATE
存储过程中INSERT INTO
附近放置NEW_DATE
,但这样做对我没有任何影响目前的问题。
另外,我没有DBA,所以我确定我的代码有一百万个问题。但是,如果有一种方法可以解决错误并使代码工作,同时仍然使用底层技术(其中一个存储过程调用另一个调用一堆函数的存储过程),那么这就是我&我#39; d最终在一些帮助下实现。
更新#1
似乎在动态SQL中INSERT INTO
过程中封装NEW_DATE
语句有点帮助。但是,它引入了以下新错误:
这些新错误是否可能是由于我在P_DATE
程序的VALUES
部分中使用NEW_DATE
参数引起的?如果是这样,我将如何更改此选项以允许使用该参数?我尝试了以下操作,但收到了相同的错误消息(专注于FULL_DATE列):
EXECUTE IMMEDIATE
'INSERT INTO
(
DATE_TYPE,
FULL_DATE,
FULL_DATE_REVERSE
)
VALUES
(
DATE_TYPE_FX(P_DATE), --DATE_TYPE
'|| P_DATE ||', --FULL_DATE
FULL_DATE_REVERSE_FX(P_DATE) --FULL_DATE_REVERSE
)';
由于
答案 0 :(得分:1)
ORA-04068消息表明从属程序单元已失效(未编译)。除其他事项外,这种情况发生在该程序单元的依赖性已经受到DDL的影响时。
您有一个删除并重新创建表的过程,以及另一个填充该表的过程。当您运行第一个过程时,其DDL使第二个过程无效。
但是你的第一个过程会调用第二个过程,并且该依赖项是问题的根源。
虽然可以说问题的真正根源是有一个程序可以删除并重新创建一个表。很少有真正需要这种情况的真实案例。这种方法大多只是想象力的失败。
但是,如果您真的坚持这个想法,那么您还需要在动态SQL中包装NEW_DATE插入语句。这将破坏依赖关系树并防止表被删除时失效。
“所以我需要在NEW_DATE中包装INSERT INTO语句 过程,在动态SQL“
是。 NEW_DATE()在DATE_DIM上有编译时依赖关系,因为INSERT是静态SQL。删除表时,该过程无效。如果将INSERT语句设置为动态SQL调用,则依赖项将进入运行时。这意味着当您删除表时,NEW_DATE()将不会失效。事实上,如果表不存在,你仍然可以执行;它只会向ORA-00904或类似错误投掷。
那么为什么我们不让所有的程序都使用动态SQL,从而消除了ORA-04068消息的诅咒?因为动态SQL是一个痛苦的问题,尤其是调试。此外,我们从依赖项中丢失了一些价值信息,这使得对数据库更改进行影响分析变得更加困难。此外,做你正在做的事情,并将DDL置于可重复的程序化过程中通常是不必要的。
“您认为参数是此处不允许列的原因吗? 我收到的错误?“
绝对。这是一个字符串文字,EXECUTE IMMEDIATE按字面意思运行,在SQL引擎中。 P_DATE
是PL / SQL参数,超出SQL范围。
如果要传递参数,则需要使用正确的语法:
EXECUTE IMMEDIATE
'INSERT INTO
(
DATE_TYPE,
FULL_DATE,
FULL_DATE_REVERSE
)
VALUES
(
DATE_TYPE_FX(:1), --DATE_TYPE
:2, --FULL_DATE
FULL_DATE_REVERSE_FX(:3) --FULL_DATE_REVERSE
)' using p_date, p_date, p_date;
请注意,占位符就是这样。如果你想在27个位置使用相同的值,你需要在USING子句中使用27个占位符和27个匹配的匹配项。
我认为如果您对动态SQL有任何疑问,您的第一个调用端口应该是文档。 Find it here。如果这对您没有帮助,请开始新的thead。
答案 1 :(得分:0)
create or replace
PROCEDURE DATE_DIM_CREATE
AUTHID CURRENT_USER
IS
V_START_DATE DATE := TO_DATE('01/01/1900','MM/DD/YYYY');
V_CURRENT_DATE DATE := V_START_DATE;
V_END_DATE DATE := TO_DATE('12/31/2099','MM/DD/YYYY');
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE "DATE_DIM" PURGE'; <-- <b>you can use if exists function so you dont get an error saying date_dim not found
EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_LANGUAGE = ''AMERICAN'' ';
EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_TERRITORY = ''AMERICA'' ';
EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_CALENDAR = ''GREGORIAN'' ';
EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_DATE_FORMAT = ''MM/DD/YYYY'' ';
EXECUTE IMMEDIATE
'CREATE TABLE DATE_DIM
(
DATE_KEY NUMBER(8, 0) NOT NULL,
DATE_TYPE VARCHAR2(14),
FULL_DATE DATE,
FULL_DATE_REVERSE VARCHAR2(10),
FULL_DATE_DESCRIPTION VARCHAR2(31),
DAY_NUMBER NUMBER(2, 0),
DAY_NAME VARCHAR2(9),
DAY_SHORT VARCHAR2(3),
FIRST_DAY_IN_MONTH DATE,
LAST_DAY_IN_MONTH DATE,
FIRST_DAY_IN_PREVIOUS_MONTH DATE,
LAST_DAY_IN_PREVIOUS_MONTH DATE,
FIRST_DAY_IN_NEXT_MONTH DATE,
LAST_DAY_IN_NEXT_MONTH DATE,
FIRST_DAY_IN_CALENDAR_QTR DATE,
LAST_DAY_IN_CALENDAR_QTR DATE,
FIRST_DAY_IN_PREV_CALENDAR_QTR DATE,
LAST_DAY_IN_PREV_CALENDAR_QTR DATE,
FIRST_DAY_IN_NEXT_CALENDAR_QTR DATE,
LAST_DAY_IN_NEXT_CALENDAR_QTR DATE,
FIRST_DAY_IN_CALENDAR_YEAR DATE,
LAST_DAY_IN_CALENDAR_YEAR DATE,
DAY_NUMBER_IN_CALENDAR_YEAR NUMBER(3, 0),
FIRST_DAY_IN_FISCAL_QTR DATE,
LAST_DAY_IN_FISCAL_QTR DATE,
FIRST_DAY_IN_PREV_FISCAL_QTR DATE,
LAST_DAY_IN_PREV_FISCAL_QTR DATE,
FIRST_DAY_IN_NEXT_FISCAL_QTR DATE,
LAST_DAY_IN_NEXT_FISCAL_QTR DATE,
FIRST_DAY_IN_FISCAL_YEAR DATE,
LAST_DAY_IN_FISCAL_YEAR DATE,
DAY_NUMBER_IN_FISCAL_YEAR NUMBER(3, 0),
IS_WEEKDAY VARCHAR2(1),
IS_WEEKEND VARCHAR2(1),
WEEK_IN_MONTH NUMBER(1, 0),
WEEK_IN_CALENDAR_YEAR_ISO NUMBER(2, 0),
WEEK_IN_FISCAL_YEAR_ISO NUMBER(2, 0),
BEGIN_FULL_WEEK DATE,
END_FULL_WEEK DATE,
BEGIN_WORK_WEEK DATE,
END_WORK_WEEK DATE,
MONTH_NUMBER NUMBER(2, 0),
MONTH_NAME VARCHAR(9),
MONTH_SHORT VARCHAR(3),
CALENDAR_QUARTER NUMBER(1, 0),
CALENDAR_QUARTER_NAME VARCHAR2(11),
CALENDAR_QUARTER_YEAR VARCHAR2(9),
FISCAL_QUARTER NUMBER(1, 0),
FISCAL_QUARTER_NAME VARCHAR2(11),
FISCAL_QUARTER_YEAR VARCHAR2(9),
CALENDAR_YEAR_NUMBER NUMBER(4, 0),
CALENDAR_YEAR VARCHAR2(6),
FISCAL_YEAR_NUMBER NUMBER(4, 0),
FISCAL_YEAR VARCHAR2(6),
IS_HOLIDAY VARCHAR2(1),
IS_BUSINESS_DAY VARCHAR2(1),
CONSTRAINT DATE_KEY_PK PRIMARY KEY (DATE_KEY)
)
/
表DATE_DIM的评论
IS''用于存储日期属性的日期维度表。'' /
栏目评论DATE_DIM.DATE_KEY
IS''日期键是日期维度表的主要/代理键。''';
WHILE V_CURRENT_DATE <= V_END_DATE LOOP
NEW_DATE(V_CURRENT_DATE);
V_CURRENT_DATE := V_CURRENT_DATE + INTERVAL '1' DAY;
END LOOP;
这是你应该做的......你应该调用程序
exec NEW_DATE;
NEW_DATE(TO_DATE('12 / 29/9999','MM / DD / YYYY'));
NEW_DATE(TO_DATE('12 / 30/9999','MM / DD / YYYY'));
NEW_DATE(TO_DATE('12 / 31/9999','MM / DD / YYYY'));
END DATE_DIM_CREATE;<br/>
我目前没有plsql来检查它,但你的问题是你没有以正确的方式调用程序。方式是新的DE_DATe \ e。我应该提一下,我已经在create table中更正了一些内容,你可以在create table中包含注释