sqlserver- 触发器

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_43650411/article/details/102258716

目录

  • 测试数据生成
  • 约束- 增加/修改
  • 触发器TRIGGER
  1. after (for)
  2. instead of
  3. 触发事件查询
  • 拓展- RAISERROR
  • 拓展- sys.开头表单详细描述

在这里插入图片描述

-- 注1:在表survey中增加自增主键Id列
-- 注2:增加辅表question_log
-- 注3:增加辅表test_insert
-- 测试数据
USE master
GO

IF EXISTS(SELECT * FROM master.dbo.sysdatabases WHERE name='LeetCode')
	BEGIN
		DROP DATABASE LeetCode
		SELECT 1
	END
GO
CREATE DATABASE LeetCode
GO
USE LeetCode
GO

-- 新建数据表
-- 注意约束
-- IF EXISTS(SELECT * FROM sysobjects WHERE name='survey_log')
IF (OBJECT_ID('survey_log', 'U') IS NOT Null)
	DROP TABLE survey_log
GO
CREATE TABLE survey_log
(
	Id INT IDENTITY
		CONSTRAINT PK_surveyLog PRIMARY KEY,
	uid INT,
	action VARCHAR(20) 
		CONSTRAINT Check_action 
		--CHECK(action IN ('show', 'skip', 'answer')),
		CHECK(action='show' or action='answer' or action='skip'),
	--action VARCHAR(20),
	--CONSTRAINT Check_action CHECK(action in ('show', 'answer', 'skip')),
	question_id INT,
	answer_id INT,
	q_num INT,
	timestamp INT,
	date DATETIME 
		CONSTRAINT Default_date DEFAULT GETDATE()
)
GO

-- 查询 自定义对象
SELECT *
FROM sysobjects
WHERE xtype NOT IN ('S', 'IT', 'SQ')

在这里插入图片描述

-- 查询 表数据
SELECT *
FROM survey_log

在这里插入图片描述

-- 查询 表信息
EXEC sp_help survey_log

在这里插入图片描述

-- 查询表 列
EXEC sp_columns survey_log

在这里插入图片描述

-- 新建表后,增加约束
-- 增加约束 Default
ALTER TABLE survey_log
ADD CONSTRAINT Default_date
DEFAULT GETDATE() FOR date
GO

-- 修改约束 Default
-- IF (EXISTS(SELECT * FROM sysobjects WHERE name='Default_date'))
IF (OBJECT_ID('Default_date', 'D') IS NOT NULL)
	ALTER TABLE survey_log DROP CONSTRAINT Default_date
GO
ALTER TABLE survey_log
ADD CONSTRAINT Default_date
DEFAULT DATEADD(DD, 1, GETDATE()) FOR date
GO

-- 增加约束 NOT NULL
ALTER TABLE survey_log
ALTER COLUMN uid INT NOT NULL
GO

-- 增加/修改 CHECK
IF (OBJECT_ID('Check_action', 'C') IS NOT NULL)
	ALTER TABLE survey_log DROP CONSTRAINT Check_action
GO
ALTER TABLE survey_log
ADD CONSTRAINT Check_action
CHECK (action IN ('answer', 'skip', 'show'))

-- 1. 后触发(after; for):插入,删除,更新
-- 2. 前触发:
-- 插入后
--
-- 测试表:插入数据保存测试
IF (OBJECT_ID('test_insert', 'U') IS NOT NULL)
	DROP TABLE test_insert
GO
CREATE TABLE test_insert
(	
	Id INT,
	uid INT,
	question_id INT,
	date DATETIME
)
GO
-- 1)检查 action='answer'-> answer_id='' NOT NULL; 
-- 2)action='skip' & 'show'->  answer_id is NULL 
IF OBJECT_ID('tgr_surveyLog_insert', 'TR') is NOT NULL
	DROP TRIGGER tgr_surveyLog_insert
GO
CREATE TRIGGER tgr_surveyLog_insert
ON survey_log
	--AFTER INSERT
	FOR INSERT
AS
	DECLARE @act1 VARCHAR(20),
			@act2 VARCHAR(20),
			@act3 VARCHAR(20),
			@uid INT,
			@question_id INT
	-- 在inserted表中,查询已插入记录
	-- SELECT @uid=uid, @question_id=question_id FROM inserted
	INSERT INTO test_insert SELECT Id, uid, question_id, GETDATE() FROM inserted
	SET @act1 = 'answer'
	SET	@act2 = 'skip'
	SET	@act3 = 'show'
	IF EXISTS(SELECT * FROM survey_log WHERE action=@act1)
		BEGIN
			UPDATE survey_log 
			SET answer_id = 
				CONVERT(INT, 
				CONVERT(VARCHAR, timestamp) + 
				CONVERT(VARCHAR, timestamp)
				)
			WHERE action=@act1  -- All?? ==> YES
		END
	ELSE IF EXISTS(SELECT * FROM survey_log WHERE action=@act2 OR action=@act3)
		BEGIN
			UPDATE survey_log 
			SET answer_id=(SELECT NULL) 
			WHERE action=@act2 
				OR action=@act3
		END
GO
-- 测试
INSERT INTO survey_log(uid, action, question_id, answer_id, q_num, timestamp)
VALUES
	(5, 'show', 285, null, 1, 123),
	(5, 'answer', 285, 124124, 1, 124),
	(5, 'show', 369, null, 2, 125),
	(5, 'skip', 369, 1, 2, 126),
	(5, 'show', 377, 1, 2, 127),
	(5, 'answer', 333, 1, 1, 128)
GO
SELECT *
FROM survey_log
--WHERE answer_id IS NOT NULL
GO



-- 2. 删除数据触发:保留删除数据
IF (OBJECT_ID('surveyLogBackup', 'U') IS NOT NULL)
--IF (EXISTS (SELECT * FROM sysobjects WHERE name='surveyLogBackup'))
	DROP TABLE surveyLogBackup
	SELECT * FROM sysobjects WHERE xtype NOT IN('S', 'IT', 'SQ')
GO
IF (OBJECT_ID('tgr_surveyLog_delete', 'TR') IS NOT NULL)
	DROP TRIGGER tgr_surveyLog_delete
	SELECT 1 AS 'tgr_surveyLog_delete'
GO
CREATE TRIGGER tgr_surveyLog_delete
ON survey_log
	FOR DELETE
AS
	BEGIN
		PRINT '备份中……'
		IF (OBJECT_ID('surveyLogBackup', 'U') IS NULL)
			-- 存在surveyLogBackup直接插入
			SELECT * INTO surveyLogBackup FROM deleted
		ELSE
			INSERT INTO surveyLogBackup SELECT * FROM deleted
		-- 查询deleted表
		SELECT * FROM deleted
		PRINT '备份完毕!'
	END
GO
-- 测试
-- SET NOCOUNT ON
DELETE FROM survey_log
GO
SELECT * FROM survey_log  


-- 3. 更新后触发
-- 输出更新前后的数据,并检查是否符合表单要求:action<>'answer' -> answer_id = NULL
-- 否则,answer_id = CONVERT(INT, CONVERT(VARCHAR(20), timestamp)+CONVERT(VARCHAR(20), timestamp))
-- 
IF (OBJECT_ID('tgr_surveyLog_update', 'TR') IS NOT NULL)
	DROP TRIGGER tgr_surveyLog_update
	SELECT 1 AS 'tgr_surveyLog_update'
GO
CREATE TRIGGER tgr_surveyLog_update
ON survey_log
	--AFTER UPDATE
	FOR UPDATE
AS
	BEGIN
	-- 更新前
	-- 1. 假设更新后的值不符合预设要求,自动恢复
	-- 2. 不能修改表inserted、updated,手动增加辅助表
	IF (OBJECT_ID('before_up1', 'U') IS NULL)
		SELECT * INTO before_up1 FROM inserted
	UPDATE survey_log SET answer_id=
		(
		CASE
			WHEN action='answer' 
				THEN CONVERT(INT, CONVERT(VARCHAR(20), timestamp)+CONVERT(VARCHAR(20), timestamp))
			ELSE (SELECT NULL)
		END
		)
	WHERE Id IN (SELECT Id FROM inserted)
	SELECT * FROM deleted
	-- 更新后
	SELECT *, GETDATE() AS TT FROM inserted
	PRINT '用于联级修改表单数据'
	END
GO
-- 测试
UPDATE survey_log
SET timestamp=121
WHERE uid=5
	AND question_id=285
	AND action='answer'
GO
SELECT *
FROM survey_log
GO


-- 4. 更新列级触发器
-- 拓展:RAISERROR
IF (OBJECT_ID ('tgr_surveyLogRow_update', 'TR') IS NOT NULL)
	DROP TRIGGER tgr_surveyLogRow_update
GO
CREATE TRIGGER tgr_surveyLogRow_update
ON survey_log
	FOR UPDATE
AS
	-- 列级触发器
	IF (UPDATE(date))
	BEGIN
		RAISERROR('%s 系统提示:不能修改!', 11, 1, '呵')
		ROLLBACK TRAN
	END
GO
-- 测试
UPDATE survey_log
SET date=DATEADD(DD, 2, GETDATE())
WHERE Id>10

-- 5. INSTEAD OF
-- instead of触发器表示并不执行其定义的操作(insert、update、delete)而仅是执行触发器本身的内容
--
-- 辅表 question_log
SELECT question_id, action, q_num
	INTO question_log
FROM survey_log
GO
SELECT * 
FROM question_log
GO
-- 
-- instead of
IF (OBJECT_ID ('tgr_questionLog_insteadOf_d', 'TR') IS NOT NULL)
	DROP TRIGGER tgr_questionLog_insteadOf_d
GO
CREATE TRIGGER tgr_questionLog_insteadOf_d
ON question_log
--WITH ENCRYPTION  -- 加密
	INSTEAD OF DELETE
AS
	BEGIN
	DELETE FROM survey_log WHERE question_id IN (SELECT question_id FROM deleted)
	DELETE FROM question_log
	PRINT 'Deleted'
	END
GO
-- test
DELETE FROM question_log
GO
  • 其它
-- Tips
-- 1. 如何拼接两个数字?
-- s1: SELECT CONVERT(INT, CONVERT(VARCHAR, 12)+CONVERT(VARCHAR, 12))
-- s2: SELECT CAST((CAST(12 AS VARCHAR) + CAST(12 AS VARCHAR)) AS INT)
-- 2. 如何赋值为null?
-- SET @a = (SELECT NULL)
-- 自定义 RAISERROR

IF (OBJECT_ID('tgr_message', 'TR') IS NOT NULL)
	DROP TRIGGER tgr_message
GO
CREATE TRIGGER tgr_message
ON survey_log
	AFTER INSERT, UPDATE
AS
	BEGIN
		DECLARE @date DATE
		--SET @date = (SELECT CONVERT(VARCHAR(20), CONVERT(DATE, GETDATE())))
		RAISERROR('%s tgr_message 触发', 16, 10, '@date')
	END
GO
-- Test
-- 第1次是此处的insert触发,第2次触发是触发器tgr_surveyLog_insert检查更新时触发
-- Test
-- 关闭触发器
DISABLE TRIGGER tgr_surveyLog_insert ON survey_log
GO
INSERT INTO survey_log(uid, action, question_id, answer_id, q_num, timestamp)
VALUES
	(1, 'answer', 1, 1, 1, 114)
GO
-- 启动触发器
ENABLE TRIGGER tgr_surveyLog_insert ON survey_log
GO
SELECT *
FROM survey
GO
SELECT *
FROM question_log
GO

在这里插入图片描述
在这里插入图片描述

-- 触发事件查询
SELECT te.* 
FROM sys.trigger_events te
	JOIN sys.triggers t
	ON te.object_id=t.object_id
WHERE t.parent_class=1
	AND t.name='tgr_message'

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43650411/article/details/102258716