2016-02-23 51 views
0

好的,所以我知道基於兩個連接表插入信息在視圖是不可能的。SQL - 如何創建用於插入的兩個連接表的觸發器

爲了做到這一點,我需要創建一個觸發器,在兩個表中插入信息,當在該視圖中插入信息時。

例如:

CREATE VIEW myJoinedView AS 
SELECT name,g.value from students 
JOIN grades g on g.id=students.id; 

觸發不工作:

CREATE TRIGGER myTrigger 
INSTEAD OF INSERT ON myJoinedView 
BEGIN 
    INSERT INTO students 
    (name,value) 
    SELECT i.myJoinedView 
    FROM inserted i 
    INNER JOIN grades 
    ON i.id = grades.id 
END myTrigger; 

然後我試圖插入:

INSERT INTO myJoinedView VALUES ('Alex',10); 

我不知道如果語法是正確的,我沒有找到有關這種特定類型的觸發器的任何有用的文檔。

我得到這個錯誤:

Error(10,46): PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following: (begin case declare end exception exit for goto if loop mod null pragma raise return select update while with
<< continue close current delete fetch lock
insert open rollback savepoint set sql execute commit forall merge pipe purge

任何幫助將備受矚目。 謝謝!

+0

讓我們退後一步。當你運行這個'insert'語句時你想要發生什麼?你是否總是想在「學生」表中插入一個新的行? 'name'是'學生'的主鍵嗎?或者'id'是主鍵?如果你插入一個新行,你如何填充'id'的新值?有序嗎?或者,如果只有沒有匹配「name」的行,纔想在'students'中插入新行?據推測,你可以有多名學生命名爲「亞歷克斯」,每個學生可以有多個成績...... –

+0

id是兩個表的主鍵;不,我只是想爲他們每一個創造一個新的行:在學生表中,我將有一個新的名字亞歷克斯,並在分數我會有亞歷克斯的成績;是的,我認爲我犯了一個錯誤,我應該插入ID以及但我仍然不知道我將如何解決這個 – Lazai

+0

好。那麼每個學生只能有一個年級?從商業角度看,這似乎很奇怪,但確定。觸發器如何知道要使用的「id」值?是否有序列可以調用'nextval'來獲取新的主鍵值?任何表格中是否有任何其他列需要填充? –

回答

0

您需要分別使用單獨的單表插入或合併語句或使用多表插入(insert all)語句執行插入。假設你有一個序列生成你是加盟的,例如該代碼將在一個非常簡陋的方式工作的ID,但有一些顯著的問題:

create table students (id number primary key 
         , name varchar2(60)); 

create table grades(id number not null 
        , value number 
        , constraint grades_fk1 foreign key (id) references students(id)); 

create sequence student_id_seq; 

create or replace view studentgrades as 
select name, value from students s join grades g on s.id = g.id; 

create or replace trigger studentgrades_ii_trg 
instead of insert on studentgrades 
begin 
    insert all into students(id, name) values (student_id_seq.nextval, name) 
      into grades(id, value) values (student_id_seq.nextval, value) 
     select :new.name name, :new.value value from dual; 
end; 
/

insert into studentgrades values ('Alex',10); 
insert into studentgrades values ('Alex',8); 

BIG問題與上面的觸發是,每時間爲'Alex'插入一個等級時,'Alex'的新學生記錄也被創建,而不是將以前的學生記錄用於'Alex'。這可能不是期望的行爲。相反,它應該只是爲Alex插入一個新的成績記錄。要達致這一個方法是爲studentgrades查看包括從學生表中的id列,因此您可以唯一地識別哪個學生添加檔次,更新觸發需要:

create or replace view studentgrades as 
select s.id, name, value from students s join grades g on s.id = g.id; 

create or replace trigger studentgrades_ii_trg 
instead of insert on studentgrades 
declare 
    newid students.id%type; 
begin 
    if :new.id is null then 
    newid := student_id_seq.nextval; 
    else 
    newid := :new.id; 
    end if; 
    insert all when :new.id is null 
      then into students(id, name) values (id, name) 
      else into grades(id, value) values (id, value) 
     select newid id, :new.name name, :new.value value from dual; 
end; 
/

insert into studentgrades values (null, 'Paul',10); 
insert into studentgrades values (student_id_seq.currval, 'Paul',8); 

不過,現在發生了什麼如果你試試這個:

insert into studentgrades values (student_id_seq.currval, 'Mary',10); 

在這種情況下,名字被有效忽略,保羅再次這樣得到一個新的檔次,這是不完全正確。問題是保羅的名字應該更新爲瑪麗,還是應該爲瑪麗創建新的學生記錄,或者是否應該提出例外情況?

相關問題