我可以创建一个视图来编辑 ID 映射表而不看到 ID 吗?

Fra*_*sca 2 sql-server ssms t-sql view

我有 2 个表,A 和 B,带有一个int主键和一个string名称。

我有一个第三个表 C,其中有 2 列将 A 和 B 的 ID 映射在一起。我想创建一个视图来编辑表 C 中的映射,但我希望视图显示Name值而不是IDs. 该视图将通过 SQL Server Management Studio 进行编辑。

例如,视图应该允许用户在项目列中输入“Item4”,在附件列中输入“Accessory1”,表 C 更新为新的行映射“4”到“1”。

在此处输入图片说明

我想知道是否可以将其设为可编辑视图,这样我就不必费心编写整个应用程序来管理它。

如果我转到 Microsoft SQL Server Management Studio 中的视图并右键单击,我可以编辑前 200 行。我知道此功能的限制是我只能在更改为单个表时进行编辑。我只会编辑一个表,所以可能有办法让它工作。有办法吗?(我的用户是熟悉 SQL Server 并且更喜欢直接访问他们的数据的人(交易员))。

Pau*_*ite 6

基表

CREATE TABLE dbo.Item
(
    ItemID integer PRIMARY KEY,
    ItemName varchar(50) NOT NULL UNIQUE
);

CREATE TABLE dbo.Accessory
(
    AccessoryID integer PRIMARY KEY,
    AccessoryName varchar(50) NOT NULL UNIQUE
);

CREATE TABLE dbo.ItemAccessory
(
    ItemID integer REFERENCES dbo.Item (ItemID),
    AccessoryID integer REFERENCES dbo.Accessory (AccessoryID),

    PRIMARY KEY (ItemID, AccessoryID)
);
Run Code Online (Sandbox Code Playgroud)

样本数据

INSERT dbo.Item
    (ItemID, ItemName)
VALUES
    (1, 'Item 1'),
    (2, 'Item 2'),
    (3, 'Item 3'),
    (4, 'Item 4');

INSERT dbo.Accessory
    (AccessoryID, AccessoryName)
VALUES
    (1, 'Accessory 1'),
    (2, 'Accessory 2'),
    (3, 'Accessory 3'),
    (4, 'Accessory 4');

INSERT dbo.ItemAccessory
    (ItemID, AccessoryID)
VALUES
    (1, 1),
    (1, 2),
    (2, 3),
    (3, 4);
Run Code Online (Sandbox Code Playgroud)

看法

CREATE VIEW dbo.ItemAccessoryName
WITH SCHEMABINDING
AS
SELECT
    I.ItemName,
    A.AccessoryName
FROM dbo.ItemAccessory AS IA
JOIN dbo.Accessory AS A
    ON A.AccessoryID = IA.AccessoryID
JOIN dbo.Item AS I
    ON I.ItemID = IA.ItemID;
Run Code Online (Sandbox Code Playgroud)

问题

该视图不可直接更新:

INSERT dbo.ItemAccessoryName
    (ItemName, AccessoryName)
VALUES
    ('Item 4', 'Accessory 4');
Run Code Online (Sandbox Code Playgroud)

消息 4405,级别 16,状态 1,第 61 行
视图或函数“dbo.ItemAccessoryName”不可更新,因为修改会影响多个基表。

解决方案

我们可以使用代替触发器使任何视图可更新:

CREATE TRIGGER dbo_ItemAccessoryName_IOI
ON dbo.ItemAccessoryName
INSTEAD OF INSERT
AS
    SET ROWCOUNT 0;
    SET NOCOUNT ON;

    INSERT dbo.ItemAccessory
    (
        ItemID, 
        AccessoryID
    )
    SELECT
        I.ItemID,
        A.AccessoryID 
    FROM Inserted AS INS
    JOIN dbo.Item AS I
        ON I.ItemName = INS.ItemName
    JOIN dbo.Accessory AS A
        ON A.AccessoryName = INS.AccessoryName;
Run Code Online (Sandbox Code Playgroud)

在尝试插入之前,触发器本质上将提供的名称转换为 ID。只要您具有良好的参照完整性,在触发器代码中进行额外检查的需求应该是最小的。例如,如果有人粘贴多个条目(例如,只有其中一些是有效的),则详细信息完全取决于您希望发生的情况。

插入、更新和删除

如果您希望通过视图允许(一般)更新和删除,您将需要额外的触发器逻辑。例如:

DROP TRIGGER dbo.dbo_ItemAccessoryName_IOI;
GO
CREATE TRIGGER dbo_ItemAccessoryName_IOIUD
ON dbo.ItemAccessoryName
INSTEAD OF INSERT, UPDATE, DELETE
AS
    SET ROWCOUNT 0;
    SET NOCOUNT ON;

    -- Handle deletions (including the delete part of an update)
    DELETE IA
    FROM dbo.ItemAccessory AS IA
    JOIN dbo.Item AS I
        ON I.ItemID = IA.ItemID
    JOIN dbo.Accessory AS A
        ON A.AccessoryID = IA.AccessoryID
    JOIN Deleted AS DEL
        ON DEL.ItemName = I.ItemName
        AND DEL.AccessoryName = A.AccessoryName;

    -- Handle inserts (including the insert part of an update)
    INSERT dbo.ItemAccessory
    (
        ItemID, 
        AccessoryID
    )
    SELECT
        I.ItemID,
        A.AccessoryID 
    FROM Inserted AS INS
    JOIN dbo.Item AS I
        ON I.ItemName = INS.ItemName
    JOIN dbo.Accessory AS A
        ON A.AccessoryName = INS.AccessoryName;
Run Code Online (Sandbox Code Playgroud)