0

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

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)
);

Units,PackageConfigurationsPackages. 一个包恰好有一个PackageConfiguration和之间的关系,Package并且Unit是多(单元)到最多一个(包)。

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

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 个左右的 Units,但更喜欢通用解决方案来解决我的问题。

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

4

1 回答 1

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
于 2013-07-04T03:15:28.607 回答