0

我需要设置用户在一个月内输入 5 条记录后无法输入任何记录的约束。是否建议我为此编写触发器或过程?否则我可以设置约束的任何其他方式吗?

我没有编写触发器,而是选择为约束编写一个过程,但我如何检查该过程是否有效?

以下是程序:

CREATE OR REPLACE PROCEDURE InsertReadingCheck
        (
         newReadNo          In Int,
         newReadValue       In Int,
         newReaderID        In Int,
         newMeterID         In Int  
        )
AS 
  varRowCount               Int;

BEGIN

Select Count(*) INTO varRowCount
From Reading 
WHERE ReaderID = newReaderID
AND Trunc(ReadDate,'mm') = Trunc(Sysdate,'mm');     

IF (varRowCount >= 5) THEN
    BEGIN
        DBMS_OUTPUT.PUT_LINE('*************************************************');
        DBMS_OUTPUT.PUT_LINE('');
        DBMS_OUTPUT.PUT_LINE(' You attempting to enter more than 5 Records ');
        DBMS_OUTPUT.PUT_LINE('');
        DBMS_OUTPUT.PUT_LINE('*************************************************');
        ROLLBACK;
  RETURN;
    END;

ELSIF (varRowCount < 5) THEN
    BEGIN
        INSERT INTO Reading
            VALUES(seqReadNo.NextVal, sysdate, newReadValue,
            newReaderID, newMeterID);
  COMMIT;
END;
END IF;
END; 

谁能帮我看看

4

4 回答 4

2

这是您应该避免触发的事情。尤其是 ROLLBACK 和 COMMIT。这似乎非常危险(我什至不确定这是否可能)。您可能有其他希望提交的事务回滚,反之亦然。

此外,通过将其放入触发器中,您收到以下错误:

ORA-04091: 表 XXXX 正在变异,触发器/函数可能看不到它

有一些方法可以解决这个问题,但它们太过分了,并且涉及到做一些时髦的事情来绕过 Oracle 坚持你做正确的事情。

这是使用存储过程将数据插入表中的绝佳机会。您可以在执行插入之前检查当前记录的数量,这意味着不需要执行回滚。

于 2012-11-12T08:53:21.740 回答
0

这是一种行为约束。这是一个见仁见智的问题,但我宁愿将这种业务逻辑保留在您的数据库之外。相反,我会跟踪谁在记录表中添加了哪些记录,以及在什么日期/时间。您可以有一个 SP 来获取此信息,但是您的代码应该根据返回的数据处理用户是否可以看到某些链接(或函数)。这是否意味着阻止用户访问他们插入记录的页面,或者给他们只读视图取决于您。

于 2012-11-12T04:15:22.983 回答
0

这取决于您的应用程序,如果您的应用程序中已经多次插入,那么触发器是更好的选择。

于 2012-11-12T04:21:34.993 回答
0

解决此问题的一种声明性方法将遵守所有并发规则,即使用单独的表来跟踪每个用户每月的插入次数:

create table inserts_check (
  ReaderID integer not null,
  month date not null,
  number_of_inserts integer constraint max_number_of_inserts check (number_of_inserts <= 5),
  primary key (ReaderID, month)
);

然后在表(或所有表)上创建一个触发器,为其插入上限为 5:

create trigger after insert on <table>
for each row
begin
  MERGE INTO inserts_check t
  USING (select 5 as ReaderID, trunc(sysdate, 'MM') as month, 1 as number_of_inserts from dual) s
  ON (t.ReaderID = s.ReaderID and t.month = s.month)
  WHEN MATCHED THEN UPDATE SET t.number_of_inserts = t.number_of_inserts + 1
  WHEN NOT MATCHED THEN INSERT (ReaderID, month, number_of_inserts)
  VALUES (s.ReaderID, s.month, s.number_of_inserts);
end;

一旦用户进行了 5 次插入,约束max_number_of_inserts将失败。

于 2012-11-12T10:34:38.060 回答