Используйте виртуальный столбец и ограничение 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
дБ <> скрипка здесь