我有一个与T-SQL中的数据库触发器有关的问题。
我想创建一个触发器,仅允许将特定字词(可用,不可用)用于avalability
列。
怎么办?
我了解触发器是什么,但在命令序列中迷失了方向-应该在什么之后发生。
答案 0 :(得分:4)
不确定此处是否确实需要触发器。另一个解决方案是在相关列上创建一个CHECK
约束,例如:
ALTER TABLE TableName
ADD CONSTRAINT availability_check CHECK (availability IN ('available', 'not available'));
CREATE TABLE TableName (availability VARCHAR(20) );
ALTER TABLE TableName
ADD CONSTRAINT availability_check CHECK (availability IN ('available', 'not available'));
INSERT INTO TableName(availability) VALUES('foo');
-- Error
Msg 547 Level 16 State 0 Line 1
The INSERT statement conflicted with the CHECK constraint "availability_check". The conflict occurred in database "fiddle_325b8b256056466caf52aa4bb7467fd7", table "dbo.TableName", column 'availability'.
Msg 3621 Level 0 State 0 Line 1
The statement has been terminated.
答案 1 :(得分:4)
您可以ALTER
您的表并直接将CHECK Constraint
添加为
ALTER TABLE YourTableName
ADD CONSTRAINT CHK_Avalability CHECK(Avalability IN('Available', 'Not Available'));
请注意,如果表中已经插入了某些数据,但它们与CHECK Constraint
不匹配且冲突,则会引发错误。
如果您还没有CREATE
您的桌子,那么您可以使用
CREATE TABLE YourTableName(
Availability VARCHAR(20) NOT NULL
CONSTRAINT CHK_Avalability CHECK(Availability IN('Available', 'Not Available'))
);
答案 2 :(得分:2)
有两种方法可以解决此问题。
ALTER TABLE Table1 ADD CONSTRAINT CHK_Table1_Availability CHECK (Availability IN ('Available', 'Not Available'))
CREATE TRIGGER [dbo].[tr_availability_insert]
ON [dbo].[Table1]
INSTEAD OF INSERT
AS
BEGIN
BEGIN TRY
BEGIN TRANSACTION
SET NOCOUNT ON;
IF (inserted.Availability IN ('available', 'not available'))
BEGIN
INSERT INTO Table1(Id, Availability)
SELECT Id, Availability FROM inserted
END
COMMIT;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK
RETURN;
END CATCH
CREATE TRIGGER [dbo].[tr_availability_update]
ON [dbo].[Table1]
INSTEAD OF UPDATE
AS
BEGIN
BEGIN TRY
BEGIN TRANSACTION
SET NOCOUNT ON;
IF (inserted.Availability IN ('available', 'not available'))
BEGIN
UPDATE Table1
SET Availability = inserted.Availability
WHERE Table1.Id = inserted.Id;
END
COMMIT;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK
RETURN;
END CATCH
答案 3 :(得分:0)
CHECK约束是我要走的路。另一种方法是使用引用约束,即AKA主键和外键。如果在多个位置使用“可用”和“不可用”,则它比CHECK约束要好,因为您可以在多个表中实施相同的规则。这样,您可以强制保持一致性,并避免将某些表与其他值(例如“ available”和“ unavailable”)结合使用。
-- Lookup table for all possible "Availability" values
CREATE TABLE dbo.LU_Availability
(
AvailabilityPK VARCHAR(14) NOT NULL,
CONSTRAINT pk_LU_Availability PRIMARY KEY CLUSTERED(AvailabilityPK)
);
INSERT dbo.LU_Availability (AvailabilityPK) VALUES ('Available'),('Not Available');
-- Table with the allowable values enforced via foriegn key constraint
CREATE TABLE dbo.YourTable
(
someId INT IDENTITY,
someValue CHAR(10),
[Availability] VARCHAR(14) NOT NULL,
CONSTRAINT fk_AvailabilityTxt FOREIGN KEY([Availability])
REFERENCES dbo.LU_Availability(AvailabilityPK)
);
INSERT dbo.YourTable ([Availability]) VALUES ('Available'); -- Succeeds
INSERT dbo.YourTable ([Availability]) VALUES ('NOT Available'); -- Succeeds
INSERT dbo.YourTable ([Availability]) VALUES ('Perhaps'); -- Fails
最后-重要的是要理解,尽管约束(CHECK,PK,FK,UNIQUE)会稍微减慢速度,但触发器是性能的杀手。这就是为什么有经验的开发人员和DBA建议在约束能够解决问题时避免使用它们。