【问题标题】:How to create a trigger in SQL Server that insert values into two tables using an ID stored in the second one如何在 SQL Server 中创建一个触发器,该触发器使用存储在第二个表中的 ID 将值插入到两个表中
【发布时间】:2016-02-24 10:14:51
【问题描述】:

我有三张桌子:

  • RawValues 包含 Timestamp、Part、PartNumber、ValueKind、...、Value
  • Measurements,包含时间戳、ID、值。
  • Hashtable 包含 ID、Part、ValueKind、...

我有一个无法修改的数据流进入RawValue。它包含除 ID 之外的所有列。

我想在RawValues 上创建一个触发器,将值插入Hashtable(如果它们尚不存在),从Hashtable 中选择ID,然后将行插入Measurements

这是我创建的:

CREATE TRIGGER [dbo].[TrigInsertToMeasurements]
ON [dbo].[MeasurementsTemp]
FOR INSERT
AS
BEGIN
    SET NOCOUNT ON;
    SET XACT_ABORT ON;

       -- Dichiaro le variaibili --
       DECLARE 
             @TimeStamp datetime, 
             @MachineType char(10), 
             @MachineModel char(10), 
             @MachineNumber int, 
             @Part char(10),
             @PartNumber int,
             @ValueKind char(10),
             @Value float,
             @ID     int

       -- Assegno i valori --
       SELECT 
             @TimeStamp = TimeStamp,
             @MachineType = MachineType,
             @MachineModel = MachineModel,
             @MachineNumber = MachineNumber, 
             @Part = Part,
             @PartNumber = PartNumber,
             @ValueKind = ValueKind,
             @Value = Value
       FROM
             inserted


        SELECT @ID=ID FROM [dbo].[Hashtable]
        WHERE 
             @MachineType = [MachineType] AND
             @MachineModel = [MachineModel] AND
             @MachineNumber = MachineNumber AND
             @Part = Part AND
             @PartNumber = PartNumber AND
             @ValueKind = ValueKind


        IF count(@ID) = count(@TimeStamp)
        BEGIN
            INSERT INTO [dbo].[Measurements] ([TimeStamp], [ID], [Value] ) VALUES (@TimeStamp, @ID, @Value)
        END
        ELSE BEGIN

            BEGIN
            IF NOT EXISTS (SELECT [ID] FROM [dbo].[Hashtable] WHERE
             @MachineType = [MachineType] AND
             @MachineModel = [MachineModel] AND
             @MachineNumber = MachineNumber AND
             @Part = Part AND
             @PartNumber = PartNumber AND
             @ValueKind = ValueKind)
            BEGIN
            INSERT INTO [dbo].[Hashtable] (MachineType, MachineModel, MachineNumber, Part, PartNumber, ValueKind)
            VALUES (@MachineType, @MachineModel, @MachineNumber, @Part, @PartNumber, @ValueKind)
            END
            END         

            SELECT @ID=ID FROM [dbo].[Hashtable]
            WHERE 
             @MachineType = MachineType AND
             @MachineModel = MachineModel AND 
             @MachineNumber = MachineNumber AND
             @Part = Part AND
             @PartNumber = PartNumber AND
             @ValueKind = ValueKind

             INSERT INTO [dbo].[Measurements] ([TimeStamp], [ID], [Value] ) VALUES (@TimeStamp, @ID, @Value)
        END
END

GO

ALTER TABLE [dbo].[MeasurementsTemp] ENABLE TRIGGER [TrigInsertToMeasurements]
GO

触发器正常工作,但有时在流中成组出现行,那么在这种情况下,不会考虑所有行。 我能做些什么?也许使用 for 循环然后访问数组?怎么做?

【问题讨论】:

  • 您的触发器概念是错误的。触发器不会针对每条记录发生。 INSERTED 可能包含多于 1 行。您需要在触发器中处理它
  • 您的触发器有 MAJOR 缺陷,因为您似乎认为它会每行调用一次 - 那是不是 b> 情况。触发器将每条语句触发一次,因此如果您的 INSERT 语句影响 25 行,您将触发触发器 一次,但随后 Inserted 将包含 25行。你不能简单地做一个SELECT .... FROM Inserted - 你只会得到一个任意的行并且忽略所有其他 - 通常不是你想要做的。您需要以基于集合的方式完全重写您的触发器

标签: sql sql-server tsql triggers


【解决方案1】:

我尝试重新编码您的触发器,根据我对逻辑的理解最好地替换它

CREATE TRIGGER [dbo].[TrigInsertToMeasurements]
ON [dbo].[MeasurementsTemp]
FOR INSERT
AS
BEGIN

    SET NOCOUNT ON;
    SET XACT_ABORT ON;

       -- Dichiaro le variaibili --
       DECLARE 
             @TimeStamp datetime, 
             @MachineType char(10), 
             @MachineModel char(10), 
             @MachineNumber int, 
             @Part char(10),
             @PartNumber int,
             @ValueKind char(10),
             @Value float,
             @ID     int

       -- Assegno i valori --
       --SELECT 
       --      @TimeStamp = TimeStamp,
       --      @MachineType = MachineType,
       --      @MachineModel = MachineModel,
       --      @MachineNumber = MachineNumber, 
       --      @Part = Part,
       --      @PartNumber = PartNumber,
       --      @ValueKind = ValueKind,
       --      @Value = Value
       --FROM
       --      inserted


        --SELECT @ID=ID FROM [dbo].[Hashtable]
        --WHERE 
        --     @MachineType = [MachineType] AND
        --     @MachineModel = [MachineModel] AND
        --     @MachineNumber = MachineNumber AND
        --     @Part = Part AND
        --     @PartNumber = PartNumber AND
        --     @ValueKind = ValueKind


        IF count(@ID) = count(@TimeStamp)
        BEGIN
            --INSERT INTO [dbo].[Measurements] ([TimeStamp], [ID], [Value] ) VALUES (@TimeStamp, @ID, @Value)
        INSERT INTO [dbo].[Measurements] ([TimeStamp], [ID], [Value] ) 
        SELECT  i.TimeStamp, h.ID, i.Value
        FROM    inserted i
            INNER JOIN [dbo].[Hashtable] h  ON  i.[MachineType]     = h.[MachineType]
                            AND i.[MachineModel]    = h.[MachineModel]
                            AND i.MachineNumber     = h.MachineNumber
                            AND i.Part          = h.Part
                            AND i.PartNumber        = h.PartNumber
                            AND i.ValueKind     = h.ValueKind
        WHERE   i.TimeStamp IS NOT NULL

        END
        ELSE 
    BEGIN

      --      BEGIN
            --IF NOT EXISTS (SELECT [ID] FROM [dbo].[Hashtable] WHERE
            -- @MachineType = [MachineType] AND
            -- @MachineModel = [MachineModel] AND
            -- @MachineNumber = MachineNumber AND
            -- @Part = Part AND
            -- @PartNumber = PartNumber AND
            -- @ValueKind = ValueKind)
               -- BEGIN
               -- INSERT INTO [dbo].[Hashtable] (MachineType, MachineModel, MachineNumber, Part, PartNumber, ValueKind)
               -- VALUES (@MachineType, @MachineModel, @MachineNumber, @Part, @PartNumber, @ValueKind)
               -- END
      --      END    
           INSERT INTO [dbo].[Hashtable] (MachineType, MachineModel, MachineNumber, Part, PartNumber, ValueKind)
       SELECT   i.MachineType, i.MachineModel, i.MachineNumber, i.Part, i.PartNumber, i.ValueKind
       FROM     inserted i
       WHERE    NOT EXISTS
            (
                SELECT  *
                FROM    [dbo].[Hashtable] x
                WHERE   x.MachineType   = i.MachineType
                AND x.MachineModel  = i.MachineModel
                AND x.MachineNumber = i.MachineNumber
                AND x.Part      = i.Part
                AND x.PartNumber    = i.PartNumber
                AND x.ValueKind = i.ValueKind
            )

            --SELECT @ID=ID FROM [dbo].[Hashtable]
            --WHERE 
            -- @MachineType = MachineType AND
            -- @MachineModel = MachineModel AND 
            -- @MachineNumber = MachineNumber AND
            -- @Part = Part AND
            -- @PartNumber = PartNumber AND
            -- @ValueKind = ValueKind

            -- INSERT INTO [dbo].[Measurements] ([TimeStamp], [ID], [Value] ) VALUES (@TimeStamp, @ID, @Value)
        INSERT INTO [dbo].[Measurements] ([TimeStamp], [ID], [Value] )
        SELECT  i.[TimeStamp], h.ID, i.Value
        FROM    inserted i
            INNER JOIN [dbo].[Hashtable] h  ON  i.MachineType   = h.MachineType
                            AND i.MachineModel  = h.MachineModel
                            AND i.MachineNumber = h.MachineNumber
                            AND i.Part      = h.Part
                            AND i.PartNumber    = h.PartNumber
                            AND i.ValueKind = h.ValueKind
        END
END

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-15
    • 2015-07-29
    • 2020-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多