1
因此,我正在尝试编写一个Oracle触发器,它将插入到一个表中,其中给定的值是另一个表中外键的错误名称。因此,触发器需要将该值更改为正确的名称,而不是给定的名称。Oracle PL/SQL触发器 - 用错误名称捕获插入
我的数据库表是建立像这样:
SIGHTINGS (NAME, PERSON, LOCATION, SIGHTED)
FEATURES (LOCATION, CLASS, LATITUDE, LONGITUDE, MAP, ELEV)
FLOWERS (GENUS, SPECIES, COMNAME)
该表具有以下语义:
- 目击给出描述每一次信息,该俱乐部的成员观察野花之一在表格中描述。 NAME告诉观察到的花的名字,PERSON描述谁看到了这朵花,LOCATION告诉附近地理特征的名字,花的位置被看到,SIGHTED告诉花被看到的那一天。
- FLOWERS列出了俱乐部成员试图找到的所有鲜花。属和种给学名花,和COMNAME给出了非学名(SIGHTING.NAME是一个外键FLOWER.COMNAME)
我试图建立映入插入到触发SIGHTINGS表格,当用户不小心插入花朵的科学名称而不是通用名称时。例如,他们可以使用:
INSERT INTO SIGHTINGS VALUES
('Chaenactis douglasii', 'Person A', 'Shirley Peak', TO_DATE('18-Aug-06', 'DD-MON-YY'));
相反的:
INSERT INTO SIGHTINGS VALUES
('Douglas dustymaiden', 'Person A', 'Shirley Peak', TO_DATE('18-Aug-06', 'DD-MON-YY'));
我想触发捕获这个问题,并显示一条警告消息到屏幕上,然后插入通用名称到数据库,而不是拉丁名字。
我的代码看起来像这样:
CREATE OR REPLACE TRIGGER Used_Latin_Name
BEFORE INSERT ON SIGHTINGS
FOR EACH ROW
WHEN (NEW.NAME IS NOT NULL)
DECLARE
-- local variables
inserted_name VARCHAR2(30);
comm_name VARCHAR2(30);
Invalid_name EXCEPTION;
Valid_name EXCEPTION;
-- local cursor
CURSOR c (name_in VARCHAR2) IS
SELECT COMNAME
FROM FLOWERS
WHERE COMNAME = name_in;
BEGIN
-- open cursor and fetch a match
OPEN c(:NEW.NAME);
FETCH c INTO inserted_name;
CLOSE c;
-- Raise an exception when foreign key is invalid
IF inserted_name IS NULL THEN
RAISE Invalid_name;
ELSE
RAISE Valid_name;
END IF;
EXCEPTION
WHEN Invalid_name THEN
CREATE INDEX genusindex on FLOWERS(GENUS)
indextype is ctxsys.ctxrule;
SELECT COMNAME FROM FLOWERS
INTO comm_name
WHERE matches(GENUS, :NEW.NAME) > 0;
DROP INDEX genusindex;
DBMS_OUTPUT.PUT_LINE ('Warning: Your insert into the SIGHTINGS table seemed to use the Latin name "' || :NEW.NAME || '" for the flower "' || comm_name '". I used the common name instead.');
WHEN Valid_name
NULL;
END;
/
我得到一个错误,虽然你不能创造一个我创建的索引的索引,所以我想知道是否有另一种办法,而不是做其他我正在做的方式,或者如果有其他地方我想插入索引。我到处寻找帮助,并没有运气找出答案。
请仅用您实际使用的数据库标记您的问题。 –
首先,您不能在触发器中创建索引。其次,你不会想。创建索引,特别是Oracle文本索引是一个缓慢的操作。创建索引只是为了稍后放下索引是没有意义的。第三,你是否真的需要一个Oracle Text索引来做你想要的查询,而不仅仅是拥有一个标准索引并进行直接的相等检查?第四,如果你真的有外键约束,那么在触发器触发前可能会违反这个约束。第五,这可能不是应该在触发器中完成的事情,它属于应用程序。 –
你的解决方案中有更多的问题 - 如果'从'FLOWERS INTO comm_name WHERE匹配(GENUS,:NEW。NAME)> 0;'返回多行,你会得到一个错误。另一个问题 - “DBMS_OUTPUT”通常用于调试,而不是将消息打印给用户。如果你在生产代码中使用它,你迟早会得到'ORA-20000 DBMS buffer overlow'。 – krokodilko