sql-server - SQL Server 触发器:限制记录插入
问题描述
我正在为大学工作做一个数据库。在某些时候,我们必须创建一个触发器/函数来限制在我的 SQL Server Management Studio 17 上插入记录,同时考虑到不同的外键。例如,我们可以有 100 条记录,但对于同一个外键,我们只能有 50 条记录。
我们有这个约束:
CREATE TABLE [dbo].[DiaFerias] WITH CHECK
ADD CONSTRAINT [Verificar22DiasFerias]
CHECK (([dbo].[verificarDiasFerias]((22)) ='True'))
借助此功能:
ALTER FUNCTION [dbo].[verificarDiasFerias] (@contagem INT)
RETURNS VARCHAR(5)
AS
BEGIN
IF EXISTS (SELECT DISTINCT idFuncionario, idDiaFerias
FROM DiaFerias
GROUP BY idFuncionario, idDiaFerias
HAVING COUNT(*) <= @contagem)
RETURN 'True'
RETURN 'False'
END
解决方案
我会在这里使用触发器吗?不情愿地,是的(请参阅强制最大数量的子行了解如何在没有触发器的情况下执行此操作,我绝不会推荐这种方式)。我会使用那个功能吗?不。
我会创建一个索引视图:
CREATE VIEW dbo.DiaFerias_Counts
WITH SCHEMABINDING
AS
SELECT idFuncionario, idDiaFerias, COUNT_BIG(*) as Cnt
FROM dbo.DiaFerias
GROUP BY idFuncionario, idDiaFerias
GO
CREATE UNIQUE CLUSTERED INDEX PK_DiaFerias_Counts on
dbo.DiaFerias_Counts (idFuncionario, idDiaFerias)
为什么要这样做?这样 SQL Server 会自动为我们维护这些计数,因此我们不必在触发器中编写范围广泛的查询。我们现在可以编写触发器,例如:
CREATE TRIGGER T_DiaFerias
ON dbo.DiaFerias
AFTER INSERT, UPDATE
AS
SET NOCOUNT ON;
IF EXISTS (
SELECT
*
FROM dbo.DiaFerias_Counts dfc
WHERE
dfc.Cnt > 22
AND
(EXISTS (select * from inserted i
where i.idFuncionario = dfc.idFuncionario AND i.idDiaFerias = dfc.idDiaFerias)
OR EXISTS (select * from deleted d
where d.idFuncionario = dfc.idFuncionario AND d.idDiaFerias = dfc.idDiaFerias)
)
)
BEGIN
RAISERROR('Constraint violation',16,1)
END
希望你能看到它是如何工作的——我们只想查询可能受到任何导致我们触发的因素影响的项目的计数——所以我们使用inserted
并deleted
限制我们的搜索。
如果任何计数大于 22,我们将拒绝更改,这与您的函数不同,它仅在每个计数大于 22 时才开始拒绝行。
推荐阅读
- python - 使用 Python 请求会话发出多个请求时权限被拒绝
- http - 我可以使用 netlify 的 CDN 来阻止 lambda 一天多次执行吗?
- php - 在 ec2 中安装 PHP 7
- openocd - openocd 无法加载 board/ti_cc26x0_launchpad.cfg
- r - R Shiny conditional dateInput for each checkboxGroupInput selected
- javascript - 为什么谷歌recaptcha不允许我点击移动版chrome开发者工具中的复选框
- java - MySQL JDBC 查询比 JMH 测试中的查询要快得多
- php - SQL操作VS wp_update_term_count_now()相关问题
- javascript - Auto Scramble Chrome Cube 实验室?
- laravel - 如何让 LaraDock 使用 yum 而不是 apt-get?