验证触发器在 SQL 服务器中不起作用
Validation trigger not working in SQL Server
我正在为一个 class 项目开发触发器。
我有一个名为 salesman
的 table 和一个名为 type
的列。 table 中的所有员工当前的 type
为 full
、part
或 temp
。
触发器的目的是检查新插入行的 type
并确保它与已存在的三个行之一匹配。如果是,则应允许插入,否则应停止或回滚。感谢您提出任何想法!
这是代码的最新排列。
CREATE TRIGGER trg_validate_emp_type
ON salesman
FOR INSERT
AS
BEGIN
DECLARE @job varchar (20)
SELECT @job = (SELECT type FROM inserted)
IF NOT EXISTS (SELECT 1 FROM salesman WHERE UPPER(type) = UPPER(@job))
BEGIN
ROLLBACK TRANSACTION
PRINT 'employee type not valid'
END
END
如果您想检查列的值,有更有效的方法。
最佳实践是定义约束。
当值存储在 table 中时,则使用 FOREIGN KEY 约束;在其他情况下使用 CHECK 约束。
正如几个人所指出的,这看起来像是检查约束或外键的工作。
例如
create table salesman(id int primary key, type varchar(20) check (type in ('a','b')))
或
create table salesman_type (type varchar(20) primary key )
create table salesman(id int primary key, type varchar(20) references salesman_type)
但如果您真的想编写一个触发器来阻止插入 table 中尚不存在的值,您可以这样做:
use tempdb
go
create table salesman
(
id int identity primary key,
type varchar(20) not null,
index ix_salesman_type(type)
)
insert into salesman(id,type) values (1,'a')
insert into salesman(id,type) values (2,'b')
go
CREATE OR ALTER TRIGGER trg_validate_emp_type
ON salesman
FOR INSERT
AS
BEGIN
IF EXISTS
(
SELECT *
FROM inserted
WHERE type not in
(
select type
from salesman
where id not in (select id from inserted)
)
)
BEGIN
throw 50001, 'employee type not valid', 1;
END
END
go
insert into salesman(id,type) values (3,'c') -- fails
insert into salesman(id,type) values (3,'a') -- succeeds
由于 XACT_ABORT 在触发器中默认为 ON,您可以简单地 THROW 而不是 ROLLBACK + PRINT,并且客户端会收到更好的错误消息。
我正在为一个 class 项目开发触发器。
我有一个名为 salesman
的 table 和一个名为 type
的列。 table 中的所有员工当前的 type
为 full
、part
或 temp
。
触发器的目的是检查新插入行的 type
并确保它与已存在的三个行之一匹配。如果是,则应允许插入,否则应停止或回滚。感谢您提出任何想法!
这是代码的最新排列。
CREATE TRIGGER trg_validate_emp_type
ON salesman
FOR INSERT
AS
BEGIN
DECLARE @job varchar (20)
SELECT @job = (SELECT type FROM inserted)
IF NOT EXISTS (SELECT 1 FROM salesman WHERE UPPER(type) = UPPER(@job))
BEGIN
ROLLBACK TRANSACTION
PRINT 'employee type not valid'
END
END
如果您想检查列的值,有更有效的方法。 最佳实践是定义约束。 当值存储在 table 中时,则使用 FOREIGN KEY 约束;在其他情况下使用 CHECK 约束。
正如几个人所指出的,这看起来像是检查约束或外键的工作。
例如
create table salesman(id int primary key, type varchar(20) check (type in ('a','b')))
或
create table salesman_type (type varchar(20) primary key )
create table salesman(id int primary key, type varchar(20) references salesman_type)
但如果您真的想编写一个触发器来阻止插入 table 中尚不存在的值,您可以这样做:
use tempdb
go
create table salesman
(
id int identity primary key,
type varchar(20) not null,
index ix_salesman_type(type)
)
insert into salesman(id,type) values (1,'a')
insert into salesman(id,type) values (2,'b')
go
CREATE OR ALTER TRIGGER trg_validate_emp_type
ON salesman
FOR INSERT
AS
BEGIN
IF EXISTS
(
SELECT *
FROM inserted
WHERE type not in
(
select type
from salesman
where id not in (select id from inserted)
)
)
BEGIN
throw 50001, 'employee type not valid', 1;
END
END
go
insert into salesman(id,type) values (3,'c') -- fails
insert into salesman(id,type) values (3,'a') -- succeeds
由于 XACT_ABORT 在触发器中默认为 ON,您可以简单地 THROW 而不是 ROLLBACK + PRINT,并且客户端会收到更好的错误消息。