Oracle SQL:为什么我的提示是重复和重复

问题描述 投票:0回答:1
Enter the year you would like to check >2022
Enter the Tour Guide ID you would like to check >TG02
 72
 73
 74
 75
 76

这是屏幕的输出

alter session set nls_date_format = 'DD/MM/YYYY';


Undefine v_guideID, v_year

set linesize 75
set pagesize 40

ACCEPT v_year PROMPT 'Enter the year you would like to check >'
ACCEPT v_guideID PROMPT 'Enter the Tour Guide ID you would like to check >'

DECLARE
   v_year number;
   lastdayofyear date;
BEGIN
   lastdayofyear := TO_DATE('31-DEC-' || v_year, 'DD-MMM-YYYY');
END;

COL tourguideid FORMAT A8 HEADING "Guide ID"
COL type FORMAT A5 HEADING "Type"
COL name FORMAT A20 HEADING "Name"
COL datejoined FORMAT A14 HEADING "Join Date" 
COL basicsalary FORMAT $9999 HEADING "Basic Salary per Month"
COL Allowance FORMAT $99999 HEADING "Allowance Amount"
COL ProfitSharing FORMAT $99999 HEADING "Annual Profit Shared"
COL totalsalary FORMAT $99999999 HEADING "Annual Salary"

TTITLE center 'Annual Salary for ' &v_guideID ' in ' &v_year -
RIGHT 'Page No: ' FORMAT 999 SQL.PNO SKIP 2
BREAK ON tourguideid SKIP 2 ON bookingid
COMPUTE SUM LABEL 'Total : ' OF Allowance ON tourguideid;



create or replace view GetEachTourGuideMonth as (select TG.tourguideid, (months_between(TG.datejoined, lastDayOfYear)) as WorkMonths
from tourguide TG);

create or replace view TotalMonth as 
select SUM(WorkMonths)
From GetEachTourGuideMonth;

create or replace view ProfitUnit as 
Select tourguideid, name, (case v_year when 2021 then
                        (case when WorkMonths >= 12 then 0.03
                                   when WorkMonths >= 3 then 0.005
                                   else 0
                           END)
                        when 2022 then
                        (case when WorkMonths >= 12 then 0.0228
                                   when WorkMonths >= 3 then 0.005
                                   else 0
                           END)
                        when 2023 then
                        (case when WorkMonths >= 12 then 0.0188
                                   when WorkMonths >= 3 then 0.005
                                   else 0
                           END) 
             END)ProfitRate * PS.SharedProfit as ProfitGiven
From tourguide TG
JOIN ProfitSharing PS ON TG.tourguideid = PS.tourguideid;

create or replace view AllowanceEachGuide as 
SELECT
    COALESCE(P.tourguideid, CP.tourguideid) AS tourguideid,
    COALESCE(P.Allowance, CP.Allowance) AS Allowance
FROM
    Package P
FULL OUTER JOIN
    CustomizedPackage CP
ON
    P.tourguideid = CP.tourguideid
AND
    P.Allowance = CP.Allowance;

Select TG.tourguideid, TG.type ,TG.name, TG.datejoined, TG.basicsalary, AEG.Allowance, PU.ProfitSharing, (PU.ProfitGiven + (TG.basicsalary * 12) + AEG.Allowance) as TotalSalary
From tourguide TG
JOIN
    ProfitUnit PU ON TG.tourguideid = PU.tourguideid
JOIN
    AllowanceEachGuide AEG ON TG.tourguideid = AEG.tourguideid
where TG.tourguideid = &v_guideID;

这些是代码。这个文件正在计算每个导游的工资,总体利润还可以。但是这个文件有无限输入的问题...

sql oracle infinite-loop sqlplus
1个回答
0
投票

那是因为您在 PL/SQL 匿名块末尾缺少一个 slash 字符;参见第

#7
行:

SQL> alter session set nls_date_format = 'DD/MM/YYYY';

Session altered.

SQL> Undefine v_guideID, v_year
SQL>
SQL> set linesize 75
SQL> set pagesize 40
SQL>
SQL> ACCEPT v_year PROMPT 'Enter the year you would like to check >'
Enter the year you would like to check >2023
SQL> ACCEPT v_guideID PROMPT 'Enter the Tour Guide ID you would like to check >'
Enter the Tour Guide ID you would like to check >225
SQL> DECLARE
  2     v_year number;
  3     lastdayofyear date;
  4  BEGIN
  5     lastdayofyear := TO_DATE('31-DEC-' || v_year, 'DD-MMM-YYYY');
  6  END;
  7  /                                                                --> here

代码现在已执行,但是 - 错误:

   lastdayofyear := TO_DATE('31-DEC-' || v_year, 'DD-MMM-YYYY');
                   *
ERROR at line 5:
ORA-01821: date format not recognized
ORA-06512: at line 5

日期格式有什么问题?没有

MMM
!您使用的“DEC”表明您实际上想要
MON
格式模型,所以 - 让我们更改它:

SQL> DECLARE
  2     v_year number;
  3     lastdayofyear date;
  4  BEGIN
  5     lastdayofyear := TO_DATE('31-DEC-' || v_year, 'DD-MON-YYYY');
  6  END;
  7  /
   lastdayofyear := TO_DATE('31-DEC-' || v_year, 'DD-MON-YYYY');
                   *
ERROR at line 5:
ORA-01843: not a valid month
ORA-06512: at line 5

现在这个月有什么问题吗?啊哈...我的数据库不会说英语,而是克罗地亚语,所以我必须先解决这个问题。或者,也许更好的选择是使用不依赖于 NLS 的代码。例如,您应该选择

31.12.

SQL> alter session set nls_date_language = 'english';

Session altered.

SQL> DECLARE
  2     v_year number;
  3     lastdayofyear date;
  4  BEGIN
  5     lastdayofyear := TO_DATE('31-DEC-' || v_year, 'DD-MON-YYYY');
  6  END;
  7  /
   lastdayofyear := TO_DATE('31-DEC-' || v_year, 'DD-MON-YYYY');
                   *
ERROR at line 5:
ORA-01840: input value not long enough for date format
ORA-06512: at line 5

哎呀,现在怎么办?这是关于

v_year
。它是一个“局部变量”(在此 PL/SQL 块中声明),而不是您在脚本开头“接受”其值的变量。因此:将其从声明部分中删除(它是无用的)并在其前面包含&符号&字符,即使用替换变量
SQL> DECLARE
  2     lastdayofyear date;
  3  BEGIN
  4     lastdayofyear := TO_DATE('31-DEC-' || &v_year, 'DD-MON-YYYY');
  5  END;
  6  /

PL/SQL procedure successfully completed.

SQL>

对;不是,没关系,代码可以继续:

SQL> COL tourguideid FORMAT A8 HEADING "Guide ID"
SQL> COL type FORMAT A5 HEADING "Type"
SQL> ...

不过,时间不会太长,因为视图似乎使用了您在 PL/SQL 过程中计算出的值的变量:

SQL> create or replace view GetEachTourGuideMonth as (select lastdayofyear from dual);
create or replace view GetEachTourGuideMonth as (select lastdayofyear from dual)
                                                        *
ERROR at line 1:
ORA-00904: "LASTDAYOFYEAR": invalid identifier

当然不行;这在 SQL 级别是不可见的;没有用。

您可以
动态地

创建视图:

SQL> DECLARE 2 l_str varchar2(500); 3 BEGIN 4 l_str := 'create or replace view GetEachTourGuideMonth as ' || 5 q'[select TO_DATE('31.12.&v_year', 'DD.MM.YYYY') ]' || 6 ' as last_day_of_year from dual'; 7 execute immediate l_str; 8 END; 9 / PL/SQL procedure successfully completed. SQL> select * From GetEachTourGuideMonth; LAST_DAY_O ---------- 31/12/2023 SQL> 或者,在 SQL 级别,但这次使用

v_year
 并进行适当修改:

SQL> create or replace view GetEachTourGuideMonth as 2 select add_months(trunc(to_date(&v_year, 'yyyy'), 'yyyy'), 12) - 1 as last_day_of_year 3 from dual; View created. SQL> select * From GetEachTourGuideMonth; LAST_DAY_O ---------- 31/12/2023

我没有你稍后使用的表,所以我不会再调试你的代码。请注意,当您在该代码中重复使用 

v_year
 时,您必须在其前面添加&符号。但是,不仅仅是一个 - 使用其中的
两个

&&v_year
,因为 - 如果您不这样做 - 每次引用该值时都会要求您重新输入该值。不要忘记undefine v_year
初始化
它。

因此,并不是每一个琐碎的代码都像你想象的那么琐碎。如果您希望该代码正常工作,可能需要注意一些事情。
    


© www.soinside.com 2019 - 2024. All rights reserved.