版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
目录
- 测试数据生成
- 约束- 增加/修改
- 触发器TRIGGER
- after (for)
- instead of
- 触发事件查询
- 拓展- 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
-- 自定义 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'
- 拓展:sqlserver sys.开头的表单说明