本文基于Kingbase和SqlServer的INSTEAD OF 触发器主要功能特点进行对比浅析,同时针对SqlServer 的INSTEAD OF 触发器提出了多种kingbase环境的等价代码方案。

一,SqlServer 的INSTEAD OF 触发器

它通常用来替换触发动作的。

1,其中一个显著特点是他的作用对象通常是一张表

2,当在表上定义了INSTEAD OF触发器后,如果对表做insert、update、delete操作时触发了所定义的触发器,会直接转到触发器去执行触发器里定义的事件,不再执行之前的DML操作。触发语句更像是一个“导火索”而已,不会真正生效,真正起作用的是触发器体内的动作。

SqlServer的INSTEAD OF触发器一种典型的使用示例:

简单应用案例1


drop table t1;
drop trigger t1_trriger;`` create table t1 (c1 int,c2 int);
insert into t1 values (1,2);
insert into t1 values (3,5); create trigger t1_trriger on t1 instead of --用于在表t1上插入数据时对数据进行修正
insert
as
begin
if exists(select 1 from inserted)
and (select c1 from inserted) = 0
begin
insert into dbo.t1(c1,c2) select -1,c2 from inserted; ---对值进行修正
end
else begin
insert into dbo.t1(c1,c2) select c1,c2 from inserted;
end
end; insert into t1 values (0,6);
select * from t1;
--结果
-1 6 --可以看到值被修正了,原语句未生效
1 2
3 5 insert into t1 values (1,16);
select * from t1;
--结果
-1 6
1 2
3 5
1 16 --无需修正

从上面的代码可以看出,sqlserver可以是insert语句进行触发,同时在触发器体内对其进行insert操作,不会产生无限死循环,起到的是真正的“替换”操作。

二,KingbaseES 的INSTEAD OF 触发器

1,INSTEAD OF 触发器不能直接作用于表,

如果作用于表t1就会产生如下报错:

ERROR: "t1" is a table

DETAIL: Tables cannot have INSTEAD OF triggers.

通常作用于视图,视图本质上不是可更新的。

INSTEAD OF 触发器是建立在不可编辑的视图上或不可编辑视图的嵌套表列上的DML触发器。

2,INSTEAD OF触发器是用触发器体的执行代替触发语句的执行

即触发语句本身不执行,从这里来看和SqlServer的作用一样,只是不能直接作用于表。

KES的INSTEAD OF触发器一种简单的使用示例:

简单应用案例2


drop table t1;
drop view t1_id_info;
create table t1(c1 int ,c2 int);
insert into t1 values(10,11);
insert into t1 values(20,22);
create or replace view t1_id_info as select * from t1; create trigger t1_trriger
instead of
insert on t1_id_info
for each row
as
begin
if inserting and :new.c1 = 0 then
insert into t1 values(-1,:new.c2); ---对值进行修正
else
insert into t1 values(:new.c1,:new.c2);
end if;
end; insert into t1_id_info values(12,5);
test=# select * from t1_id_info;
test-# /
c1 | c2
----+----
10 | 11
20 | 22
12 | 5
(3 rows) insert into t1_id_info values(0,5); test=# select * from t1_id_info;
test-# /
c1 | c2
----+----
10 | 11
20 | 22
12 | 5
-1 | 5
(4 rows)

三,SqlServer的INSTEAD OF触发器等价改写思考

以简单案例1为例,如果想把sqlserver中的instead of触发器通过KingbaseES的PLSQL中触发器等价改写,如何改写呢?

1,案例2本身就是案例1的一种改写方案,

当然也可以考虑其他改写方案。如下

2,before条件的DML触发改写方案

从字面理解,before 触发器是在触发操作完成之前执行,显然,before触发器(针对insert和update操作)可以修改NEW的值。

-----------before DML trigger 1(即作用于表t1又在触发体对t1进行insert插入,会形成死循环触发)

create trigger t1_trriger
before insert on t1
as
begin
if inserting and :new.c1 = 0 then
insert into t1 values(-1,:new.c2); ---对值进行修正
else
insert into t1 values(:new.c1,:new.c2);
end if;
end;

这样写肯定不可以,会形成递归,无限循环下去,最终达到stack depth限制。


test=# insert into t1_id_info values(0,5);
test-# /
ERROR: stack depth limit exceeded
HINT: Increase the configuration parameter "max_stack_depth" (currently 2048kB), after ensuring the platforms stack depth limit is adequate.
CONTEXT: SQL statement "SELECT inserting and :new.c1 = 0"
PL/SQL function t1_trriger_1680177824() line 3 at IF
SQL statement "insert into t1 values(:new.c1,:new.c2)"
PL/SQL function t1_trriger_1680177824() line 6 at SQL statement
SQL statement "insert into t1 values(:new.c1,:new.c2)"
PL/SQL function t1_trriger_1680177824() line 6 at SQL statement
。。。。。。。。。(略)
SQL statement "insert into t1 values(:new.c1,:new.c2)"
PL/SQL function t1_trriger_1680177824() line 6 at SQL statement
SQL statement "insert into t1 values(:new.c1,:new.c2)"
PL/SQL function t1_trriger_1680177824() line 6 at SQL statement

-----------before DML trigger 2

值得注意的是行级触发器才能修改:NEW值

create trigger t1_trriger
before insert on t1
for each row --修改new值,必须是行级触发器,否则不生效的
as
begin
if inserting and :new.c1 = 0 then
:new.c1 := -1; ---对值进行修正
end if;
end;

验证:

test=# select * from t1;
test-# /
c1 | c2
----+----
10 | 11
20 | 22
12 | 5
(3 rows) test=# insert into t1_id_info values(0,66);
test-# /
INSERT 0 1
test=# select * from t1;
test-# /
c1 | c2
----+----
10 | 11
20 | 22
12 | 5
-1 | 66
(4 rows)

最终修改成功

3,after条件的DML触发改写方案

而after 触发器是在触发操作完成之后执行,显然从new值中着手已经没有意义,只能依靠其他方式实现“对值的修正”操作。

--使用update在插入数据后进行修正

create trigger t1_trriger
after insert on t1
for each row
as
begin
if inserting and :new.c1 = 0 then
update t1 set c1 = -1 where c1 = 0 and c2 = :new.c2; ---对值进行修正
end if;
end;

验证:

test=# select * from t1;
test-# /
c1 | c2
----+----
10 | 11
20 | 22
12 | 5
-1 | 66
(4 rows) test=# insert into t1_id_info values(0,55);
test-# /
INSERT 0 1
test=# select * from t1;
test-# /
c1 | c2
----+----
10 | 11
20 | 22
12 | 5
-1 | 66
-1 | 55
(5 rows)

验证成功,

注意:上面的这种写法会影响历史c1值是0的数据行(c1 = 0 且 c2 = :new.c2时),如果希望不修改已有的值,最好可以根据表中的主键(如果有的话)或者唯一值进行修改。

浅谈 KingbaseES 和 SQLServer 中的 instead of 触发器的更多相关文章

  1. 浅谈线程池(中):独立线程池的作用及IO线程池

    原文地址:http://blog.zhaojie.me/2009/07/thread-pool-2-dedicate-pool-and-io-pool.html 在上一篇文章中,我们简单讨论了线程池的 ...

  2. 【ASP.NET MVC系列】浅谈NuGet在VS中的运用

    一     概述 在我们讲解NuGet前,我们先来看看一个例子. 1.例子: 假设现在开发一套系统,其中前端框架我们选择Bootstrap,由于选择Bootstrap作为前端框架,因此,在项目中,我们 ...

  3. 浅谈surging服务引擎中的rabbitmq组件和容器化部署

    1.前言 上个星期完成了surging 的0.9.0.1 更新工作,此版本通过nuget下载引擎组件,下载后,无需通过代码build集成,引擎会通过Sidecar模式自动扫描装配异构组件来构建服务引擎 ...

  4. 浅谈如何检查Linux中开放端口列表

    给大家分享一篇关于如何检查Linux中的开放端口列表的详细介绍,首先如果你想检查远程Linux系统上的端口是否打开请点击链接浏览.如果你想检查多个远程Linux系统上的端口是否打开请点击链接浏览.如果 ...

  5. 【Unity游戏开发】浅谈Lua和C#中的闭包

    一.前言 目前在Unity游戏开发中,比较流行的两种语言就是Lua和C#.通常的做法是:C#做些核心的功能和接口供Lua调用,Lua主要做些UI模块和一些业务逻辑.这样既能在保持一定的游戏运行效率的同 ...

  6. 浅谈使用spring security中的BCryptPasswordEncoder方法对密码进行加密与密码匹配

    浅谈使用springsecurity中的BCryptPasswordEncoder方法对密码进行加密(encode)与密码匹配(matches) spring security中的BCryptPass ...

  7. 浅谈MFC类CrackMe中消息处理函数查找方法

    最近一个学姐发给我了一份CrackMe希望我解一下,其中涉及到了MFC的消息函数查找的问题,就顺便以此为例谈一下自己使用的消息函数查找的方法.本人萌新,如果有任何错漏与解释不清的地方,欢迎各路大佬指正 ...

  8. 浅谈Observer在代码中表现形式

    说到观察者模式,基本在软件工程领域中是应用广泛,不知道的可以先学习一番,下面给个快速的回顾,然后在通过一个grpc中的responseObserver谈下观察者对象在代码中的位置. 喜欢类图,就不上其 ...

  9. 浅谈我对C#中抽象类与接口的理解

    C#中的抽象类与接口有些相似,初学者很容易混淆,今天就让我来谈谈对二者的理解. 首先我们得明确二者的含义,分述如下: 如果一个类不与具体的事物相联系,而只是表达一种抽象的概念,仅仅是作为其派生类的一个 ...

  10. 浅谈python web框架中的orm设计

    看了一下廖雪峰的那个web框架,其实就是封装了web.py,请求使用异步并将aiomysql做为MySQL数据库提供了异步IO的驱动,前端部分则整合了jinja.其中最难的应该是orm部分了. 下面是 ...

随机推荐

  1. Innodb学习之MySQL体系结构

    目录 数据库和数据库实例 MySQL体系结构 MySQL各存储引擎特性 Innodb存储引擎 MyISAM BDB: Memory Archive Federated 数据库和数据库实例 数据库是所有 ...

  2. go语言编程常见问题

    在Goland中运行单元测试报错Error: Cannot find package 如下图,在Goland中运行单元测试时报错:"Error: Cannot find package&qu ...

  3. Git 分支管理参考模型

    一个值得参考的Git分支管理模型如下: master 生产主分支,发布到生产环境使用这个分支,由hotfix或者release分支合并过来,不直接提交代码. release 预发布分支, 基于feat ...

  4. day01---操作系统安装环境准备

    虚拟机安装操作系统步骤 1.新建虚拟主机 2.选择自定义 3.稍后安装操作系统 4.操作系统选择linux 5.选择存放位置 6.cpu和核数选择,默认即可 7.内存分配 8.网络选择 9.控制器类型 ...

  5. Elasticsearch系列之-linux.docker安装和基础操作及在Django中集成

    elasticsearch Elasticsearch是一个基于Lucene的搜索服务器,也是属于NoSQL阵营的数据库.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口提供 ...

  6. 2-Django之三板斧

    HttpResponse 返回字符串类型的数据 HttpResponse: 这是 Django 自带的类,用于构建基本的 HTTP 响应 我的app名称是demo,我们先按照正常的流程,在views中 ...

  7. 【Azure Redis 缓存 Azure Cache For Redis】Azure Redis删除 TLS 1.0 和 1.1的计划及问题

    问题描述 Azure Redis 正式关闭TLS1.0和1.1关闭的时间 根据文档描述Azure Redis阶段2我们将停止支持 TLS 1.1 和 TLS 1.0,暂时计划 2020 年 12 月 ...

  8. [Linux] 无显示器 无键盘 网线直连传输文件

    有显示器可以操作 这种情况下要简单的多,基本思想是,网线直连之后让其中一方当作网关,分配好ip地址,比如说192.168.8.1,网关也是192.168.8.1即可,如果要填写子网掩码就写255.25 ...

  9. 使用 Java 在Excel中创建下拉列表

    下拉列表(下拉框)可以确保用户仅从预先给定的选项中进行选择,这样不仅能减少数据输入错误,还能节省时间提高效率.在MS Excel中,我们可以通过 "数据验证" 提供的选项来创建下拉 ...

  10. Zabbix“专家坐诊”第190期问答汇总

    问题一 Q:请问为啥用拓扑图监控交换机接口流量,获取不到数据,显示未知,键值也没错 ,最新数据也能看到,是什么原因呢? A:把第一个值改成主机名. 问题二 Q:请问下zabbix server 有什么 ...