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;
这些是代码。这个文件正在计算每个导游的工资,总体利润还可以。但是这个文件有无限输入的问题...
那是因为您在 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
来初始化它。 因此,并不是每一个琐碎的代码都像你想象的那么琐碎。如果您希望该代码正常工作,可能需要注意一些事情。