一张表Cd_Completion_t的非主键字段Completion_Description 要实现唯一性约束,因实际需要,字段Completion_Description 可以为空,可以为多个t,但是只允许有一个T,因此无法建唯一性索引,请问用触发器如何实现,我的触发器如下,但同时修改一下两条记录时有问题:
XJ7XVXqgzN t
XJ7XVXqgzN TCreate Or Replace Trigger Tg_Completion_Test
After Insert Or Update On Cd_Completion_t
Declare
Too_Many Exception;
Pragma Exception_Init(Too_Many, -20001);
v_Exist_Count Number := 0;
Begin
Begin
Select max(Count(*))
Into v_Exist_Count
From Cd_Completion_t t
Where t.Completion_Description = 'T'
Group By t.Well_Id;
Exception
When Others Then
v_Exist_Count := 0;
End;
If v_Exist_Count > 1 Then
Raise_Application_Error(-20001, '该井只能有一个主要生产层(T)!');
End If;
End;
XJ7XVXqgzN t
XJ7XVXqgzN TCreate Or Replace Trigger Tg_Completion_Test
After Insert Or Update On Cd_Completion_t
Declare
Too_Many Exception;
Pragma Exception_Init(Too_Many, -20001);
v_Exist_Count Number := 0;
Begin
Begin
Select max(Count(*))
Into v_Exist_Count
From Cd_Completion_t t
Where t.Completion_Description = 'T'
Group By t.Well_Id;
Exception
When Others Then
v_Exist_Count := 0;
End;
If v_Exist_Count > 1 Then
Raise_Application_Error(-20001, '该井只能有一个主要生产层(T)!');
End If;
End;
AFTER INSERT OR UPDATE ON Cd_Completion_t
FOR EACH ROW --行触发,没有本行则为语句级触发
DECLARE
Too_Many EXCEPTION;
PRAGMA EXCEPTION_INIT(Too_Many, -20001);
v_Exist_Count NUMBER := 0;
BEGIN
BEGIN
SELECT MAX(COUNT(*))
INTO v_Exist_Count
FROM Cd_Completion_t t
WHERE t.Completion_Description = 'T'
GROUP BY t.Well_Id;
EXCEPTION
WHEN OTHERS THEN
v_Exist_Count := 0;
END;
IF v_Exist_Count > 1 THEN
Raise_Application_Error(-20001, '该井只能有一个主要生产层(T)!');
END IF;
END;
Select max(Count(*))
Into v_Exist_Count
From Cd_Completion_t t
Where t.Completion_Description = 'T'
Group By t.Well_Id;
Exception
When Others Then
v_Exist_Count := 0;
End;
If v_Exist_Count > 1 Then
Raise_Application_Error(-20001, '该井只能有一个主要生产层(T)!');
End If;改为:
Begin
Select Count(*)
Into v_Exist_Count
From Cd_Completion_t t
Where t.Completion_Description = 'T'
Exception
When Others Then
v_Exist_Count := 0;
End;
If v_Exist_Count > 1 Then
Raise_Application_Error(-20001, '该井只能有一个主要生产层(T)!');
End If;
AFTER INSERT OR UPDATE ON Cd_Completion_t
FOR EACH ROW --行触发,没有本行则为语句级触发
DECLARE
Too_Many EXCEPTION;
PRAGMA EXCEPTION_INIT(Too_Many, -20001);
v_Exist_Count NUMBER := 0;
BEGINBegin
Select max(Count(*))
Into v_Exist_Count
From Cd_Completion_t t
Where t.Completion_Description = 'T'
Group By t.Well_Id;
Exception
When Others Then
v_Exist_Count := 0;
End;
If v_Exist_Count > 1 Then
Raise_Application_Error(-20001, '该井只能有一个主要生产层(T)!');
End If;改为:
CREATE OR REPLACE TRIGGER Tg_Completion_Test
AFTER INSERT OR UPDATE ON Cd_Completion_t
FOR EACH ROW --行触发,没有本行则为语句级触发
DECLARE
Too_Many EXCEPTION;
PRAGMA EXCEPTION_INIT(Too_Many, -20001);
v_Exist_Count NUMBER := 0;
BEGINBegin
Select Count(*)
Into v_Exist_Count
From Cd_Completion_t t
Where t.Completion_Description = 'T'
and t.Well_Id=:new.Well_Id
Exception
When Others Then
v_Exist_Count := 0;
End;
If v_Exist_Count > 1 Then
Raise_Application_Error(-20001, '该井只能有一个主要生产层(T)!');
End If;
或者以下情况:
第一条为t,第二条为T,我现在同时修改第一条为T,第二条为t
以上各位的写法貌似都无法实现。
同志们,继续……
CREATE OR REPLACE TRIGGER Tg_Completion_Test
AFTER INSERT OR UPDATE ON Cd_Completion_t
FOR EACH ROW
WHEN (new.Completion_Description='T')
DECLARE
Too_Many EXCEPTION;
PRAGMA EXCEPTION_INIT(Too_Many, -20001);
PRAGMA AUTONOMOUS_TRANSACTION;
v_Exist_Count NUMBER := 0;
BEGIN
SELECT COUNT(*)
INTO v_Exist_Count
FROM Cd_Completion_t t
WHERE t.Completion_Description = 'T'
AND t.well_id = :new.well_id;
IF v_Exist_Count > 0 THEN
Raise_Application_Error(-20001, '该井只能有一个主要生产层(T)!');
END IF;
END;
/
第一条为t,第二条为T,我现在同时修改第一条为T,第二条为t
我现在最纠结的就是这一条有问题。
第一条为t,第二条为T,我现在同时修改第一条为T,第二条为t
我现在最纠结的就是这一条有问题。
Create unique index idx_cd_completon_t
on cd_completion_t(Case when completion_description = 'T' then WELL_ID End);
利用oracle自带的创建索引,也无法解决上面我说的那个同时改两条数据的问题,崩溃啊。
这种情况是符合你的规则,还是违反你的规则?
update cd_completion_t set completion_description = 't' where 第二条这种情况认为应该是符合你的规则?
所以你的触发器应该是一个before触发器;2.在update之后,检查表里面的T的数据数量,如果大于1条,那么回滚刚刚的更新,
所以应该建立一个after触发器;3.不过还是觉得麻烦,还是使用存储过程比较好些吧!