Oracle 存储过程与 case when 位于 where 原因中

发布于 2025-01-09 12:11:01 字数 540 浏览 0 评论 0原文

以下存储过程出现错误。看来错误是在 where 原因的 case 语句中。我该如何修复它?

create or replace PROCEDURE APPEND_HIST_TBLS_PROC AS 
CurTerm varchar2(4) := '1222';
PS_ACAD_PROG_HISTORY varchar2(35) := 'PS_ACAD_PROG_HISTORY_' || CurTerm;
Begin
execute immediate 'insert into ' || PS_ACAD_PROG_HISTORY
|| '(select sysdate as date_created,
EFFDT, 
ADMIT_TERM, 
EXP_GRAD_TERM, 
CAMPUS
from ERP_ACAD
where CASE WHEN SUBSTR(ADMIT_TERM,4,1)= '6' THEN SUBSTR(ADMIT_TERM,1,3) || '9' ELSE ADMIT_TERM END = '||CurTerm ||'
)';
END APPEND_HIST_TBLS_PROC;

The following stored procedure complied with errors. It seems the errors are in the case statement in the where cause. How do I fix it?

create or replace PROCEDURE APPEND_HIST_TBLS_PROC AS 
CurTerm varchar2(4) := '1222';
PS_ACAD_PROG_HISTORY varchar2(35) := 'PS_ACAD_PROG_HISTORY_' || CurTerm;
Begin
execute immediate 'insert into ' || PS_ACAD_PROG_HISTORY
|| '(select sysdate as date_created,
EFFDT, 
ADMIT_TERM, 
EXP_GRAD_TERM, 
CAMPUS
from ERP_ACAD
where CASE WHEN SUBSTR(ADMIT_TERM,4,1)= '6' THEN SUBSTR(ADMIT_TERM,1,3) || '9' ELSE ADMIT_TERM END = '||CurTerm ||'
)';
END APPEND_HIST_TBLS_PROC;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

别念他 2025-01-16 12:11:01

动态SQL很难维护和调试。过程编译成功这一事实没有告诉关于动态语句本身的信息 - 它只是说过程“按原样”没有错误。

编写语句并将其存储到局部变量中,然后显示其内容是一个好习惯;一旦确认没问题,就执行它。

另外,由于您必须转义单引号(有时它会变得令人讨厌,有几个连续的单引号可以满足您的需要),因此使用q-quoting机制可以让您编写“正常”语句(那么单引号确实是单引号)。

像这样的事情:

SQL> CREATE OR REPLACE PROCEDURE append_hist_tbls_proc
  2  AS
  3     curterm               VARCHAR2 (4) := '1222';
  4     ps_acad_prog_history  VARCHAR2 (35) := 'PS_ACAD_PROG_HISTORY_' || curterm;
  5     l_str                 VARCHAR2 (4000);
  6  BEGIN
  7     -- Compose the INSERT statement into a VARCHAR2 local variable so that you'd be able
  8     -- to check whether you did it right or not.
  9     -- Use the q-quoting mechanism as it helps with consecutive single quotes issues
 10     l_str :=
 11           'INSERT INTO '
 12        || ps_acad_prog_history
 13        || q'[ SELECT sysdate as date_created,
 14                      effdt,
 15                      admit_term,
 16                      exp_grad_term,
 17                      campus
 18        FROM erp_acad
 19        WHERE CASE WHEN SUBSTR(admit_term, 4, 1) = '6' THEN
 20                        SUBSTR(admit_term, 1, 3) || '9'
 21                   ELSE ADMIT_TERM
 22              END = ]'
 23        || curterm;
 24
 25     -- FIRST check the command you're about to execute
 26     DBMS_OUTPUT.put_line (l_str);
 27
 28     -- When you verified that it is correct, then comment DBMS_OUTPUT.PUT_LINE call
 29     -- and uncomment EXECUTE IMMEDIATE
 30     -- EXECUTE IMMEDIATE l_str;
 31  END append_hist_tbls_proc;
 32  /

Procedure created.

让我们尝试一下:

SQL> SET SERVEROUTPUT ON
SQL> EXEC append_hist_tbls_proc;
INSERT INTO PS_ACAD_PROG_HISTORY_1222 SELECT sysdate as date_created,

effdt,
                    admit_term,
                    exp_grad_term,

campus
      FROM erp_acad
      WHERE CASE WHEN SUBSTR(admit_term, 4, 1) = '6'
THEN
                      SUBSTR(admit_term, 1, 3) || '9'
                 ELSE
ADMIT_TERM
            END = 1222

PL/SQL procedure successfully completed.

SQL>

输出看起来很难看(这是在过程中让它漂亮的代价),但是 - 如果你格式化它 - 它看起来像这样:

INSERT INTO PS_ACAD_PROG_HISTORY_1222
   SELECT SYSDATE AS date_created,
          effdt,
          admit_term,
          exp_grad_term,
          campus
     FROM erp_acad
    WHERE CASE
             WHEN SUBSTR (admit_term, 4, 1) = '6'
             THEN
                SUBSTR (admit_term, 1, 3) || '9'
             ELSE
                ADMIT_TERM
          END = 1222

所以,如果你真的可以执行它(我不能,我没有你的表),然后取消注释立即执行并使用该过程。否则,请修复该语句。

Dynamic SQL is difficult to maintain and debug. The fact that procedure compiled successfully tells nothing about the dynamic statement itself - it just says that there were no errors in the procedure "as is".

It is a good habit to compose the statement and store it into a local variable and then display its contents; once you verify it is OK, then execute it.

Also, as you have to escape single quotes (sometimes it becomes nasty, with several consecutive single quotes which do what you need), use the q-quoting mechanism which lets you write "normal" statements (single quotes really are single, then).

Something like this:

SQL> CREATE OR REPLACE PROCEDURE append_hist_tbls_proc
  2  AS
  3     curterm               VARCHAR2 (4) := '1222';
  4     ps_acad_prog_history  VARCHAR2 (35) := 'PS_ACAD_PROG_HISTORY_' || curterm;
  5     l_str                 VARCHAR2 (4000);
  6  BEGIN
  7     -- Compose the INSERT statement into a VARCHAR2 local variable so that you'd be able
  8     -- to check whether you did it right or not.
  9     -- Use the q-quoting mechanism as it helps with consecutive single quotes issues
 10     l_str :=
 11           'INSERT INTO '
 12        || ps_acad_prog_history
 13        || q'[ SELECT sysdate as date_created,
 14                      effdt,
 15                      admit_term,
 16                      exp_grad_term,
 17                      campus
 18        FROM erp_acad
 19        WHERE CASE WHEN SUBSTR(admit_term, 4, 1) = '6' THEN
 20                        SUBSTR(admit_term, 1, 3) || '9'
 21                   ELSE ADMIT_TERM
 22              END = ]'
 23        || curterm;
 24
 25     -- FIRST check the command you're about to execute
 26     DBMS_OUTPUT.put_line (l_str);
 27
 28     -- When you verified that it is correct, then comment DBMS_OUTPUT.PUT_LINE call
 29     -- and uncomment EXECUTE IMMEDIATE
 30     -- EXECUTE IMMEDIATE l_str;
 31  END append_hist_tbls_proc;
 32  /

Procedure created.

Let's try it:

SQL> SET SERVEROUTPUT ON
SQL> EXEC append_hist_tbls_proc;
INSERT INTO PS_ACAD_PROG_HISTORY_1222 SELECT sysdate as date_created,

effdt,
                    admit_term,
                    exp_grad_term,

campus
      FROM erp_acad
      WHERE CASE WHEN SUBSTR(admit_term, 4, 1) = '6'
THEN
                      SUBSTR(admit_term, 1, 3) || '9'
                 ELSE
ADMIT_TERM
            END = 1222

PL/SQL procedure successfully completed.

SQL>

Output looks ugly (that's the price of having it pretty in the procedure), but - if you format it - it looks like this:

INSERT INTO PS_ACAD_PROG_HISTORY_1222
   SELECT SYSDATE AS date_created,
          effdt,
          admit_term,
          exp_grad_term,
          campus
     FROM erp_acad
    WHERE CASE
             WHEN SUBSTR (admit_term, 4, 1) = '6'
             THEN
                SUBSTR (admit_term, 1, 3) || '9'
             ELSE
                ADMIT_TERM
          END = 1222

So, if you can really execute it (I can't, I don't have your tables), then uncomment execute immediate and use the procedure. Otherwise, fix the statement.

窗影残 2025-01-16 12:11:01

似乎是引用的问题。您是否尝试过此操作:

create or replace PROCEDURE APPEND_HIST_TBLS_PROC AS 
CurTerm varchar2(4) := '1222';
PS_ACAD_PROG_HISTORY varchar2(35) := 'PS_ACAD_PROG_HISTORY_' || CurTerm;
Begin
execute immediate 'insert into ' || PS_ACAD_PROG_HISTORY
|| '(select sysdate as date_created,
EFFDT, 
ADMIT_TERM, 
EXP_GRAD_TERM, 
CAMPUS
from ERP_ACAD
where CASE WHEN SUBSTR(ADMIT_TERM,4,1)= ''6'' 
THEN CONCAT(SUBSTR(ADMIT_TERM,1,3), ''9'') ELSE ADMIT_TERM END = '||CurTerm ||'
)';
END APPEND_HIST_TBLS_PROC;

假设您想在 admin_term 子字符串的末尾附加 9,也使用 CONCAT 而不是双管道。

确实取决于您的数据和您要实现的逻辑。该过程现在应该可以编译,但它是否达到所需的结果 - 取决于您在此处尝试实现的逻辑。

Seems like an issue with quoting. Have you tried this:

create or replace PROCEDURE APPEND_HIST_TBLS_PROC AS 
CurTerm varchar2(4) := '1222';
PS_ACAD_PROG_HISTORY varchar2(35) := 'PS_ACAD_PROG_HISTORY_' || CurTerm;
Begin
execute immediate 'insert into ' || PS_ACAD_PROG_HISTORY
|| '(select sysdate as date_created,
EFFDT, 
ADMIT_TERM, 
EXP_GRAD_TERM, 
CAMPUS
from ERP_ACAD
where CASE WHEN SUBSTR(ADMIT_TERM,4,1)= ''6'' 
THEN CONCAT(SUBSTR(ADMIT_TERM,1,3), ''9'') ELSE ADMIT_TERM END = '||CurTerm ||'
)';
END APPEND_HIST_TBLS_PROC;

Also used CONCAT instead of double pipe assuming you want to append 9 at the end of sub string of admin_term.

Really depends on your data and the logic you are trying to implement. This procedure should now compile but whether it achieves the desired result - depends on the logic you are trying to implement here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文