【问题标题】:Trigger to update value with no of records触发以更新没有记录的值
【发布时间】:2021-04-13 10:38:42
【问题描述】:

试图设置一个触发器,但努力让它按我想要的方式工作,我想用为特定公司记录创建的机会记录来更新字段 oppo_pono 所以 1 家公司可以有多个机会,我想记录为公司创建的主机会的数量,因此为公司创建的第一个主 opp 将设置为 1,依此类推

我在下面设置了触发器,但它使用所有公司的计数设置 oppo_pono,而不是我正在为其创造机会的那个

下面是我的触发器

USE [CRM]
GO
/****** Object:  Trigger [dbo].[GeneratePNo]    Script Date: 1/7/2021 3:55:27 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER TRIGGER [dbo].[GeneratePNo]
ON [dbo].[Opportunity]
FOR insert
AS 

declare @OppPrimary Int
declare @company Int
declare @compid Int
declare @type nvarchar(40)
declare @childopp nchar(1)
declare @pono int

Select  @OppPrimary = Oppo_OpportunityId,
        @company = Oppo_PrimaryCompanyId,
        @compid = comp_companyid,
        @type = Oppo_Type,
        @childopp = oppo_childoppo,
        @pono = oppo_pono
FROM Inserted inner join company on Oppo_PrimaryCompanyId = @compid


Begin
    UPDATE [Opportunity] SET oppo_pono = (select count(*) from vSearchListOpportunity where Oppo_Deleted is null and @type = 'Master' and Oppo_PrimaryCompanyId = ) +1
WHERE Oppo_OpportunityId =@OppPrimary 

End

【问题讨论】:

  • 您的触发器有 MAJOR 缺陷,您似乎认为它会被 每行调用一次 - 事实并非如此。触发器将每条语句触发一次,因此如果您的INSERT 导致此触发器触发插入 25 行,您将触发触发器一次和@987654323 @ 伪表将包含 25 行。您的代码将从Inserted 中选择这 25 行中的哪一行?它是不确定的,您将获得任意行,而您将忽略所有其他行。您需要重写触发器以考虑到这一点!
  • 当机会被删除时会发生什么?然后你是否也重新编号所有其他人?
  • 不会真正删除任何主要商机,因为它们会有与其相关联的子商机

标签: sql sql-server tsql triggers


【解决方案1】:

正如 cmets 中所述,您没有考虑到具有多行的 inserted 伪表。您还有许多明显的语法错误。

编辑: 按照您的 cmets,我想我了解您要做什么。我的原始解决方案在这里不起作用,因为索引视图不能具有排名功能,但我已对其进行了修改以适应您的需要。

理想情况下,您不必关心实际的 ID 排列,只需使用 IDENTITY 列,但通常需要每个组的 ID 系列。

通常,具有正确索引的视图将是性能更高的选项,但这取决于您的需要。


使用视图

我将向您展示一种解决方案,该解决方案可用于通常需要触发器的许多不同类型的聚合。 如果您打算在分组中间删除一行时更改编号,这仅适用于您的问题。如果您希望保留编号,请改用触发器

我不确定OpportunityCompanyvSearchListOpportunity 的确切关系(似乎是对Opportunity 的看法),但您应该可以修改它以适应。

在数据上创建一个索引视图,并为每一行包含一个行号:

CREATE VIEW vOpportunityNumbered
AS
SELECT
    o.Oppo_OpportunityId,
    o.Oppo_PrimaryCompanyId,
    o.Oppo_Type,
    o.oppo_childoppo,
    ROW_NUMBER() OVER
        (PARTITION BY o.Oppo_PrimaryCompanyId ORDER BY o.Oppo_OpportunityId)
    -- Order by primary key to get deterministic ordering
FROM Opportunity AS o
WHERE o.Oppo_Deleted IS NULL;

GO

现在,为了支持这个视图,我们不能直接索引它,如前所述。但是,我们可以在支持它的基表上创建一个索引:

CREATE UNIQUE CLUSTERED INDEX opp_CompanyOpportunity
    ON Opportunity  (Oppo_PrimaryCompanyId, Oppo_OpportunityId) 
    -- note the ordering of the columns
    INCLUDE (Oppo_Type, oppo_childoppo)
    WITH (OPTIMIZE_FOR_SEQUENTIAL_KEY = ON) -- ONLY FOR SQL2019
;

GO

此视图现在将为每个不同的Company 提供Opportunity 的连续行编号。


触发器

如果您希望无论中间行发生什么情况,ID 始终保持不变,您将需要一个触发器(即,删除的行将在数字中留下空白)。

每个触发器都有两个表,inserteddeleted,其中包含已更改的数据。对于更新触发器,两个表都有数据,每个更改的行对应一行。

这意味着触发器在每个语句中执行一次,并且这些表包含所有相关行。但是,您不能直接更新它们;您必须将真实的表加入到它们中。

那么让我们来看看如何编写触发器。同样,我有点猜测表的关系:

CREATE OR ALTER TRIGGER [dbo].[GeneratePNo]
ON [dbo].[Opportunity]
AFTER INSERT  -- FOR is an alternative syntax, AFTER is more usual
AS 
-- No need for BEGIN and END, the whole batch until GO is the trigger
SET NOCOUNT ON;  -- Prevent DONE_IN_PROC rowcount messages

IF (NOT EXISTS (SELECT 1 FROM inserted))
    RETURN;   -- Bail-out early if no rows

-- We do not declare variables because we cannot store multiple rows in variables

UPDATE
    o
SET oppo_pono =
    ISNULL(  --If there are no other rows we would get a null
    (SELECT MAX(allO.oppo_pono)
        FROM Opportunity allO
    -- no need for the following two filters as the oppo_pono needs to be unique anyway
    -- where allO.Oppo_Deleted is null and allO.type = 'Master'
        WHERE allO.Oppo_PrimaryCompanyId = inserted.Oppo_PrimaryCompanyId
    ), 0) + 1

FROM inserted i
JOIN Opportunity o ON o.Oppo_OpportunityId = i.Oppo_OpportunityId;
-- We join inserted table on primary key always

GO

有更有效的方法来编写该更新,但这取决于您是否插入了很多行。 INSTEAD OF 触发器在这里的性能也会更高,但我没有尝试过,因为我没有你的表定义。

【讨论】:

  • 谢谢你 - 我将如何自动增加这个不?基本上我想要实现的是在 opp 记录(oppo_pono)上创建一个字段,每次针对公司创建新的主 opp 时,该字段都会自动递增(opp 表上有一个名为 oppo_type 的下拉列表字段,其中包含一个名为master) 所以针对一家公司创建了一个新的 master opp,它是第一个 oppo_pono 将设置为 01 然后为同一公司输入的下一个 master opp 将设置为 02 - 如果针对不同的公司创建了一个新的 master opp公司,那么它将被设置为 01
猜你喜欢
  • 2021-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多