sql 触发器未触发
SQL Triggers are another powerful database object we have at our disposal. In previous articles, we’ve covered user-defined functions, user-defined procedures, and SQL Views. Today we’ll talk about SQL triggers and how to use them to achieve the desired behavior.
SQL触发器是我们可以使用的另一个强大的数据库对象。 在先前的文章中,我们介绍了用户定义的函数 , 用户定义的过程和SQL视图 。 今天,我们将讨论SQL触发器以及如何使用它们来实现所需的行为。
Before we move to the topic of this article, let’s take a quick look at the model we’re using in this article but also throughout this series.
在转到本文主题之前,让我们快速看一下本文中以及本系列中使用的模型。
In this article, we’ll focus on DML (data manipulation language) triggers and show how they function when we make changes in a single table.
在本文中,我们将重点介绍DML(数据操作语言)触发器,并说明在单个表中进行更改时它们如何工作。
In SQL Server, triggers are database objects, actually, a special kind of stored procedure, which “reacts” to certain actions we make in the database. The main idea behind triggers is that they always perform an action in case some event happens. If we’re talking about DML triggers, these changes shall be changes in our data. Let’s examine a few interesting situations:
在SQL Server中,触发器是数据库对象,实际上是一种特殊的存储过程,它对我们在数据库中执行的某些操作“做出React”。 触发器背后的主要思想是,万一发生某些事件,它们总是执行一个动作。 如果我们在谈论DML触发器,则这些更改将是我们数据中的更改。 让我们研究一些有趣的情况:
From examples, you can notice that DML triggers are actions related to the SQL commands defined in these triggers. Since they are similar to stored procedures, you can test values using the IF statement, etc. This provides a lot of flexibility.
从示例中,您可以注意到DML触发器是与这些触发器中定义SQL命令相关的操作。 由于它们类似于存储过程,因此可以使用IF语句等测试值。这提供了很大的灵活性。
The good reason to use DML SQL triggers is the case when you want to assure that a certain control shall be performed before or after the defined statement on the defined table. This could be the case when your code is all over the place, e.g. database is used by different applications, code is written directly in applications and you don’t have it well-documented.
使用DML SQL触发器的充分理由是,当您要确保在定义的表上的定义的语句之前或之后执行某些控件时。 当您的代码无处不在时,可能是这种情况,例如,数据库被不同的应用程序使用,代码直接编写在应用程序中,而您没有充分的文档说明。
In SQL Server, we have 3 groups of triggers:
在SQL Server中,我们有3组触发器:
In this article, we’ll focus on DML triggers, because they are most commonly used. We’ll cover the remaining two trigger types in the upcoming articles of this series.
在本文中,我们将重点介绍DML触发器,因为它们是最常用的。 在本系列的后续文章中,我们将介绍其余两种触发器类型。
The simplified SQL syntax to define the trigger is as follows.
定义触发器的简化SQL语法如下。
CREATE TRIGGER [schema_name.]trigger_name
ON table_name
{FOR | AFTER | INSTEAD OF} {[INSERT] [,] [UPDATE] [,] [DELETE]}
AS
{sql_statements}
Most of the syntax should be self-explanatory. The main idea is to define:
大多数语法应该是不言自明的。 主要思想是定义:
With this in mind, we can easily write triggers that will:
考虑到这一点,我们可以轻松地编写触发器,该触发器将:
If you want to drop a trigger, you’ll use:
如果要删除触发器,请使用:
DROP TRIGGER [schema_name.]trigger_name;
First, we’ll create a simple SQL trigger that shall perform check before the INSERT statement.
首先,我们将创建一个简单SQL触发器,该触发器将在INSERT语句之前执行检查。
DROP TRIGGER IF EXISTS t_country_insert;
GO
CREATE TRIGGER t_country_insert ON country INSTEAD OF INSERT
AS BEGIN
DECLARE @country_name CHAR(128);
DECLARE @country_name_eng CHAR(128);
DECLARE @country_code CHAR(8);
SELECT @country_name = country_name, @country_name_eng = country_name_eng, @country_code = country_code FROM INSERTED;
IF @country_name IS NULL SET @country_name = @country_name_eng;
IF @country_name_eng IS NULL SET @country_name_eng = @country_name;
INSERT INTO country (country_name, country_name_eng, country_code) VALUES (@country_name, @country_name_eng, @country_code);
END;
We can see our trigger in the Object Explorer, when we expand the data for the related table (country).
展开相关表( 国家/地区 )的数据时,我们可以在对象资源管理器中看到触发器。
I want to emphasize a few things here:
我想在这里强调一些事情:
Let’s now run an INSERT INTO command and see what happens in the database. We’ll run the following statements:
现在让我们运行INSERT INTO命令,看看数据库中发生了什么。 我们将运行以下语句:
SELECT * FROM country;
INSERT INTO country (country_name_eng, country_code) VALUES ('United Kingdom', 'UK');
SELECT * FROM country;
The result is in the picture below.
结果如下图所示。
You can easily notice that the row with id = 10, had been inserted. We haven’t specified the country_name, but the trigger did its’ job and filled that value with country_name_eng.
您可以轻松地注意到,已插入id = 10的行。 我们没有指定country_name,但是触发器完成了工作,并用country_name_eng填充了该值。
Now let’s create a trigger that shall fire upon the DELETE statement on the country table.
现在,让我们创建一个触发器,该触发器将在country表上的DELETE语句上触发。
DROP TRIGGER IF EXISTS t_country_delete;
GO
CREATE TRIGGER t_country_delete ON country INSTEAD OF DELETE
AS BEGIN
DECLARE @id INT;
DECLARE @count INT;
SELECT @id = id FROM DELETED;
SELECT @count = COUNT(*) FROM city WHERE country_id = @id;
IF @count = 0
DELETE FROM country WHERE id = @id;
ELSE
THROW 51000, 'can not delete - country is referenced in other tables', 1;
END;
For this trigger, it’s worth to emphasize the following:
对于此触发器,值得强调以下几点:
Running the below statement went without an error because the country with id = 6 had no related records.
运行下面的语句没有错误,因为id = 6的国家没有相关记录。
DELETE FROM country WHERE id = 6;
If we run this statement we’ll see a custom error message, as shown in the picture below.
如果运行此语句,我们将看到一个自定义错误消息,如下图所示。
DELETE FROM country WHERE id = 1;
Such a message is not only descriptive, but allows us to treat this error nicely and show a more meaningful message to the end-user.
这样的消息不仅具有描述性,还使我们能够很好地处理此错误,并向最终用户显示更有意义的消息。
I will leave this one to you, as a practice. So try to write down the UPDATE trigger. The important thing you should know is that in the update trigger you can use both – INSERTED (after update) and DELETED (before update) records. In almost all cases, you’ll need to use both of them.
作为练习,我将把这个留给您。 因此,请尝试写下UPDATE触发器。 您应该知道的重要一点是,在更新触发器中,可以同时使用– INSERTED(更新后)和DELETED(更新前)记录。 在几乎所有情况下,都需要同时使用它们。
Triggers share a lot in common with stored procedures. Still, compared to stored procedures they are limited in what you can do. Therefore, I prefer to have one stored procedure for insert/update/delete and make all checks and additional actions there.
触发器与存储过程有很多共同点。 但是,与存储过程相比,它们在执行操作方面受到限制。 因此,我更喜欢使用一个存储过程来进行插入/更新/删除,并在那里进行所有检查和其他操作。
Still, that is not always the option. If you inherited a system or you simply don’t want to put all the logic in the stored procedures, then triggers could a solution for many problems you might have.
尽管如此,这并不总是选择。 如果您继承了一个系统,或者只是不想将所有逻辑都放在存储过程中,那么触发器可以解决您可能遇到的许多问题。
Learn SQL: CREATE DATABASE & CREATE TABLE Operations | |
Learn SQL: INSERT INTO TABLE | |
Learn SQL: Primary Key | |
Learn SQL: Foreign Key | |
Learn SQL: SELECT statement | |
Learn SQL: INNER JOIN vs LEFT JOIN | |
Learn SQL: SQL Scripts | |
Learn SQL: Types of relations | |
Learn SQL: Join multiple tables | |
Learn SQL: Aggregate Functions | |
Learn SQL: How to Write a Complex SELECT Query? | |
Learn SQL: The INFORMATION_SCHEMA Database | |
Learn SQL: SQL Data Types | |
Learn SQL: Set Theory | |
Learn SQL: User-Defined Functions | |
Learn SQL: User-Defined Stored Procedures | |
Learn SQL: SQL Views | |
Learn SQL: SQL Triggers | |
Learn SQL: Practice SQL Queries | |
Learn SQL: SQL Query examples | |
Learn SQL: Create a report manually using SQL queries | |
Learn SQL: SQL Server date and time functions | |
Learn SQL: Create SQL Server reports using date and time functions | |
Learn SQL: SQL Server Pivot Tables | |
Learn SQL: SQL Server export to Excel | |
Learn SQL: Intro to SQL Server loops | |
Learn SQL: SQL Server Cursors | |
Learn SQL: SQL Best Practices for Deleting and Updating data | |
Learn SQL: Naming Conventions |
学习SQL:CREATE DATABASE&CREATE TABLE操作 | |
学习SQL:插入表 | |
学习SQL:主键 | |
学习SQL:外键 | |
学习SQL:SELECT语句 | |
学习SQL:INNER JOIN与LEFT JOIN | |
学习SQL:SQL脚本 | |
学习SQL:关系类型 | |
学习SQL:联接多个表 | |
学习SQL:聚合函数 | |
学习SQL:如何编写复杂的SELECT查询? | |
学习SQL:INFORMATION_SCHEMA数据库 | |
学习SQL:SQL数据类型 | |
学习SQL:集合论 | |
学习SQL:用户定义的函数 | |
学习SQL:用户定义的存储过程 | |
学习SQL:SQL视图 | |
学习SQL:SQL触发器 | |
学习SQL:练习SQL查询 | |
学习SQL:SQL查询示例 | |
学习SQL:使用SQL查询手动创建报告 | |
学习SQL:SQL Server日期和时间函数 | |
学习SQL:使用日期和时间函数创建SQL Server报表 | |
学习SQL:SQL Server数据透视表 | |
学习SQL:将SQL Server导出到Excel | |
学习SQL:SQL Server循环简介 | |
学习SQL:SQL Server游标 | |
学习SQL:删除和更新数据SQL最佳实践 | |
学习SQL:命名约定 |
翻译自: https://www.sqlshack.com/learn-sql-sql-triggers/
sql 触发器未触发