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