sql - 触发检查重复项

标签 sql database oracle triggers

我正在编写一个触发器,但遇到了一些问题。触发器执行和编译没有错误,但由于某些原因它没有完成我想要的工作。如果有人能帮助我。

问题是:

编写一个在插入、更新属性时执行的触发器。输入的每个属性都会根据具有相同属性的其他属性进行检查:代理人、所有者、地址,如果找到一个,则将属性状态更新为“双重”作为副本。

我正在插入相同的数据,它允许我这样做,但通常不会这样做!

这是我的表格:

create table Properties(  
            idProperties number(10) NOT NULL,
        Type varchar2(45) NOT NULL,
        SquareMeters varchar2(10) NOT NULL,
        Rooms number(10) NOT NULL,
        ConstructionDate date NOT NULL,
        FloorLocation varchar(20),
        Price number(10) NOT NULL,
        CityView varchar2(20),
        DateOfInsert date NOT NULL,
        DateOfExiration date NOT NULL,
        Address_FK number(20),
        Service_FK number(20),
        Ownership_FK number(20),
        Status_FK number(20),
        PropertyService_FK number(20))

create table Address(
          idAddress number(10) NOT NULL,
          address_name varchar2(20),
          City_FK number(20))


create table OwnerAgent(
           idOwnerAgent number(10) NOT NULL,
           Name varchar2(50)  NOT NULL,
           LastName varchar2(50)  NOT NULL,
           PhoneNr number(20),  
           Email varchar2(20),
           Sex varchar2(10),
           Profesion varchar2(20),
           Birthdate date,
           LastLogInDate date NOT NULL,
           Status varchar2(20),
           Address_FK number(20))

create table Ownership(
            idOwnership number(10) NOT NULL,
            PercentageOwed number(10)NOT NULL,
            RequiredPercentage number(10) NOT NULL,
        OwnerAgent_FK number(20))

这是我的触发器:

CREATE OR REPLACE TRIGGER Check_Duplicate
before insert or update on properties
FOR each ROW

declare
v_dup number;

begin
    select count(idProperties) INTO v_dup from properties where Address_FK=:NEW.Address_FK and 
     Ownership_FK=:NEW.Ownership_FK;

 if v_dup > 0 then
   Raise_Application_Error (-20100, 'This property already exists. The insert is cancelled.');
end if;
end;

谢谢。

最佳答案

一般来说,您不能在触发器中强制执行此类约束。您需要使用约束。

如果您尝试使用触发器,您将面临的问题是您通常会遇到“变异表”异常。通常,表 A 上的行级触发器(即 properties)无法查询表 A。您可以通过创建包、在该包中创建集合、在before 语句触发器,将插入或更新的键写入行级触发器中的集合,然后在 after 语句触发器中遍历集合的元素,并对表发出适当的 DML。然而,这涉及大量的移动部分和大量的复杂性(尽管如果您使用 11g 并且可以改用复合触发器,复杂性会降低)。

此外,如果您尝试使用触发器,您将在多用户环境中遇到问题。如果用户 A 在一个 session 中插入一行,而用户 B 在用户 A 提交之前在另一个 session 中插入重复的行,则两个 session 的触发器都不会检测到重复的行。您可以通过显式锁定父表中的一行来解决此类问题,以便序列化插入到表中(有意使应用程序变慢且可扩展性降低)。但约束将是一种更加有效和实用的解决方案。

综上所述,如果您使用 INSERT ... VALUES 语法仅执行单行插入并将自己限制在单个 session 中,您的触发器似乎确实有效

SQL> ed
Wrote file afiedt.buf

  1  create table Properties(
  2          idProperties number(10) NOT NULL,
  3          Address_FK number(20),
  4          Ownership_FK number(20)
  5* )
SQL> /

Table created.

SQL> CREATE OR REPLACE TRIGGER Check_Duplicate
  2  before insert or update on properties
  3  FOR each ROW
  4
  5  declare
  6  v_dup number;
  7
  8  begin
  9      select count(idProperties) INTO v_dup from properties where Address_FK=
:NEW.Address_FK and
 10       Ownership_FK=:NEW.Ownership_FK;
 11
 12   if v_dup > 0 then
 13     Raise_Application_Error (-20100, 'This property already exists. The inse
rt is cancelled.');
 14  end if;
 15  end;
 16  /

Trigger created.

SQL> insert into properties values( 1, 10, 100 );

1 row created.

SQL> insert into properties values( 2, 10, 100 );
insert into properties values( 2, 10, 100 )
            *
ERROR at line 1:
ORA-20100: This property already exists. The insert is cancelled.
ORA-06512: at "SCOTT.CHECK_DUPLICATE", line 9
ORA-04088: error during execution of trigger 'SCOTT.CHECK_DUPLICATE'

关于sql - 触发检查重复项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8482167/

相关文章:

oracle - 如何使Oracle ALTER TABLE MODIFY脚本具有幂等性?

MySQL 将行转为动态数量的列

c# - 从 SqlDataReader 创建 JSON 字符串

sql - 存在外键时违反外键约束

oracle - 流畅的 NHibernate 3 和 Oracle.DataAccess

oracle - I/O 资源计划

sql - 具有像 where 0=0 这样的条件的确切含义是什么?

mysql - 在 Rails 中获取 mysql 结果,但格式类似于 MySql 客户端界面

SQL Server 2005 错误 - ""MAX“不是可识别的表提示选项”

sql-server - 选择太多字段会导致表锁定吗?