【发布时间】:2019-02-22 13:38:28
【问题描述】:
我有存储过程和函数,我在 ORACLE 的存储过程中调用函数。函数 CalculateIncomeTax 是给我错误的原因。在 MSSQL 中,这种类型的更新是可能的,因为我以前做过。我在存储过程中调用了该函数。当我阅读答案时,我得到的答案是在我不能使用函数从另一个表更新表之前使用包。如果你有任何想法,请告诉我.我得到的错误是
table string.string 正在变异,触发器/函数可能看不到它 原因:触发器(或此语句中引用的用户定义的 plsql 函数)试图查看(或修改)正在被触发它的语句修改的表。 行动:重写触发器(或函数),使其不读取该表。
这是函数
CREATE OR REPLACE function CalculateIncomeTax(periodId NVARCHAR2,
employeeId NVARCHAR2, taxableIncome NUMBER)return NUMBER
AS
IncomeTax NUMBER (18,4);Taxable NUMBER(18,4);
BEGIN
SELECT SUM(CASE WHEN (taxableIncome > T.TAX_CUMMULATIVE_AMOUNT)
THEN (taxableIncome - T.TAX_CUMMULATIVE_AMOUNT)* T.TAX_PERCENTAGE/ 100
ELSE 0.00 END ) INTO IncomeTax
FROM TAX_LAW T JOIN PAY_GROUP P ON P.PAY_FORMULA_ID =T.TAX_FORMULA_ID
JOIN PAYROLL_MASTER PP ON P.PAY_CODE =PP.PAY_PAY_GROUP_CODE
WHERE PP.PAY_EMPLOYEE_ID = employeeId AND PP.PAY_PERIOD_CODE = periodId;
if IncomeTax IS NULL THEN IncomeTax :=0;
end if;
return IncomeTax;
end;/
这是存储过程
CREATE OR REPLACE PROCEDURE PROCESSPAYROLLMASTER (periodcode
VARCHAR2) AS BEGIN
INSERT INTO PAYROLL_MASTER
(
PAY_PAYROLL_ID,PAY_EMPLOYEE_ID ,PAY_EMPLOYEE_NAME,PAY_SALARY_GRADE_CODE
,PAY_SALARY_NOTCH_CODE,PAY_BASIC_SALARY,PAY_TOTAL_ALLOWANCE
,PAY_TOTAL_CASH_BENEFIT,PAY_MEDICAL_BENEFIT,PAY_TOTAL_BENEFIT
,PAY_TOTAL_DEDUCTION,PAY_GROSS_SALARY,PAY_TOTAL_TAXABLE,PAY_INCOME_TAX
,PAY_TAXABLE,PAY_PERIOD_CODE,PAY_BANK_CODE,PAY_BANK_NAME,PAY_BANK_ACCOUNT_NO
,PAY_PAY_GROUP_CODE )
SELECT
1,
E.EMP_ID AS PAY_EMPLOYEE_ID ,
E.EMP_FIRST_NAME || ' ' || E.EMP_LAST_NAME AS PAY_EMPLOYEE_NAME,
E.EMP_RANK_CODE,
'CODE',
(SC.SAL_MINIMUM_AMOUNT+( SN.SAL_SALARY_PERCENTAGE *
SC.SAL_MINIMUM_AMOUNT)/100) AS PAY_BASIC_SALARY,
0,
0,
0,
0,
0,
0,
0,
0,
0,
periodcode,
'BANKCODE',
'BANKNAME',
'BANKNUMBER',
'GENERAL'
FROM EMPLOYEE E
LEFT JOIN SALARY_SCALE SC ON SC.SAL_RANK_CODE = E.EMP_RANK_CODE
LEFT JOIN SALARY_NOTCH SN ON SC.SAL_ID = SN.SAL_SALARYSCALE_ID
WHERE E.EMP_RANK_CODE = SC.SAL_RANK_CODE AND E.EMP_STATUS=2;
CALCULATEALLOWANCE(v_payrollId,periodcode);
CALCULATECASHBENEFITS(v_payrollId,periodcode);
CALCULATEDEDUCTIONS(v_payrollId,periodcode);
-- UPDATE PAYROLL PAY_INCOME_TAX
UPDATE PAYROLL_MASTER PM SET PM.PAY_INCOME_TAX = CalculateIncomeTax(PM.PAY_PERIOD_CODE,PM.PAY_EMPLOYEE_ID,PM.PAY_TOTAL_TAXABLE) WHERE PM.PAY_PAYROLL_ID = v_payrollId;
UPDATE PAYROLL_PROCESS set PAY_CANCELLED = 1 WHERE PAY_PAY_GROUP_CODE='GENERAL' AND PAY_PERIOD_CODE=periodcode
AND PAY_ID<>v_payrollId;
COMMIT;
END ;
/
【问题讨论】:
-
我在两张表上没有任何触发器,只有表ID是主键
-
CREATE OR REPLACE TRIGGER TR_PAYROLL_MASTER before insert on "SIBAHR"."PAYROLL_MASTER" 为每一行开始选择 "SIBAHR"."SQ_PAYROLL_MASTER".nextval 到 :new."PAY_ID" from dual;结尾; /
-
我正在使用该函数计算所得税,它需要存储过程中已经定义的三个参数。之后它将更新数据库中的指定列。
-
你不需要触发器,一个函数可能会导致错误。您正在使用查询该表的函数调用更新
payroll_master表。最简单的方法是重写insert...select以包含其他表并一次计算所有字段值,完全避免使用该函数。 -
同样的查询在 MSSQL Server 中运行没有任何问题,为什么 Oracle 给我一个错误。我正在从另一个表中挑选数据,使用这些值进行计算。老实说,我不知道该怎么做你的建议
标签: function stored-procedures oracle11g