编写程序以强制执行约束+测试

时间:2012-11-12 04:09:14

标签: oracle plsql triggers

我需要设置一个约束,即用户在一个月内输入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 个答案:

答案 0 :(得分:2)

这是你应该避免放入触发器的事情。特别是ROLLBACK和COMMIT。这似乎非常危险(我甚至不确定它是否可能)。您可能有其他事务要提交以进行回滚,反之亦然。

此外,通过将其置于触发器中, 将会出现以下错误:

  

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

There are ways round this但他们过分并且涉及做一些时髦的事情,以便绕过甲骨文坚持你做正确的事情。

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

答案 3 :(得分: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将失败。