2

我是触发器的新手,我似乎无法找到这个问题的答案。

我需要在表中插入计算的行并且无法访问应用程序源代码。我认为解决方法可能是在表上创建一个触发器以根据插入的值计算值,然后将它们插入表中,尽管我不确定这是如何工作的。

我有以下触发器,它适用于更新,但不适用于插入。如果我在“FOR INSERT, UPDATE”中删除“INSERT”,它将插入 account_id 字段(这是唯一的非空字段),但不会插入其余字段。如果我留下“INSERT”,它不会插入任何字段。

我怎样才能使这对插入和更新都有效?

ALTER TRIGGER [dbo].[SelfCalFieldsTrigger]
ON [dbo].[dynTable]
FOR INSERT, UPDATE
AS
BEGIN

Declare @acctID uniqueidentifier
Declare @invDiscPremPerc decimal(9,6)
Declare @investorSRP decimal(9,6)
Declare @purchWireAmt decimal(11,2)

set @acctID = (Select account_id from inserted) 

set @invDiscPremPerc = (Select Coalesce(INVESTOR_DISC_PREM_DOLLAR, 0)/
Coalesce(INVESTOR_PRIN_BAL_PURCHASED, 0)*100 from inserted)


set @investorSRP = (Select Coalesce(INVESTOR_SRP_PREM_DOLLAR, 0)/
Coalesce(INVESTOR_PRIN_BAL_PURCHASED, 0)*100 from inserted)


set @purchWireAmt = (Select Coalesce(INVESTOR_PRIN_BAL_PURCHASED, 0)-
Coalesce(INVESTOR_ADMIN_FEE, 0)-
Coalesce(INVESTOR_WIRE_FEE, 0)- Coalesce(INVESTOR_FLOOD_FEE, 0)-
Coalesce(INVESTOR_TAX_SERVICE_FEE, 0) - Coalesce(INVESTOR_OTHER_FEE, 0) from     
inserted)


UPDATE [dbo].dynTable]
set INVESTOR_DISC_PREM_PERCENT = @invDiscPremPerc,
INVESTOR_SRP = @investorSRP,
PURCHASE_WIRE_AMOUNT = @purchWireAmt
Where [dbo].[dynTable].Account_ID = @acctID

END
4

3 回答 3

3

您需要更改触发器的逻辑。现在,您假设只有一行插入或更新,但这不是它的工作方式。INSERTED是一个伪表,包含所有插入或更新的行。所以,试试这个:

ALTER TRIGGER [dbo].[SelfCalFieldsTrigger]
ON [dbo].[dynTable]
FOR INSERT, UPDATE
AS
BEGIN

    UPDATE A
    SET INVESTOR_DISC_PREM_PERCENT = ISNULL(B.INVESTOR_DISC_PREM_DOLLAR / 
                                            NULLIF(B.INVESTOR_PRIN_BAL_PURCHASED,0)*100,0),
    INVESTOR_SRP = ISNULL(B.INVESTOR_SRP_PREM_DOLLAR / 
                          NULLIF(B.INVESTOR_PRIN_BAL_PURCHASED,0)*100,0),
    PURCHASE_WIRE_AMOUNT =  COALESCE(B.INVESTOR_PRIN_BAL_PURCHASED, 0)-
                            COALESCE(B.INVESTOR_ADMIN_FEE, 0)-
                            COALESCE(B.INVESTOR_WIRE_FEE, 0)- 
                            COALESCE(B.INVESTOR_FLOOD_FEE, 0)-
                            COALESCE(B.INVESTOR_TAX_SERVICE_FEE, 0)- 
                            COALESCE(B.INVESTOR_OTHER_FEE, 0)
    FROM [dbo].[dynTable] A
    INNER JOIN INSERTED B
        ON A.Account_ID = B.Account_ID

END
于 2013-09-10T14:11:50.267 回答
0

我同意上述评论。插入的表可以有 1 到 n 行。

除了触发器之外,我还有另外两个建议。

您可以创建一个函数来将业务逻辑包装在一个整洁的包中。

1-您可以更改表设计并添加持久计算列吗?

在设计中使用上述功能。

2 - 如何在 SELECT 语句中使用计算字段创建视图?

在设计中使用上述功能。

最后但同样重要的是,一种适用于空值和零值的触发解决方案。

--
-- Sample table
--

-- Use temp database
USE TEMPDB;
GO

-- Remove old object
IF OBJECT_ID('DBO.INVESTOR') > 1
    DROP TABLE DBO.INVESTOR
GO

-- Create new object
CREATE TABLE DBO.INVESTOR
(
    INVESTOR_ID INT IDENTITY(1, 1),
    INVESTOR_PRIN_BAL_PURCHASED MONEY,
    INVESTOR_DISC_PREM_DOLLAR MONEY,
    INVESTOR_SRP_PREM_DOLLAR MONEY,
    INVESTOR_ADMIN_FEE MONEY,
    INVESTOR_WIRE_FEE MONEY,
    INVESTOR_FLOOD_FEE MONEY,
    INVESTOR_TAX_SERVICE_FEE MONEY,
    INVESTOR_OTHER_FEE MONEY,
    INVESTOR_DISC_PREM_PERCENT REAL,
    INVESTOR_SRP REAL,
    PURCHASE_WIRE_AMOUNT MONEY
);


--
-- Sample trigger
--

-- Remove old object
IF OBJECT_ID('DBO.CALCULATE_FEILDS') > 1
    DROP TRIGGER DBO.CALCULATE_FEILDS
GO

-- Create new object
CREATE TRIGGER DBO.CALCULATE_FEILDS ON DBO.INVESTOR
FOR INSERT, UPDATE AS
BEGIN

    UPDATE 
        DBO.INVESTOR
    SET 
        INVESTOR_DISC_PREM_PERCENT = 
            CASE WHEN INVESTOR_PRIN_BAL_PURCHASED <> 0 THEN
                Coalesce(INVESTOR_DISC_PREM_DOLLAR, 0) /
                Coalesce(INVESTOR_PRIN_BAL_PURCHASED, 0) * 100
            ELSE 0 END,

        INVESTOR_SRP = 
            CASE WHEN INVESTOR_PRIN_BAL_PURCHASED <> 0 THEN
                Coalesce(INVESTOR_SRP_PREM_DOLLAR, 0) /
                Coalesce(INVESTOR_PRIN_BAL_PURCHASED, 0) * 100
            ELSE 0 END,
        PURCHASE_WIRE_AMOUNT = 
            Coalesce(INVESTOR_PRIN_BAL_PURCHASED, 0) -
            Coalesce(INVESTOR_ADMIN_FEE, 0) -
            Coalesce(INVESTOR_WIRE_FEE, 0) - 
            Coalesce(INVESTOR_FLOOD_FEE, 0) -
            Coalesce(INVESTOR_TAX_SERVICE_FEE, 0) - 
            Coalesce(INVESTOR_OTHER_FEE, 0)
    WHERE 
        INVESTOR_ID IN (Select i.INVESTOR_ID From inserted i)

END
GO

--
-- Sample data (zeros & nulls)
--

INSERT INTO DBO.INVESTOR
(
    INVESTOR_PRIN_BAL_PURCHASED,
    INVESTOR_DISC_PREM_DOLLAR,
    INVESTOR_SRP_PREM_DOLLAR,
    INVESTOR_ADMIN_FEE,
    INVESTOR_WIRE_FEE,
    INVESTOR_FLOOD_FEE,
    INVESTOR_TAX_SERVICE_FEE,
    INVESTOR_OTHER_FEE
) 
VALUES 
(0, 0, 0, 0, 0, 0, 0, 0),
(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);

-- Show the data
SELECT * FROM TEMPDB.DBO.INVESTOR
于 2013-09-10T14:10:25.193 回答
0

像这样尝试,它应该可以解决这两个问题:

ALTER TRIGGER [dbo].[SelfCalFieldsTrigger] ON [dbo].[dynTable]
FOR INSERT, UPDATE AS
BEGIN

    UPDATE [dbo].dynTable
        SET INVESTOR_DISC_PREM_PERCENT = Coalesce(INVESTOR_DISC_PREM_DOLLAR, 0)/
                Coalesce(INVESTOR_PRIN_BAL_PURCHASED, 0)*100,
            INVESTOR_SRP = Coalesce(INVESTOR_SRP_PREM_DOLLAR, 0)/
                Coalesce(INVESTOR_PRIN_BAL_PURCHASED, 0)*100,
            PURCHASE_WIRE_AMOUNT = Coalesce(INVESTOR_PRIN_BAL_PURCHASED, 0)-
                Coalesce(INVESTOR_ADMIN_FEE, 0)-
                Coalesce(INVESTOR_WIRE_FEE, 0)- Coalesce(INVESTOR_FLOOD_FEE, 0)-
                Coalesce(INVESTOR_TAX_SERVICE_FEE, 0) - Coalesce(INVESTOR_OTHER_FEE, 0)
    WHERE Account_id IN(Select i.Account_id From inserted i)

END
于 2013-09-10T14:23:30.067 回答