在虚拟视图上创建触发器

时间:2013-07-04 02:28:29

标签: sql sql-server tsql

我在创建触发器时遇到问题。数据库模型如下所示:

CREATE TABLE Unit (
SerialNO    VARCHAR(3)
PRIMARY KEY (serialNO)
);

CREATE TABLE PackageConfig (
PartNO      VARCHAR(15),
SomeValue   VARCHAR(20),
PRIMARY KEY (PartNO)
);

CREATE TABLE Package (
ID          INT IDENTITY(1,1),
Config      VARCHAR(15),
PRIMARY KEY (ID),
FOREIGN KEY (Config) REFERENCES PackageConfig(PartNO)
);

CREATE TABLE UnitInPackage (
Package     INT,
Unit        VARCHAR(3),
PRIMARY KEY (Package,Unit),
FOREIGN KEY (Package) REFERENCES Package(ID),
FOREIGN KEY (Unit) REFERENCES Unit(SerialNO)
);

UnitsPackageConfigurationsPackages。一个包只有一个PackageConfigurationPackageUnit之间的关系是多(单位)到最多一个(包)。

我想要完成的是一个视图触发器,让我可以执行以下操作(假设PackageConfigUnits存在):

INSERT INTO v_MultiUnitPackage (PackageConfig, Unit1, Unit2, Unit3) 
VALUES ('SomeConfig','abc','bcd','cde');

触发器内部会执行以下操作:

DECLARE @last INT;

INSERT INTO Package (Config) VALUES ('SomeConfig');
SET @last = SCOPE_IDENTITY();
INSERT INTO UnitInPackage (Package,Unit)
VALUES (@last,'abc'),(@last,'bcd'),(@last,'cde');

或者更多列:

INSERT INTO Package (Config) VALUES ('SomeConfig');
SET @last = SCOPE_IDENTITY();
INSERT INTO UnitInPackage (Package,Unit)
VALUES (@last,'hgf'),(@last,'gfe'),(@last,'fed'),(@last,'edc'),(@last,'dcb'),(@last,'cba');

总结一下,我想创建一个触发器,它接受PackageConfig和N个Units并将它们插入相应的表中。

我一直在研究创建一个虚拟视图,它只具有正确的数据类型和足够数量的列,以允许我想要的单位数但却找不到解决方案。

我还查看了Package.ID分组的内容,并为每个组选择了尚未选择到前一列的第一个单元。由于GROUP BY仅适用于聚合函数,因此我不确定如何实现这一想法。

实际上我认为不需要超过5个左右的单位,但更喜欢我的问题的通用解决方案。

也许有一个非常简单的解决方案,我只是没有看到。非常感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

使用视图插入是一种方法,因此您只需要使用所需的单位数量更新虚拟视图。以下是触发器的外观:

create  view v_MultiUnitPackage
as
select 'Some-Config' as PackageConfig, 'abc' as Unit1, 'bcd' as Unit2, 'cde' as Unit3
go

  create TRIGGER tg_I_v_MultiUnitPackage
ON v_MultiUnitPackage 
INSTEAD OF INSERT
AS
BEGIN
    DECLARE @last INT;

    INSERT INTO Package (Config)
    SELECT inserted.PackageConfig
    FROM inserted
    SET @last = SCOPE_IDENTITY();

    INSERT INTO UnitInPackage (Package,Unit)
    SELECT @last, inserted.Unit1
    FROM inserted;

    INSERT INTO UnitInPackage (Package,Unit)
    SELECT @last, inserted.Unit2
    FROM inserted;

    INSERT INTO UnitInPackage (Package,Unit)
    SELECT @last, inserted.Unit3
    FROM inserted;
END

在我看来,更好的选择是将单元作为XML传递给存储过程并在那里处理插入。以下是程序的外观:

CREATE PROCEDURE usp_i_PackageUnits
(
    @PackageConfig varchar(15),
    @Units xml -- <root><unit>abc</unit><unit>bcd</unit><unit>cde</unit>
)
AS
BEGIN
    DECLARE @last INT;
    INSERT INTO Package (Config) VALUES (@PackageConfig);
    SET @last = SCOPE_IDENTITY();

    INSERT INTO UnitInPackage (Package,Unit)
    select node.value('(.)[1]', 'VARCHAR(3)') from @xml.nodes('/root/unit')as result(node)

END