大家好,我在PLSQL中使用iban检查器来检查用户是否填写了正确的IBAN。
我已经在Internet上查找了该函数,现在我需要插入一个触发器,但是我尝试了它却给出了错误
当用户在APEX应用程序上输入iban nummer且ibannummers错误时,触发器需要使其起作用
这是我的功能:
create or replace FUNCTION CheckIBANNUMMBER(
pIBAN IN VARCHAR2
) RETURN VARCHAR IS
lResult INTEGER;
ResulText Varchar(250);
IBAN VARCHAR2(256);
IBAN_Digits VARCHAR2(256);
l_mod NUMBER;
lTmp VARCHAR2(8);
lSCnt INTEGER := 5;
i INTEGER := 1;
---
FUNCTION fn_GetIBANDigits RETURN VARCHAR2 AS
lChar VARCHAR2(1);
lNumber INTEGER;
lString VARCHAR2(255);
BEGIN
FOR i IN 1..LENGTH(IBAN) LOOP
lChar := SUBSTR(IBAN, i, 1);
BEGIN
lNumber := ASCII(lChar);
IF lNumber > 47 AND lNumber < 58 THEN
-- It's number 0 ... 9
lString := lString || TO_CHAR(lNumber - 48);
ELSE
lString := lString || TO_CHAR(lNumber - 55);
END IF;
END;
END LOOP;
RETURN lString;
END fn_GetIBANDigits;
---
BEGIN
IBAN := SUBSTR(pIBAN, 5) || SUBSTR(pIBAN, 1, 4);
IBAN_Digits := fn_GetIBANDigits;
LOOP
lTmp := SUBSTR(IBAN_Digits, i, lSCnt);
EXIT WHEN lTmp IS NULL;
IF l_mod IS NULL THEN
l_mod := MOD( TO_NUMBER(lTmp), 97);
ELSE
l_mod := MOD(TO_NUMBER( TO_CHAR(l_mod) || lTmp), 97);
END IF;
i := i + lSCnt;
END LOOP;
IF l_mod = 1 THEN
lResult := 1;
ResulText := 'The given IBAN is correct';
ELSE
lResult := 0;
ResulText := 'The given IBAN is incorrect';
END IF;
RETURN(ResulText);
END CheckIBANNUMMBER;
这是我做的触发器
create or replace trigger "T_CHECKIBAN"
BEFORE
insert or update on "PAYMENTS"
for each row
begin
if CHECKIBAN(new.IBAN) = 0 then raise_application_error(-20500,'Wrong IBANNUMMBER');
end;
答案 0 :(得分:2)
使用虚拟列和CHECK
约束,然后您的有效性检查将在表的DDL语句中进行,而不是在另一个城堡(即触发器)中进行:
create or replace FUNCTION CheckIBANNumber(
pIBAN IN VARCHAR2
) RETURN NUMBER DETERMINISTIC
IS
lResult INTEGER;
ResulText Varchar(250);
IBAN VARCHAR2(256);
IBAN_Digits VARCHAR2(256);
l_mod NUMBER;
lTmp VARCHAR2(8);
lSCnt INTEGER := 5;
i INTEGER := 1;
---
FUNCTION fn_GetIBANDigits RETURN VARCHAR2 AS
lChar VARCHAR2(1);
lNumber INTEGER;
lString VARCHAR2(255);
BEGIN
FOR i IN 1..LENGTH(IBAN) LOOP
lChar := SUBSTR(IBAN, i, 1);
BEGIN
lNumber := ASCII(lChar);
IF lChar BETWEEN '0' AND '9' THEN
-- It's number 0 ... 9
lString := lString || lChar;
ELSIF lChar BETWEEN 'A' AND 'Z' THEN
lString := lString || TO_CHAR(ASCII(lChar) - 55);
END IF;
END;
END LOOP;
RETURN lString;
END fn_GetIBANDigits;
---
BEGIN
IBAN := SUBSTR(pIBAN, 5) || SUBSTR(pIBAN, 1, 4);
IBAN_Digits := fn_GetIBANDigits;
LOOP
lTmp := SUBSTR(IBAN_Digits, i, lSCnt);
EXIT WHEN lTmp IS NULL;
IF l_mod IS NULL THEN
l_mod := MOD( TO_NUMBER(lTmp), 97);
ELSE
l_mod := MOD(TO_NUMBER( TO_CHAR(l_mod) || lTmp), 97);
END IF;
i := i + lSCnt;
END LOOP;
IF l_mod = 1 THEN
RETURN 1;
ELSE
RETURN 0;
END IF;
END CheckIBANNumber;
/
CREATE TABLE test_data (
Country VARCHAR2(20),
IBAN VARCHAR2(50),
IBANValidity NUMBER(1) GENERATED ALWAYS AS ( CheckIBANNumber( iban ) ),
CONSTRAINT IsValidIBAN CHECK ( IBANValidity = 1 )
);
然后(使用维基百科的测试数据):
INSERT INTO test_data ( Country, IBAN ) VALUES ( 'Belgium', 'BE71 0961 2345 6769' );
INSERT INTO test_data ( Country, IBAN ) VALUES ( 'France', 'FR76 3000 6000 0112 3456 7890 189' );
INSERT INTO test_data ( Country, IBAN ) VALUES ( 'Germany', 'DE91 1000 0000 0123 4567 89' );
INSERT INTO test_data ( Country, IBAN ) VALUES ( 'Greece', 'GR96 0810 0010 0000 0123 4567 890' );
INSERT INTO test_data ( Country, IBAN ) VALUES ( 'Romania', 'RO09 BCYP 0000 0012 3456 7890' );
INSERT INTO test_data ( Country, IBAN ) VALUES ( 'Saudi Arabia', 'SA44 2000 0001 2345 6789 1234' );
INSERT INTO test_data ( Country, IBAN ) VALUES ( 'Spain', 'ES79 2100 0813 6101 2345 6789' );
INSERT INTO test_data ( Country, IBAN ) VALUES ( 'Switzerland', 'CH56 0483 5012 3456 7800 9' );
INSERT INTO test_data ( Country, IBAN ) VALUES ( 'United Kingdom', 'GB98 MIDL 0700 9312 3456 78' );
成功,并且:
SELECT * FROM test_data;
输出:
COUNTRY | IBAN | IBANVALIDITY :------------- | :-------------------------------- | -----------: Belgium | BE71 0961 2345 6769 | 1 France | FR76 3000 6000 0112 3456 7890 189 | 1 Germany | DE91 1000 0000 0123 4567 89 | 1 Greece | GR96 0810 0010 0000 0123 4567 890 | 1 Romania | RO09 BCYP 0000 0012 3456 7890 | 1 Saudi Arabia | SA44 2000 0001 2345 6789 1234 | 1 Spain | ES79 2100 0813 6101 2345 6789 | 1 Switzerland | CH56 0483 5012 3456 7800 9 | 1 United Kingdom | GB98 MIDL 0700 9312 3456 78 | 1
db <>提琴here
答案 1 :(得分:0)
您的代码,已编辑:
CREATE OR REPLACE TRIGGER T_CHECKIBAN
BEFORE INSERT OR UPDATE
ON PAYMENTS
FOR EACH ROW
BEGIN
IF CheckIBANNUMMBER(:new.IBAN) = 0 /* new --> :new, CHECKIBAN -- > CheckIBANNUMMBER*/
THEN
raise_application_error(-20500, 'Wrong IBANNUMMBER');
END IF; /* added END IF */
END;
我删除了双引号,因为只有在要使用小写字符时才需要双引号。
还要注意,您的函数给出了ResulText
,而它似乎应该返回lResult
;甚至,您正在使用varchar2
返回值来处理数字。
如果只希望此功能检查IBAN是否正确,则应按以下方式编辑功能(ResulText
在这里无效):
create or replace FUNCTION CheckIBANNUMMBER(
pIBAN IN VARCHAR2
) RETURN number IS /* return a number */
...
RETURN(lResult); /* return 0/1 */
END CheckIBANNUMMBER;