觸發器(六、instead of觸發器實現檢視增刪改)
場景描述
開發中遇到一個情況:前臺頁面是一個角色對使用者的批量授權,其中使用者是多選,多選的結果是控制元件裡會填入逗號分隔的使用者ID字串,比如“TOM,JERRY”,最終要分別插入2張一對多的主從表中。
--主表
CREATE TABLE T_MAIN
(GUID VARCHAR2(32) primary key
,GRANTOR VARCHAR2(30)
,ROLEID VARCHAR2(10)
,CREATED DATE
);
--從表
CREATE TABLE T_DETAIL
(GUID VARCHAR2(32)
,GRANTEE VARCHAR2(32)
,ROLEID VARCHAR2(10 )
);
--前臺展示的的是一個檢視:
CREATE OR REPLACE VIEW V_MAIN_DETAIL AS
SELECT A.GUID,A.GRANTOR,A.ROLEID,A.CREATED,TO_CHAR(WM_CONCAT(B.GRANTEE)) GRANTEES
FROM T_MAIN A,T_DETAIL B
WHERE A.GUID=B.GUID
GROUP BY A.GUID,A.GRANTOR,A.ROLEID,A.CREATED;
前臺實現的做法是在主表中插入資料,然後對使用者多選結果進行迴圈插入從表。
今天介紹一種後臺實現的方式,即前臺只需對檢視進行增刪改查。
大家知道,Oracle裡的檢視是不能做DML操作的,儘快Oracle做了很多改進,比如對單表檢視或一對一鍵值關聯的多表檢視可以做增刪改。但一對多或者多對多關聯的檢視還是不支援增刪改操作,會報錯ORA-01779: cannot modify a column which maps to a non key-preserved table
事實上,Oracle還提供一個變通方式來完成對檢視的增刪改操作。就是用instead of觸發器。
INSTEAD OF INSERT 實現檢視新增操作
以下對檢視進行insert操作的觸發器實現。
CREATE OR REPLACE TRIGGER TRI_V_MAIN_DETAIL
INSTEAD OF INSERT
ON V_MAIN_DETAIL
DECLARE
--分解用分隔符分隔的字串
cursor cur_GRANTEE(v_GRANTEE varchar2,v_deli varchar2) is
select substr(t.ca,instr(t.ca,v_deli,1,c.lv)+1,instr(t.ca,v_deli,1,c.lv+1)-(instr(t.ca,v_deli,1,c.lv)+1)) as GRANTEE
from (select v_deli||v_GRANTEE||v_deli as ca,length(v_deli||v_GRANTEE||v_deli)-nvl(length(replace(v_deli||v_GRANTEE||v_deli,v_deli)),0)-1 as cnt from dual) t,
(select level lv from dual connect by level<=200) c
where c.lv<=t.cnt;
v_guid varchar2(32);
BEGIN
if :new.GRANTEES is null then
raise_application_error(-20000,'沒有選擇被授權使用者!');
else
select sys_guid() into v_guid
from dual;
--插入主表資料1條
insert into T_MAIN(GUID,
GRANTOR,
ROLEID,
CREATED)
values(v_guid,:new.grantor,:new.roleid,sysdate);
--插入從表資料N條
for rec_GRANTEE in cur_GRANTEE(:new.GRANTEES,',') loop
insert into t_detail(guid,
grantee,
roleid)
values(v_guid,rec_grantee.GRANTEE,:new.roleid);
end loop;
end if;
end;
再試一下INSERT操作,對檢視插入1條資料,結果在T_MAIN插入1條資料,在T_DETAIL插入了2條資料。
從上面我們大致可以看出來,INSTEAD OF INSERT觸發器的原理實際上是捕捉到對檢視的INSERT動作,然後用觸發器的程式替換該insert操作。
INSTEAD OF UPDATE實現檢視更新操作
同理,我們可以對檢視進行update和delete操作,以下是update的觸發器實現。
CREATE OR REPLACE TRIGGER TRI_V_MAIN_DETAIL_UPD
INSTEAD OF UPDATE
ON V_MAIN_DETAIL
DECLARE
--分解用分隔符分隔的字串
cursor cur_GRANTEE(v_GRANTEE varchar2,v_deli varchar2) is
select substr(t.ca,instr(t.ca,v_deli,1,c.lv)+1,instr(t.ca,v_deli,1,c.lv+1)-(instr(t.ca,v_deli,1,c.lv)+1)) as GRANTEE
from (select v_deli||v_GRANTEE||v_deli as ca,length(v_deli||v_GRANTEE||v_deli)-nvl(length(replace(v_deli||v_GRANTEE||v_deli,v_deli)),0)-1 as cnt from dual) t,
(select level lv from dual connect by level<=200) c
where c.lv<=t.cnt;
BEGIN
--更新主表資料
UPDATE T_MAIN T SET
GRANTOR=:NEW.GRANTOR,ROLEID=:NEW.ROLEID,CREATED=SYSDATE
WHERE GUID=:NEW.GUID;
if :new.GRANTEES!=:OLD.GRANTEES then
--重新插入從表資料N條
delete from t_detail where guid=:new.GUID;
for rec_GRANTEE in cur_GRANTEE(:new.GRANTEES,',') loop
insert into t_detail(guid,
grantee,
roleid)
values(v_guid,rec_grantee.GRANTEE,:new.roleid);
end loop;
end if;
end;
執行效果如下
INSTEAD OF DELETE 實現檢視刪除操作
檢視delete觸發器的實現如下:
CREATE OR REPLACE TRIGGER TRI_V_MAIN_DETAIL_DEL
INSTEAD OF DELETE
ON V_MAIN_DETAIL
DECLARE
BEGIN
--刪除從表資料
DELETE FROM T_DETAIL T WHERE GUID=:OLD.GUID;
--刪除主表資料
DELETE FROM T_MAIN T WHERE GUID=:OLD.GUID;
end;
執行效果如下:
總結
儘管INSTEAD OF觸發器比較好的實現了檢視的增刪改操作,
但我還是不提倡經常使用這種方式來處理真實業務,
原因是:業務邏輯被觸發器的程式碼輕易改變了。
比如上面的案例中,假設前臺使用者選擇的是DBA許可權,而在觸發器中完全可以被篡改成SYSDBA許可權,或者執行一堆其他的操作。很容易引起前臺人員和後臺人員對於業務邏輯實現的混亂。
相關推薦
觸發器(六、instead of觸發器實現檢視增刪改)
場景描述 開發中遇到一個情況:前臺頁面是一個角色對使用者的批量授權,其中使用者是多選,多選的結果是控制元件裡會填入逗號分隔的使用者ID字串,比如“TOM,JERRY”,最終要分別插入2張一對多的主從表中。 --主表 CREATE TABLE T_MAIN (
使用Spring、Struts2、Hibernate三大框架實現使用者增刪改查
這就是SSH框架內容很多,隨著下面一個案例來進入分析: 1 首先專案是依賴maven進行管理的,建立一個動態的web專案 2 在pom.xml匯入相關jar包,配置如下: <project xmlns="http://maven.apache.org/POM/4.
【SQL觸發器】型別 FOR 、AFTER、 Instead of到底是什麼鬼
前言: 上一篇部落格講述了觸發器的基本概念,觸發器什麼時候用,為什麼用!這篇部落格將簡述觸發器的型別,由於FOR觸發器與AFTER觸發器是一個作用,所以觸發器分為AFTER觸發器,與Instead of 觸發器! 為了讓大家明白觸發器,我先把我的資料庫是幹嘛的給
PL/SQL --> INSTEAD OF 觸發器
--============================== -- PL/SQL --> INSTEAD OF 觸發器 --============================== IN
如何使用SQL Server INSTEAD-OF觸發器
觸發器是類似於儲存程式的資料庫物件,它響應資料庫環境下的某個請求。SQL Sever 2005包含3個觸發器物件:AFTER,資料定義語言 (DDL)和INSTEAD-OF。 AFTER觸發器是儲存程式,它發生於資料操作語句作用之後,例如刪除語句等。DDL是SQL Server 2005的新觸發器,允許響
觸發器(二、BEFORE和AFTER的區別及使用場景)
DML操作的行級觸發器,分為before和after兩類。比如下面在同一張表上分別建了2個觸發器然後用一個insert語句進行觸發結果發現,這2類觸發器捕捉的:OLD和:NEW資料實際是一樣的。那麼什麼時候用before,什麼時候用after呢?我們先要知道這2種觸發器的特性
Java (六、String類和StringBuffer)
image 存在 equal 分享 buffer 大寫 移除 能夠 nal Java String 類 字符串廣泛應用 在Java 編程中,在 Java 中字符串屬於對象,Java 提供了 String 類來創建和操作字符串。 創建字符串 // ==比
線性規劃中的單純形法與內點法(原理、步驟以及matlab實現)(三)
應用 最大化 round 並不是 兩個 生產 陰影 3.3 ima 在本系列的第三篇博客中,筆者討論對偶單純形法的相關理論和應用 2.3 Dual Simplex Method(對偶單純形法) Contents 2.3.1 對偶問題產生的原因 2.3.2 對偶問題的
Java編程思想(六、訪問權限控制)
而不是 包含 得到 獲取 開發 變量 平臺 世界 類的繼承 訪問控制(或隱藏具體實現)與“最初的實現並不恰當”有關。便於未來重構代碼,而不必對業務層做過多的改變。因此,Java提供了訪問控制修飾詞,以供類庫開發人員向客戶端程序員指明哪些是可用的,哪些是不可用的。 訪
移植u-boot.2016.09 ——(六、制作補丁、打補丁)
mini2440 style mic 移植 打補丁 spa ont microsoft ini 制作補丁: 制作補丁: diff -urN u-boot-2016.09 u-boot-2016.09_mini2440 > u-boot-2016.09_patch 打補
WPF觸發器(非資料庫中的觸發器)
原文: WPF觸發器(非資料庫中的觸發器) 一、什麼是觸發器?觸發器(Trigger)就是當某種條件滿足後即完成相應邏輯功能的一部分程式組成。在當前的WPF中,Trigger一共有三種類型,它們分別是: (1)屬性觸發器:其對應的類是Trigger。它在特定關聯屬性發生變化時被觸發。 (2)資料
spring cloud(六、rabbitmq)
用Spring Cloud Bus實現通知微服務架構的配置檔案的更改 1.安裝好rabbitMq並啟動 2.修改config-client專案,引入spring-cloud-starter-bus-amqp和spring-boot-starter-actuator依賴 3.修改boots
PostScript語言教程(六、坐標變換)
默認 物理 長度 wpa class 根據 然而 time 都是 6.1、坐標系變換 POSTSCRIPT圖形操作是在一個坐標系中,這個坐標系被稱為用戶坐標系或用戶空間,該坐標系獨立於任何物理設備。POSTSCRIPT在用戶空間中進行繪制,並將結果傳輸到特定的打印機設備(
Hadoop學習記錄(六、MapReduce測試)
1.MRUnit進行單元測試 加入依賴 <dependency> <groupId>org.apache.mrunit</groupId> <artifactId>mrunit&l
前端視訊學習(六、JavaScript高階)
目錄 0. 複習 基本型別(值型別) 複雜型別(引用型別) 型別檢測 JavaScript 執行過程 1. 物件 1.1 建立物件的方法
ES6語法筆記(Iterator、for...of、Generator、async)
**以下內容均摘自ECMAScript 6 入門——阮一峰 一、Iterator 遍歷器(Iterator)是一種介面,為各種不同的資料結構提供統一的訪問機制。任何資料結構只要部署 Iterator 介面,就可以完成遍歷操作。 Iterator 的作用有三個:一是為各種資料結構,提供一個統一的、簡便的訪
從零開始之驅動發開、linux驅動(三十六、linux中common clock framework[1]_consoumer)
部分內容來自下面幾位博主的文章,如有侵權,聯絡我刪除。 時鐘管理模組是linux系統為統一管理各硬體的時鐘而實現管理框架,負責所有模組的時鐘調節和電源管理。時鐘管理模組主要負責處理各硬體模組的工作頻率調節及電源切換管理。一個硬體模組要正常工作,必須先配置好硬體的
從零開始學USB(六、USB通訊的資料格式)
USB中用NRZI來編碼資料 前面章節已經學習過了USB的引腳定義了,但是對於其中的USB 2.0的兩根資料線D+和D-所對應的資料傳輸,卻沒有詳細介紹。此處就是介紹,在此序列資料線中,資料是如何被編碼和傳送的。 USB所傳輸的資料,用的資料編碼方式是NRZI(Non-Return-to
STL深入探究(二、容器的底層實現)
1 前言 上一篇 STL深入探究(一、空間配置器)我詳細總結了SGI STL採用的空間配置機制,這一篇來總結一下stl容器的底層實現機制。 2 序列式容器 2.1 Vector Vector實現方式類似於“陣列”,與array的資料安排和操作方式非常類似,兩者唯一的差
spark學習記錄(六、基礎知識)
1.術語解釋 2.SparkCore和SparkSQL知識點思維導圖整理 https://download.csdn.net/download/qq_33283652/10890863 3.RDD的寬窄依賴 相同的key去同一個分割槽,但一個分割槽可以用不同的key