PL/SQL 存储过程 - IF THEN ELSE 条件
PL/SQL Stored Procedure - IF THEN ELSE condition
存储过程是我自己写的,也是为了自己的学习。这是针对数据仓库的,发生的情况是在两个参数之间 table 将填充从 START_YEAR 第一天到 END_YEAR 最后一天的日期。我的存储过程将包含更多列,但我打算一点一点地开始,并在构建代码时处理错误。因此,例如 sp_DATE_D(2000,2001) 并且当您 运行 在 Application Express 中为一行 select 语句时,它 returns以下
当我 运行 一行的 SELECT 语句时的预期
DATE_KEY = 2000 年 1 月 1 日
FULL_DATE_DESCRIPTION = 2000 年 1 月 1 日星期六
DAY_OF_WEEK = 6
LAST_DAY_OF_WEEK_INDICATOR = Y -- 如果是星期六则为 Y,对于其他所有情况则为 N。
Table定义:
CREATE TABLE DATE_D
(
DATE_KEY DATE NOT NULL,
FULL_DATE_DESCRIPTION VARCHAR2(64) NOT NULL,
DAY_OF_WEEK NUMBER(1,0) NOT NULL,
LAST_DAY_OF_WEEK_INDICATOR CHAR(1) NOT NULL,
CONSTRAINT DATE_D_PK PRIMARY KEY (DATE_KEY)
);
存储过程:
我知道有一个条件需要实施,只是不确定在哪里。我尝试了 IF THEN ELSE,但没有成功。
CREATE OR REPLACE PROCEDURE sp_DATE_D(v_START_YEAR IN INT, v_END_YEAR IN INT) AS
v_CURRENT_DATE DATE;
v_END_DATE DATE;
BEGIN
v_CURRENT_DATE := TO_DATE('0101' || v_START_YEAR, 'MMDDYYYY');
v_END_DATE := TO_DATE('1231' || v_END_YEAR, 'MMDDYYYY');
DELETE FROM DATE_D;
WHILE v_CURRENT_DATE <= v_END_DATE
LOOP
INSERT INTO DATE_D
(
DATE_KEY,
FULL_DATE_DESCRIPTION,
DAY_OF_WEEK
)
VALUES
(
v_CURRENT_DATE,
TO_CHAR(v_CURRENT_DATE, 'Day, Month DD, YYYY'),
TO_NUMBER(TO_CHAR(v_CURRENT_DATE,'D')) - 1
);
BEGIN
IF TO_CHAR(v_CURRENT_DATE,'DAY') != 'Saturday' THEN
INSERT INTO DATE_D (LAST_DAY_OF_WEEK_INDICATOR) values(LAST_DAY_OF_WEEK_INDICATOR = 'N');
ELSE
INSERT INTO DATE_D(LAST_DAY_OF_WEEK_INDICATOR) values(LAST_DAY_OF_WEEK_INDICATOR = 'Y');
END IF;
END;
v_CURRENT_DATE := v_CURRENT_DATE + 1;
END LOOP;
END;
/
错误
编译失败,第 49 行 (17:03:53)
PL/SQL: ORA-00917: 缺少逗号编译失败,第 49 行 (17:03:53)
PL/SQL:SQL 语句 ignoredCompilation 失败,第 51 行 (17:03:53)
PL/SQL: ORA-00917: 缺少逗号编译失败,第 51 行 (17:03:53)
PL/SQL: SQL 语句被忽略
您正试图在 if/else 的 table 中插入第二行,我认为这不是您真正想要的。我不确定您为什么将 LAST_DAY_OF_WEEK_INDICATOR =
部分放在 values 子句中;也许您正在尝试更新,但对它的语法(相当)感到困惑。
虽然永远不会匹配 if 条件,但您将日期转换为带有 DAY
的日期名称,这会为您提供全大写的日期名称。它也被填充到你的日期语言中最长的一天名称的长度,即英语中的星期三,所以你实际上必须与 SATURDAY
(尾随 space)进行比较,除非你包括 an FM
format modifier;并且您假设调用它的人将进行英语会话,这对于本练习可能是允许的。
您真的只想执行一次插入,而不是先插入再更新。 (我忽略了逐行方法的低效率,因为你说这是有意学习的)。因此,您可以将指示符列及其值作为现有插入的一部分。要在 SQL 语句中执行 if/else,您可以使用 decode 或 case 表达式:
...
LOOP
INSERT INTO DATE_D
(
DATE_KEY,
FULL_DATE_DESCRIPTION,
DAY_OF_WEEK,
LAST_DAY_OF_WEEK_INDICATOR
)
VALUES
(
v_CURRENT_DATE,
TO_CHAR(v_CURRENT_DATE, 'Day, Month DD, YYYY'),
TO_NUMBER(TO_CHAR(v_CURRENT_DATE,'D')) - 1,
CASE
WHEN TO_CHAR(v_CURRENT_DATE,'FMDay') = 'Saturday' THEN 'Y'
ELSE 'N'
END
);
v_CURRENT_DATE := v_CURRENT_DATE + 1;
END LOOP;
END;
/
如果您确实想要允许使用不同的会话语言,那么 to_char()
有第三个参数,它允许您指定用于日期和月份名称的语言。
请注意 FULL_DATE_DESCRIPTION
列中的填充,这会导致元素对齐。如果您希望它看起来更自然,也可以对该列值使用 FM 修饰符。
存储过程是我自己写的,也是为了自己的学习。这是针对数据仓库的,发生的情况是在两个参数之间 table 将填充从 START_YEAR 第一天到 END_YEAR 最后一天的日期。我的存储过程将包含更多列,但我打算一点一点地开始,并在构建代码时处理错误。因此,例如 sp_DATE_D(2000,2001) 并且当您 运行 在 Application Express 中为一行 select 语句时,它 returns以下
当我 运行 一行的 SELECT 语句时的预期
DATE_KEY = 2000 年 1 月 1 日
FULL_DATE_DESCRIPTION = 2000 年 1 月 1 日星期六
DAY_OF_WEEK = 6
LAST_DAY_OF_WEEK_INDICATOR = Y -- 如果是星期六则为 Y,对于其他所有情况则为 N。
Table定义:
CREATE TABLE DATE_D
(
DATE_KEY DATE NOT NULL,
FULL_DATE_DESCRIPTION VARCHAR2(64) NOT NULL,
DAY_OF_WEEK NUMBER(1,0) NOT NULL,
LAST_DAY_OF_WEEK_INDICATOR CHAR(1) NOT NULL,
CONSTRAINT DATE_D_PK PRIMARY KEY (DATE_KEY)
);
存储过程:
我知道有一个条件需要实施,只是不确定在哪里。我尝试了 IF THEN ELSE,但没有成功。
CREATE OR REPLACE PROCEDURE sp_DATE_D(v_START_YEAR IN INT, v_END_YEAR IN INT) AS
v_CURRENT_DATE DATE;
v_END_DATE DATE;
BEGIN
v_CURRENT_DATE := TO_DATE('0101' || v_START_YEAR, 'MMDDYYYY');
v_END_DATE := TO_DATE('1231' || v_END_YEAR, 'MMDDYYYY');
DELETE FROM DATE_D;
WHILE v_CURRENT_DATE <= v_END_DATE
LOOP
INSERT INTO DATE_D
(
DATE_KEY,
FULL_DATE_DESCRIPTION,
DAY_OF_WEEK
)
VALUES
(
v_CURRENT_DATE,
TO_CHAR(v_CURRENT_DATE, 'Day, Month DD, YYYY'),
TO_NUMBER(TO_CHAR(v_CURRENT_DATE,'D')) - 1
);
BEGIN
IF TO_CHAR(v_CURRENT_DATE,'DAY') != 'Saturday' THEN
INSERT INTO DATE_D (LAST_DAY_OF_WEEK_INDICATOR) values(LAST_DAY_OF_WEEK_INDICATOR = 'N');
ELSE
INSERT INTO DATE_D(LAST_DAY_OF_WEEK_INDICATOR) values(LAST_DAY_OF_WEEK_INDICATOR = 'Y');
END IF;
END;
v_CURRENT_DATE := v_CURRENT_DATE + 1;
END LOOP;
END;
/
错误
编译失败,第 49 行 (17:03:53)
PL/SQL: ORA-00917: 缺少逗号编译失败,第 49 行 (17:03:53)
PL/SQL:SQL 语句 ignoredCompilation 失败,第 51 行 (17:03:53)
PL/SQL: ORA-00917: 缺少逗号编译失败,第 51 行 (17:03:53)
PL/SQL: SQL 语句被忽略
您正试图在 if/else 的 table 中插入第二行,我认为这不是您真正想要的。我不确定您为什么将 LAST_DAY_OF_WEEK_INDICATOR =
部分放在 values 子句中;也许您正在尝试更新,但对它的语法(相当)感到困惑。
虽然永远不会匹配 if 条件,但您将日期转换为带有 DAY
的日期名称,这会为您提供全大写的日期名称。它也被填充到你的日期语言中最长的一天名称的长度,即英语中的星期三,所以你实际上必须与 SATURDAY
(尾随 space)进行比较,除非你包括 an FM
format modifier;并且您假设调用它的人将进行英语会话,这对于本练习可能是允许的。
您真的只想执行一次插入,而不是先插入再更新。 (我忽略了逐行方法的低效率,因为你说这是有意学习的)。因此,您可以将指示符列及其值作为现有插入的一部分。要在 SQL 语句中执行 if/else,您可以使用 decode 或 case 表达式:
...
LOOP
INSERT INTO DATE_D
(
DATE_KEY,
FULL_DATE_DESCRIPTION,
DAY_OF_WEEK,
LAST_DAY_OF_WEEK_INDICATOR
)
VALUES
(
v_CURRENT_DATE,
TO_CHAR(v_CURRENT_DATE, 'Day, Month DD, YYYY'),
TO_NUMBER(TO_CHAR(v_CURRENT_DATE,'D')) - 1,
CASE
WHEN TO_CHAR(v_CURRENT_DATE,'FMDay') = 'Saturday' THEN 'Y'
ELSE 'N'
END
);
v_CURRENT_DATE := v_CURRENT_DATE + 1;
END LOOP;
END;
/
如果您确实想要允许使用不同的会话语言,那么 to_char()
有第三个参数,它允许您指定用于日期和月份名称的语言。
请注意 FULL_DATE_DESCRIPTION
列中的填充,这会导致元素对齐。如果您希望它看起来更自然,也可以对该列值使用 FM 修饰符。