f_trig触发器

问题描述:请问示波器中的trigger是干什么用的 大家好,给大家分享一下触发器for after instead of,很多人还不知道这一点。下面详细解释一下。现在让我们来看看!

postgreSQL触发器

f_trig触发器的相关图片

是示波器的同步。

trigger 触发器设置触发方式与电平 ,然后就能把满足触发条件的保存下来因为信号太快无法看清楚 ,要利用触发方式捕捉以便慢慢看一般可以设置触发方式 ,和触发电平波形满足设置条件都可以触发。

示波器是一种用途十分广泛的电子测量仪器。它能把肉眼看不见的电信号变换成看得见的图像,便于人们研究各种电现象的变化过程。示波器利用狭窄的、由高速电子组成的电子束,打在涂有荧光物质的屏面上,就可产生细小的光点(这是传统的模拟示波器的工作原理)。

扩展资料:

波形显示的基本原理

由示波管的原理可知,一个直流电压加到一对偏转板上时,将使光点在荧光屏上产生一个固定位移,该位移的大小与所加直流电压成正比。如果分别将两个直流电压同时加到垂直和水平两对偏转板上,则荧光屏上的光点位置就由两个方向的位移所共同决定。

如果将一个正弦交流电压加到一对偏转板上时,光点在荧光屏上将随电压的变化而移动。

参考资料来源:百度百科-通用示波器。

SQL。。server级触发器代码问题。。高手》》的相关图片

SQL。。server级触发器代码问题。。高手》》

PostgreSQL 提供按行与按语句触发的触发器。按行触发的触发器函数为触发语句影响的每一行执行一次;按语句触发的触发器函数为每条触发语句执行一次,而不管影响的行数。特别是,一个影响零行的语句将仍然导致按语句触发的触发器执行。这两种类型的触发器有时候分别叫做行级触发器和语句级触发器。触发器还通常分成 before 触发器和 after 触发器。语句级别的"before"触发器通常在语句开始做任何事情之前触发,而语句级别的"after"触发器在语句结束时触发。行级别的"before"触发器在对特定行进行操作之前触发,而行级别的"after"触发器在语句结束的时候触发(但是在任何语句级别的"after"触发器之前)。

一个触发器是一种声明,告诉数据库应该在执行特定的操作的时候执行特定的函数。触发器可以定义在一个 INSERT, UPDATE, DELETE 命令之前或者之后执行,要么是对每行执行一次,要么是对每条 SQL 语句执行一次。如果发生触发器事件,那么将在合适的时刻调用触发器函数以处理该事件。触发器函数必须在创建触发器之前,作为一个没有参数并且返回 trigger 类型的函数定义。触发器函数通过特殊的 TriggerData 结构接收其输入,而不是用普通的函数参数方式.。

注意:

一.按语句触发的触发器应该总是返回 NULL. 。

二.如果必要,按行触发的触发器函数可以给调用它的执行者返回一行数据(一个类型为 HeapTuple 的数值),那些在操作之前触发的触发器有以下选择。

1. 它可以返回 NULL 以忽略对当前行的操作。这就指示执行器不要执行调用该触。

发器的行级别操作(对特定行的插入或者更改)。

2.只用于 INSERT 和 UPDATE 行触发器:返回的行将成为被插入的行或者是成为。

将要更新的行。这样就允许触发器函数修改将要被插入或者更新的行。

一个无意导致任何这类行为的在操作之前触发的行级触发器必须仔细返回那个被当作新行传进来的行。也就是说,对于 INSERT 和 UPDATE 触发器而言,是 NEW 行,对于 DELETE触发器而言,是 OLD 行。

三. 对于在操作之后触发的行级触发器,其返回值会被忽略,因此可以回NULL。

下面通过具体的例子来说明在postgresql中触发器的建立和使用(老规矩先写代码然后讲解)。

#include <postgres.h>。

#include <executor/spi.h>。

#include <funcapi.h>。

#include <commands/trigger.h>。

#include <fmgr.h>。

extern Datum pg_trigf(PG_FUNCTION_ARGS);。

#ifdef PG_MODULE_MAGIC。

PG_MODULE_MAGIC;。

#endif

PG_FUNCTION_INFO_V1(pg_trigf);。

Datum

pg_trigf(PG_FUNCTION_ARGS)。

TriggerData *trigdata = (TriggerData *)fcinfo->context;。

HeapTuple rettuple = NULL;。

int ret;

int proc; /* to store the value of SPI_processed (actual row number)*/。

/* to be sure this function will be called by trigger */。

if (!(CALLED_AS_TRIGGER(fcinfo))) {。

elog(ERROR, "trigf: not called by triggermanager");。

}

/* should be fired by statement */。

if (TRIGGER_FIRED_FOR_ROW(trigdata->tg_event)) {。

elog(ERROR, "cannot process row events");。

}

/* should be fired before event */。

if (TRIGGER_FIRED_AFTER(trigdata->tg_event)) {。

elog(ERROR, "must be fired before event");。

}

/* connect spi manager */。

if ((ret = SPI_connect()) < 0) {。

elog(INFO, "SPI_connect failed: SPI_connectreturned: %d", ret);。

return PointerGetDatum(rettuple);。

}

/* check the permanent table name(perm_user) existsor not*/。

ret = SPI_exec("SELECT tablename FROM pg_tables WHERE tablename LIKE'perm!_user' ESCAPE '!';", 1);。

proc = SPI_processed;。

if (ret != SPI_OK_SELECT) {。

elog(INFO, "SPI_exec execute error: user table.");。

SPI_finish();。

return PointerGetDatum(rettuple);。

}

/* create the permanent table(perm_user) if it does not exist */。

if (proc < 1) {。

/* create permanent table: perm_user */。

ret = SPI_exec("CREATE TABLE perm_user ASSELECT * FROM tbl_user;", 0);。

if (ret != SPI_OK_SELINTO ) {。

elog(INFO, "SPI_execexecute error: fail to create perm_user");。

SPI_finish();。

returnPointerGetDatum(rettuple);。

}

/* set attribute to perm_user */。

ret = SPI_exec("ALTER TABLE perm_user ADD PRIMARYKEY (user_name);", 0);。

if (ret != SPI_OK_SELINTO) {。

elog(INFO, "SPI_execexecute error: fail to add primary key to perm_user");。

SPI_finish();。

returnPointerGetDatum(rettuple);。

}

/* set attribute to perm_user*/。

ret = SPI_exec("ALTER TABLE perm_user ALTERuser_passwd SET NOT NULL;", 0);。

if (ret != SPI_OK_SELINTO) {。

elog(INFO, "SPI_execexecute error: fail to set attribute to password.");。

SPI_finish();。

returnPointerGetDatum(rettuple);。

}

}

.....

/* check the permanent table name(perm_member) exists or not */。

ret = SPI_exec("SELECT tablename FROM pg_tables WHERE tablename LIKE'perm!_member' ESCAPE '!';", 1);。

proc = SPI_processed;。

if (ret != SPI_OK_SELECT) {。

elog(INFO, "SPI_exec execute errortbl_member");。

SPI_finish();。

return PointerGetDatum(rettuple);。

}

/* create the permanent table(perm_member) if it does not exist */。

if (proc < 1) {。

/* create permanent table: perm_member */。

ret = SPI_exec("CREATE TABLE perm_member ASSELECT * FROM tbl_member;", 0);。

if (ret != SPI_OK_SELINTO) {。

elog(INFO, "SPI_execexecute error");。

SPI_finish();。

returnPointerGetDatum(rettuple);。

}

/* set attribute to perm_member */。

ret = SPI_exec("ALTER TABLE perm_member ADDCONSTRAINT user_fk FOREIGN KEY (user_name) REFERENCES perm_user(user_name) ONDELETE CASCADE ON UPDATE CASCADE;", 0); 。

if (ret != SPI_OK_UTILITY) {。

elog(INFO, "SPI_execexecute error: fail to set attribute to user_name.");。

SPI_finish();。

returnPointerGetDatum(rettuple);。

}

/* set attribute to perm_member */。

ret = SPI_exec("ALTER TABLE perm_member ADDCONSTRAINT group_fk FOREIGN KEY (grp_name) REFERENCES perm_group(grp_name) ONDELETE CASCADE ON UPDATE CASCADE;", 0); 。

if (ret != SPI_OK_UTILITY) {。

elog(INFO, "SPI_execexecute error: fail to set attribute to grp_name.");。

SPI_finish();。

return PointerGetDatum(rettuple);。

}

/* add primary key to perm_member */。

ret = SPI_exec("ALTER TABLE perm_member ADDPRIMARY KEY (user_name, grp_name);", 0); 。

if (ret != SPI_OK_UTILITY) {。

elog(INFO, "SPI_execexecute error: fail to add primary key to perm_member.");。

SPI_finish();。

returnPointerGetDatum(rettuple);。

}

}

/*close connect with SPI manager */。

SPI_finish(); 。

/* return back must be NULL*/。

return PointerGetDatum(rettuple);。

这个函数写法与postgresql服务端函数的写法很相似, 但是不完全相同.具体需要注意的地方是:。

1. 需要多添加头文件:#include <commands/trigger.h>。

2. 这个函数的返回值一定是trigger类型的.。

3. 函数的开始最好确认这个函数是供触发器调用的并且明确一下自己要写的触发器的类型是什么,然后做一下判断,以免别的语句也触发的触发器.。

二. 接下来的事情是编译:

gcc -fpic -c trigger.c-I/usr/local/postgreSQL/include/postgresql/server。

gcc -shared -o trigger.so trigger.o。

如果不明白可以参考手册(说句题外话,手册的作用实在是太大了,在手册中也提供了一例子).。

三. 在数据库中创建函数和触发器:。

/* create a trigger used to write memory and configmemory */。

CREATE OR REPLACE FUNCTION pg_trigf() RETURNS trigger。

AS 'filename' 。

LANGUAGE C IMMUTABLESTRICT; 。

CREATE TRIGGER tbuser BEFORE INSERT OR UPDATE OR DELETE 。

ON tbl_user FOR EACH STATEMENT。

EXECUTE PROCEDURE pg_trigf();。

CREATE TRIGGER tbgroup BEFORE INSERT OR UPDATE OR DELETE。

创建的触发器是语句触发器,这个和手册上的不一样, 手册上的是行触发器.。

然后在数据库中使用SQL语句就可以看到触发器的效果了.。

在数据库中建立一个触发器:当学生表student中插入一个新同学时,就会显示所有的同学的信息的相关图片

在数据库中建立一个触发器:当学生表student中插入一个新同学时,就会显示所有的同学的信息

第一,,这段代码能运行吗?

语法

CREATE TRIGGER trigger_name 。

ON { table | view } 。

[ WITH ENCRYPTION ] 。

{ { FOR | AFTER | INSTEAD OF } { [ INSERT ] [ , ] [ UPDATE ] }。

[ WITH APPEND ]。

[ NOT FOR REPLICATION ]。

AS

[ { IF UPDATE ( column )。

[ { AND | OR } UPDATE ( column ) ]。

[ ...n ]。

| IF ( COLUMNS_UPDATED ( ) { bitwise_operator } updated_bitmask )。

{ comparison_operator } column_bitmask [ ...n ]。

} ]

sql_statement [ ...n ] 。

}

}

看语法:

on后是表名或视图名

实例:

USE pubs

IF EXISTS (SELECT name FROM sysobjects。

WHERE name = 'reminder' AND type = 'TR')。

DROP TRIGGER reminder。

GO

CREATE TRIGGER reminder。

ON titles

FOR INSERT, UPDATE 。

AS RAISERROR (50009, 16, 10)。

GO

我参考为SQL Server帮助。

Transact-SQL 参考 。

CREATE TRIGGER

创建触发器,触发器是一种特殊的存储过程,在用户试图对指定的表执行指定的数据修改语句时自动执行。Microsoft® SQL Server™ 允许为任何给定的 INSERT、UPDATE 或 DELETE 语句创建多个触发器。

语法

CREATE TRIGGER trigger_name 。

ON { table | view } 。

[ WITH ENCRYPTION ] 。

{ { FOR | AFTER | INSTEAD OF } { [ INSERT ] [ , ] [ UPDATE ] }。

[ WITH APPEND ]。

[ NOT FOR REPLICATION ]。

AS

[ { IF UPDATE ( column )。

[ { AND | OR } UPDATE ( column ) ]。

[ ...n ]。

| IF ( COLUMNS_UPDATED ( ) { bitwise_operator } updated_bitmask )。

{ comparison_operator } column_bitmask [ ...n ]。

} ]

sql_statement [ ...n ] 。

}

}

参数

trigger_name

是触发器的名称。触发器名称必须符合标识符规则,并且在数据库中必须唯一。可以选择是否指定触发器所有者名称。

Table | view

是在其上执行触发器的表或视图,有时称为触发器表或触发器视图。可以选择是否指定表或视图的所有者名称。

WITH ENCRYPTION。

加密 syscomments 表中包含 CREATE TRIGGER 语句文本的条目。使用 WITH ENCRYPTION 可防止将触发器作为 SQL Server 复制的一部分发布。

AFTER

指定触发器只有在触发 SQL 语句中指定的所有操作都已成功执行后才激发。所有的引用级联操作和约束检查也必须成功完成后,才能执行此触发器。

如果仅指定 FOR 关键字,则 AFTER 是默认设置。

不能在视图上定义 AFTER 触发器。

INSTEAD OF

指定执行触发器而不是执行触发 SQL 语句,从而替代触发语句的操作。

在表或视图上,每个 INSERT、UPDATE 或 DELETE 语句最多可以定义一个 INSTEAD OF 触发器。然而,可以在每个具有 INSTEAD OF 触发器的视图上定义视图。

INSTEAD OF 触发器不能在 WITH CHECK OPTION 的可更新视图上定义。如果向指定了 WITH CHECK OPTION 选项的可更新视图添加 INSTEAD OF 触发器,SQL Server 将产生一个错误。用户必须用 ALTER VIEW 删除该选项后才能定义 INSTEAD OF 触发器。

{ [DELETE] [,] [INSERT] [,] [UPDATE] }。

是指定在表或视图上执行哪些数据修改语句时将激活触发器的关键字。必须至少指定一个选项。在触发器定义中允许使用以任意顺序组合的这些关键字。如果指定的选项多于一个,需用逗号分隔这些选项。

对于 INSTEAD OF 触发器,不允许在具有 ON DELETE 级联操作引用关系的表上使用 DELETE 选项。同样,也不允许在具有 ON UPDATE 级联操作引用关系的表上使用 UPDATE 选项。

WITH APPEND

指定应该添加现有类型的其它触发器。只有当兼容级别是 65 或更低时,才需要使用该可选子句。如果兼容级别是 70 或更高,则不必使用 WITH APPEND 子句添加现有类型的其它触发器(这是兼容级别设置为 70 或更高的 CREATE TRIGGER 的默认行为)。有关更多信息,请参见 sp_dbcmptlevel。

WITH APPEND 不能与 INSTEAD OF 触发器一起使用,或者,如果显式声明 AFTER 触发器,也不能使用该子句。只有当出于向后兼容而指定 FOR 时(没有 INSTEAD OF 或 AFTER),才能使用 WITH APPEND。以后的版本将不支持 WITH APPEND 和 FOR(将被解释为 AFTER)。

NOT FOR REPLICATION。

表示当复制进程更改触发器所涉及的表时,不应执行该触发器。

AS

是触发器要执行的操作。

sql_statement

是触发器的条件和操作。触发器条件指定其它准则,以确定 DELETE、INSERT 或 UPDATE 语句是否导致执行触发器操作。

当尝试 DELETE、INSERT 或 UPDATE 操作时,Transact-SQL语句中指定的触发器操作将生效。

触发器可以包含任意数量和种类的 Transact-SQL 语句。触发器旨在根据数据修改语句检查或更改数据;它不应将数据返回给用户。触发器中的 Transact-SQL 语句常常包含控制流语言。CREATE TRIGGER 语句中使用几个特殊的表:

deleted 和 inserted 是逻辑(概念)表。这些表在结构上类似于定义触发器的表(也就是在其中尝试用户操作的表);这些表用于保存用户操作可能更改的行的旧值或新值。例如,若要检索 deleted 表中的所有值,请使用:

SELECT *

FROM deleted

如果兼容级别等于 70,那么在 DELETE、INSERT 或 UPDATE 触发器中,SQL Server 将不允许引用 inserted 和 deleted 表中的 text、ntext 或 image 列。不能访问 inserted 和 deleted 表中的 text、ntext 和 image 值。若要在 INSERT 或 UPDATE 触发器中检索新值,请将 inserted 表与原始更新表联接。当兼容级别是 65 或更低时,对 inserted 或 deleted 表中允许空值的text、ntext 或 image 列,将返回空值;如果这些列不可为空,则返回零长度字符串。

当兼容级别是 80 或更高时,SQL Server 允许在表或视图上通过 INSTEAD OF 触发器更新 text、ntext 或 image 列。

是表示触发器中可以包含多条 Transact-SQL 语句的占位符。对于 IF UPDATE (column) 语句,可以通过重复 UPDATE (column) 子句包含多列。

IF UPDATE (column)。

测试在指定的列上进行的 INSERT 或 UPDATE 操作,不能用于 DELETE 操作。可以指定多列。因为在 ON 子句中指定了表名,所以在 IF UPDATE 子句中的列名前不要包含表名。若要测试在多个列上进行的 INSERT 或 UPDATE 操作,请在第一个操作后指定单独的 UPDATE(column) 子句。在 INSERT 操作中 IF UPDATE 将返回 TRUE 值,因为这些列插入了显式值或隐性 (NULL) 值。

说明 IF UPDATE (column) 子句的功能等同于 IF、IF...ELSE 或 WHILE 语句,并且可以使用 BEGIN...END 语句块。有关更多信息,请参见控制流语言。

可以在触发器主体中的任意位置使用 UPDATE (column)。

column

是要测试 INSERT 或 UPDATE 操作的列名。该列可以是 SQL Server 支持的任何数据类型。但是,计算列不能用于该环境中。有关更多信息,请参见数据类型。

IF (COLUMNS_UPDATED()) 。

测试是否插入或更新了提及的列,仅用于 INSERT 或 UPDATE 触发器中。COLUMNS_UPDATED 返回 varbinary 位模式,表示插入或更新了表中的哪些列。

COLUMNS_UPDATED 函数以从左到右的顺序返回位,最左边的为最不重要的位。最左边的位表示表中的第一列;向右的下一位表示第二列,依此类推。如果在表上创建的触发器包含 8 列以上,则 COLUMNS_UPDATED 返回多个字节,最左边的为最不重要的字节。在 INSERT 操作中 COLUMNS_UPDATED 将对所有列返回 TRUE 值,因为这些列插入了显式值或隐性 (NULL) 值。

可以在触发器主体中的任意位置使用 COLUMNS_UPDATED。

bitwise_operator。

是用于比较运算的位运算符。

updated_bitmask。

是整型位掩码,表示实际更新或插入的列。例如,表 t1 包含列 C1、C2、C3、C4 和 C5。假定表 t1 上有 UPDATE 触发器,若要检查列 C2、C3 和 C4 是否都有更新,指定值 14;若要检查是否只有列 C2 有更新,指定值 2。

comparison_operator。

是比较运算符。使用等号 (=) 检查 updated_bitmask 中指定的所有列是否都实际进行了更新。使用大于号 (>) 检查 updated_bitmask 中指定的任一列或某些列是否已更新。

column_bitmask

是要检查的列的整型位掩码,用来检查是否已更新或插入了这些列。

注释

触发器常常用于强制业务规则和数据完整性。SQL Server 通过表创建语句(ALTER TABLE 和 CREATE TABLE)提供声明引用完整性 (DRI);但是 DRI 不提供数据库间的引用完整性。若要强制引用完整性(有关表的主键和外键之间关系的规则),请使用主键和外键约束(ALTER TABLE 和 CREATE TABLE 的 PRIMARY KEY 和 FOREIGN KEY 关键字)。如果触发器表存在约束,则在 INSTEAD OF 触发器执行之后和 AFTER 触发器执行之前检查这些约束。如果违反了约束,则回滚 INSTEAD OF 触发器操作且不执行(激发)AFTER 触发器。

可用 sp_settriggerorder 指定表上第一个和最后一个执行的 AFTER 触发器。在表上只能为每个 INSERT、UPDATE 和 DELETE 操作指定一个第一个执行和一个最后一个执行的 AFTER 触发器。如果同一表上还有其它 AFTER 触发器,则这些触发器将以随机顺序执行。

如果 ALTER TRIGGER 语句更改了第一个或最后一个触发器,则将除去已修改触发器上设置的第一个或最后一个特性,而且必须用 sp_settriggerorder 重置排序值。

只有当触发 SQL 语句(包括所有与更新或删除的对象关联的引用级联操作和约束检查)成功执行后,AFTER 触发器才会执行。AFTER 触发器检查触发语句的运行效果,以及所有由触发语句引起的 UPDATE 和 DELETE 引用级联操作的效果。

触发器限制

CREATE TRIGGER 必须是批处理中的第一条语句,并且只能应用到一个表中。

触发器只能在当前的数据库中创建,不过触发器可以引用当前数据库的外部对象。

如果指定触发器所有者名称以限定触发器,请以相同的方式限定表名。

在同一条 CREATE TRIGGER 语句中,可以为多种用户操作(如 INSERT 和 UPDATE)定义相同的触发器操作。

如果一个表的外键在 DELETE/UPDATE 操作上定义了级联,则不能在该表上定义 INSTEAD OF DELETE/UPDATE 触发器。

在触发器内可以指定任意的 SET 语句。所选择的 SET 选项在触发器执行期间有效,并在触发器执行完后恢复到以前的设置。

与使用存储过程一样,当触发器激发时,将向调用应用程序返回结果。若要避免由于触发器激发而向应用程序返回结果,请不要包含返回结果的 SELECT 语句,也不要包含在触发器中进行变量赋值的语句。包含向用户返回结果的 SELECT 语句或进行变量赋值的语句的触发器需要特殊处理;这些返回的结果必须写入允许修改触发器表的每个应用程序中。如果必须在触发器中进行变量赋值,则应该在触发器的开头使用 SET NOCOUNT 语句以避免返回任何结果集。

DELETE 触发器不能捕获 TRUNCATE TABLE 语句。尽管 TRUNCATE TABLE 语句实际上是没有 WHERE 子句的 DELETE(它删除所有行),但它是无日志记录的,因而不能执行触发器。因为 TRUNCATE TABLE 语句的权限默认授予表所有者且不可转让,所以只有表所有者才需要考虑无意中用 TRUNCATE TABLE 语句规避 DELETE 触发器的问题。

无论有日志记录还是无日志记录,WRITETEXT 语句都不激活触发器。

触发器中不允许以下 Transact-SQL 语句:

ALTER DATABASE CREATE DATABASE DISK INIT 。

DISK RESIZE DROP DATABASE LOAD DATABASE 。

LOAD LOG RECONFIGURE RESTORE DATABASE 。

RESTORE LOG 。

说明 由于 SQL Server 不支持系统表中的用户定义触发器,因此建议不要在系统表中创建用户定义触发器。

多个触发器

SQL Server 允许为每个数据修改事件(DELETE、INSERT 或 UPDATE)创建多个触发器。例如,如果对已有 UPDATE 触发器的表执行 CREATE TRIGGER FOR UPDATE,则将创建另一个更新触发器。在早期版本中,在每个表上,每个数据修改事件(INSERT、UPDATE 或 DELETE)只允许有一个触发器。

说明 如果触发器名称不同,则 CREATE TRIGGER(兼容级别为 70)的默认行为是在现有的触发器中添加其它触发器。如果触发器名称相同,则 SQL Server 返回一条错误信息。但是,如果兼容级别等于或小于 65,则使用 CREATE TRIGGER 语句创建的新触发器将替换同一类型的任何现有触发器,即使触发器名称不同。有关更多信息,请参见 sp_dbcmptlevel。

递归触发器

当在 sp_dboption 中启用 recursive triggers 设置时,SQL Server 还允许触发器的递归调用。

递归触发器允许发生两种类型的递归:

间接递归

直接递归

使用间接递归时,应用程序更新表 T1,从而激发触发器 TR1,该触发器更新表 T2。在这种情况下,触发器 T2 将激发并更新 T1。

使用直接递归时,应用程序更新表 T1,从而激发触发器 TR1,该触发器更新表 T1。由于表 T1 被更新,触发器 TR1 再次激发,依此类推。

下例既使用了间接触发器递归,又使用了直接触发器递归。假定在表 T1 中定义了两个更新触发器 TR1 和 TR2。触发器 TR1 递归地更新表 T1。UPDATE 语句使 TR1 和 TR2 各执行一次。而 TR1 的执行将触发 TR1(递归)和 TR2 的执行。给定触发器的 inserted 和 deleted 表只包含与唤醒调用触发器的 UPDATE 语句相对应的行。

说明 只有启用 sp_dboption 的 recursive triggers 设置,才会发生上述行为。对于为给定事件定义的多个触发器,并没有确定的执行顺序。每个触发器都应是自包含的。

禁用 recursive triggers 设置只能禁止直接递归。若要也禁用间接递归,请使用 sp_configure 将 nested triggers 服务器选项设置为 0。

如果任一触发器执行了 ROLLBACK TRANSACTION 语句,则无论嵌套级是多少,都不会进一步执行其它触发器。

嵌套触发器

触发器最多可以嵌套 32 层。如果一个触发器更改了包含另一个触发器的表,则第二个触发器将激活,然后该触发器可以再调用第三个触发器,依此类推。如果链中任意一个触发器引发了无限循环,则会超出嵌套级限制,从而导致取消触发器。若要禁用嵌套触发器,请用 sp_configure 将 nested triggers 选项设置为 0(关闭)。默认配置允许嵌套触发器。如果嵌套触发器是关闭的,则也将禁用递归触发器,与 sp_dboption 的 recursive triggers 设置无关。

延迟名称解析

SQL Server 允许 Transact-SQL 存储过程、触发器和批处理引用编译时不存在的表。这种能力称为延迟名称解析。但是,如果 Transact-SQL 存储过程、触发器或批处理引用在存储过程或触发器中定义的表,则只有当兼容级别设置(通过执行 sp_dbcmptlevel 设置)等于 65 时,才会在创建时发出警告。如果使用批处理,则在编译时发出警告。如果引用的表不存在,将在运行时返回错误信息。有关更多信息,请参见延迟名称解析和编译。

权限

CREATE TRIGGER 权限默认授予定义触发器的表所有者、sysadmin 固定服务器角色成员以及 db_owner 和 db_ddladmin 固定数据库角色成员,并且不可转让。

若要检索表或视图中的数据,用户必须在表或视图中拥有 SELECT 语句权限。若要更新表或视图的内容,用户必须在表或视图中拥有 INSERT、DELETE 和 UPDATE 语句权限。

如果视图中存在 INSTEAD OF 触发器,用户必须在该视图中有 INSERT、DELETE 和 UPDATE 特权,以对该视图发出 INSERT、DELETE 和 UPDATE 语句,而不管实际上是否在视图上执行了这样的操作。

示例

A. 使用带有提醒消息的触发器。

当有人试图在 titles 表中添加或更改数据时,下例将向客户端显示一条消息。

说明 消息 50009 是 sysmessages 中的用户定义消息。有关创建用户定义消息的更多信息,请参见 sp_addmessage。

USE pubs

IF EXISTS (SELECT name FROM sysobjects。

WHERE name = 'reminder' AND type = 'TR')。

DROP TRIGGER reminder。

GO

CREATE TRIGGER reminder。

ON titles

FOR INSERT, UPDATE 。

AS RAISERROR (50009, 16, 10)。

GO

B. 使用带有提醒电子邮件的触发器。

当 titles 表更改时,下例将电子邮件发送给指定的人员 (MaryM)。

USE pubs

IF EXISTS (SELECT name FROM sysobjects。

WHERE name = 'reminder' AND type = 'TR')。

DROP TRIGGER reminder。

GO

CREATE TRIGGER reminder。

ON titles

FOR INSERT, UPDATE, DELETE 。

AS

EXEC master..xp_sendmail 'MaryM', 。

'Don''t forget to print a report for the distributors.'。

GO

C. 在 employee 和 jobs 表之间使用触发器业务规则。

由于 CHECK 约束只能引用定义了列级或表级约束的列,表间的任何约束(在下例中是指业务规则)都必须定义为触发器。

下例创建一个触发器,当插入或更新雇员工作级别 (job_lvls) 时,该触发器检查指定雇员的工作级别(由此决定薪水)是否处于为该工作定义的范围内。若要获得适当的范围,必须引用 jobs 表。

USE pubs

IF EXISTS (SELECT name FROM sysobjects。

WHERE name = 'employee_insupd' AND type = 'TR')。

DROP TRIGGER employee_insupd。

GO

CREATE TRIGGER employee_insupd。

ON employee

FOR INSERT, UPDATE。

AS

/* Get the range of level for this job type from the jobs table. */。

DECLARE @min_lvl tinyint,。

@max_lvl tinyint,。

@emp_lvl tinyint,。

@job_id smallint。

SELECT @min_lvl = min_lvl, 。

@max_lvl = max_lvl, 。

@emp_lvl = i.job_lvl,。

@job_id = i.job_id。

FROM employee e INNER JOIN inserted i ON e.emp_id = i.emp_id 。

JOIN jobs j ON j.job_id = i.job_id。

IF (@job_id = 1) and (@emp_lvl <> 10) 。

BEGIN

RAISERROR ('Job id 1 expects the default level of 10.', 16, 1)。

ROLLBACK TRANSACTION。

END

ELSE

IF NOT (@emp_lvl BETWEEN @min_lvl AND @max_lvl)。

BEGIN

RAISERROR ('The level for job_id:%d should be between %d and %d.',。

16, 1, @job_id, @min_lvl, @max_lvl)。

ROLLBACK TRANSACTION。

END

D. 使用延迟名称解析

下例创建两个触发器以说明延迟名称解析。

USE pubs

IF EXISTS (SELECT name FROM sysobjects。

WHERE name = 'trig1' AND type = 'TR')。

DROP TRIGGER trig1。

GO

-- Creating a trigger on a nonexistent table.。

CREATE TRIGGER trig1。

on authors

FOR INSERT, UPDATE, DELETE。

AS

SELECT a.au_lname, a.au_fname, x.info 。

FROM authors a INNER JOIN does_not_exist x 。

ON a.au_id = x.au_id。

GO

-- Here is the statement to actually see the text of the trigger.。

SELECT o.id, c.text。

FROM sysobjects o INNER JOIN syscomments c 。

ON o.id = c.id。

WHERE o.type = 'TR' and o.name = 'trig1'。

-- Creating a trigger on an existing table, but with a nonexistent 。

-- column.

USE pubs

IF EXISTS (SELECT name FROM sysobjects。

WHERE name = 'trig2' AND type = 'TR')。

DROP TRIGGER trig2。

GO

CREATE TRIGGER trig2 。

ON authors

FOR INSERT, UPDATE。

AS

DECLARE @fax varchar(12)。

SELECT @fax = phone 。

FROM authors。

GO

-- Here is the statement to actually see the text of the trigger.。

SELECT o.id, c.text。

FROM sysobjects o INNER JOIN syscomments c 。

ON o.id = c.id。

WHERE o.type = 'TR' and o.name = 'trig2'。

E. 使用 COLUMNS_UPDATED。

下例创建两个表:一个 employeeData 表和一个 auditEmployeeData 表。人力资源部的成员可以修改 employeeData 表,该表包含敏感的雇员薪水信息。如果更改了雇员的社会保险号码 (SSN)、年薪或银行帐户,则生成审核记录并插入到 auditEmployeeData 审核表。

通过使用 COLUMNS_UPDATED() 功能,可以快速测试对这些包含敏感雇员信息的列所做的更改。只有在试图检测对表中的前 8 列所做的更改时,COLUMNS_UPDATED() 才起作用。

USE pubs

IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES。

WHERE TABLE_NAME = 'employeeData')。

DROP TABLE employeeData。

IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES。

WHERE TABLE_NAME = 'auditEmployeeData')。

DROP TABLE auditEmployeeData。

GO

CREATE TABLE employeeData (。

emp_id int NOT NULL,。

emp_bankAccountNumber char (10) NOT NULL,。

emp_salary int NOT NULL,。

emp_SSN char (11) NOT NULL,。

emp_lname nchar (32) NOT NULL,。

emp_fname nchar (32) NOT NULL,。

emp_manager int NOT NULL。

)

GO

CREATE TABLE auditEmployeeData (。

audit_log_id uniqueidentifier DEFAULT NEWID(),。

audit_log_type char (3) NOT NULL,。

audit_emp_id int NOT NULL,。

audit_emp_bankAccountNumber char (10) NULL,。

audit_emp_salary int NULL,。

audit_emp_SSN char (11) NULL,。

audit_user sysname DEFAULT SUSER_SNAME(),。

audit_changed datetime DEFAULT GETDATE()。

)

GO

CREATE TRIGGER updEmployeeData 。

ON employeeData 。

FOR update AS

/*Check whether columns 2, 3 or 4 has been updated. If any or all of columns 2, 3 or 4 have been changed, create an audit record. The bitmask is: power(2,(2-1))+power(2,(3-1))+power(2,(4-1)) = 14. To check if all columns 2, 3, and 4 are updated, use = 14 in place of >0 (below).*/。

IF (COLUMNS_UPDATED() & 14) > 0。

/*Use IF (COLUMNS_UPDATED() & 14) = 14 to see if all of columns 2, 3, and 4 are updated.*/。

BEGIN

-- Audit OLD record.。

INSERT INTO auditEmployeeData。

(audit_log_type,。

audit_emp_id,。

audit_emp_bankAccountNumber,。

audit_emp_salary,。

audit_emp_SSN)。

SELECT 'OLD', 。

del.emp_id,。

del.emp_bankAccountNumber,。

del.emp_salary,。

del.emp_SSN。

FROM deleted del。

-- Audit NEW record.。

INSERT INTO auditEmployeeData。

(audit_log_type,。

audit_emp_id,。

audit_emp_bankAccountNumber,。

audit_emp_salary,。

audit_emp_SSN)。

SELECT 'NEW',。

ins.emp_id,。

ins.emp_bankAccountNumber,。

ins.emp_salary,。

ins.emp_SSN。

FROM inserted ins。

END

GO

/*Inserting a new employee does not cause the UPDATE trigger to fire.*/。

INSERT INTO employeeData。

VALUES ( 101, 'USA-987-01', 23000, 'R-M53550M', N'Mendel', N'Roland', 32)。

GO

/*Updating the employee record for employee number 101 to change the salary to 51000 causes the UPDATE trigger to fire and an audit trail to be produced.*/。

UPDATE employeeData。

SET emp_salary = 51000。

WHERE emp_id = 101。

GO

SELECT * FROM auditEmployeeData。

GO

/*Updating the employee record for employee number 101 to change both the bank account number and social security number (SSN) causes the UPDATE trigger to fire and an audit trail to be produced.*/。

UPDATE employeeData。

SET emp_bankAccountNumber = '133146A0', emp_SSN = 'R-M53550M'。

WHERE emp_id = 101。

GO

SELECT * FROM auditEmployeeData。

GO

数据库触发器的优缺点以及用法的相关图片

数据库触发器的优缺点以及用法

代码如下:

alter table SC 。

Drop constraint  FK_SC--删除外键约束。

CREATE TRIGGER  trig_insert  ON SC--在SC表中创建trig_insert触发器 。

AFTER INSERT--insert为触发事件,after则为触发的时机 。

AS  IF  NOT EXISTS(。

SELECT  * FROM Course,。

inserted where Course.Cno=inserted.Cno)  --向SC表插入数据时,检查插入数据的课程号是否存在于Course表中 。

begin  print'插入的课程号不在课程表中'--出错提示  rollback   。

END测试触发器:

insert into SC VALUES('201215130','2','78');--命令成功执行 。

INSERT INTO SC VALUES('201215131','10','78');--事务在触发器中结束。

批处理已中止

扩展资料

触发器是由事件来触发某个操作。这些事件包括INSERT语句、UPDATE语句和DELETE语句。当数据库系统执行这些事件时,会激活促发其执行相应的操作。

SQL触发器,是一种特殊类型的存储过程,不由用户直接调用。它在指定的表中的数据发生变化时自动生效。唤醒调用触发器以响应 INSERT、UPDATE 或 DELETE 语句。他可以查询其它表,并可以包含复杂的Transact-SQL语句。

将触发器和触发它的语句作为可在触发器内回滚的单个事务对待。如果检测到严重错误(例如,磁盘空间不足),则整个事务即自动回滚。常常用于强制业务规则和数据完整性。

参考资料来源:

百度百科——触发器

C#中使用存储过程、触发器、范式!

触发器本质上讲就是事件监控器,可以定义在数据库系统进行某一个操作的前后。

当数据库系统在进行特定的操作时,发现有触发器定义,就去执行触发器定义的功能,从而满足某些特定的需要。

例如,在更新某些数据后,再去更新特定的数据。

这就可以定义一个触发器完成这样的需要。

触发器的优点:

以事件方式来处理. 当数据发生变化的时候, 自动作处理。

缺点:

当数据库之间 导出导入的时候, 可能会引起不必要的触发逻辑。

原文地址:http://www.qianchusai.com/f_trig%E8%A7%A6%E5%8F%91%E5%99%A8.html

condensed近义词,condition的近义词

condensed近义词,condition的近义词

medical词根词缀,医学词根词缀记忆法总口诀

medical词根词缀,医学词根词缀记忆法总口诀

数字1512爱情暗语,1527爱情数字暗语

数字1512爱情暗语,1527爱情数字暗语

300字作文-10,300字作文植物三年级

300字作文-10,300字作文植物三年级

300字作文-60,300字作文 国宝大熊猫

300字作文-60,300字作文 国宝大熊猫

300字作文-80,300字作文 国宝大熊猫

300字作文-80,300字作文 国宝大熊猫

center和middle区别,middle和center有什么区别

center和middle区别,middle和center有什么区别

30字作文-30,30字作文 一年级

30字作文-30,30字作文 一年级

30字作文-10,30字作文 一年级

30字作文-10,30字作文 一年级

30字作文-60,30字作文 一年级

30字作文-60,30字作文 一年级