oracle PL/SQL触发器,如果名称太相似,则不允许插入

holgip5t  于 2023-10-16  发布在  Oracle
关注(0)|答案(1)|浏览(130)

我一直在尝试在PL/SQL中创建一个触发器,如果名称与数据库中已经存在的其他名称太相似,则不允许新插入,但我一直在努力创建这个触发器(在插入中,即使名称非常相似,它也不会做任何事情),有什么想法吗?
代码:

CREATE OR REPLACE TRIGGER similaridade
BEFORE INSERT ON pessoa
FOR EACH ROW
DECLARE
    similaridade_c NUMBER;
BEGIN
    SELECT COUNT(*) INTO similaridade_c
    FROM pessoa
    WHERE SIMILARITY(:NEW.nome, nome) > 0.92;
    
    IF similaridade_c > 0 THEN
        RAISE_APPLICATION_ERROR(-20001, 'Esse nome já existe');
    END IF;
END;
sigwle7e

sigwle7e1#

除非你有一个名为SIMILARITY的用户定义函数,否则这个函数不存在。您可能需要UTL_MATCH包中的一个函数:

CREATE OR REPLACE TRIGGER similaridade
BEFORE INSERT ON pessoa
FOR EACH ROW
DECLARE
    similaridade_c NUMBER;
BEGIN
    SELECT COUNT(*) INTO similaridade_c
    FROM   pessoa
    WHERE  UTL_MATCH.EDIT_DISTANCE_SIMILARITY(:NEW.nome, nome) > 0.92;
    
    IF similaridade_c > 0 THEN
        RAISE_APPLICATION_ERROR(-20001, 'Esse nome já existe');
    END IF;
END;
/

如果你有table:

CREATE TABLE pessoa (nome) AS
SELECT 'Anna' FROM DUAL;

然后插入:

INSERT INTO pessoa (nome) VALUES ('Anya');

然后你得到错误:

ORA-20001: Esse nome já existe
ORA-06512: at "FIDDLE_DOZWTHWYHQKNLDOVFQZI.SIMILARIDADE", line 9
ORA-04088: error during execution of trigger 'FIDDLE_DOZWTHWYHQKNLDOVFQZI.SIMILARIDADE'

fiddle
要修复插入多行时发生的可变表异常,可以改为使用AFTER INSERT语句级触发器:

CREATE OR REPLACE TRIGGER similaridade
AFTER INSERT ON pessoa
DECLARE
    similaridade_c NUMBER;
BEGIN
    SELECT 1
    INTO   similaridade_c
    FROM   DUAL
    WHERE  NOT EXISTS(
             SELECT 1
             FROM   pessoa p
                    INNER JOIN pessoa s
                    ON  p.ROWID < s.ROWID
                    AND UTL_MATCH.EDIT_DISTANCE_SIMILARITY(p.nome, s.nome) > 0.92
           );
EXCEPTION
  WHEN NO_DATA_FOUND THEN
    RAISE_APPLICATION_ERROR(-20001, 'Esse nome já existe');
END;
/

或者,您可以使用复合触发器来只检查插入行的相似性,而不是检查整个表(但这是留给读者实现的练习)。
fiddle

相关问题