Sql-Server

我可以在不查看 ID 的情況下創建視圖來編輯 ID 映射表嗎?

  • October 11, 2016

我有 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 並喜歡直接訪問其數據的人(交易者)。

桌腳

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

樣本數據

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

看法

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;

問題

視圖不可直接更新:

INSERT dbo.ItemAccessoryName
   (ItemName, AccessoryName)
VALUES
   ('Item 4', 'Accessory 4');

消息 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;

在嘗試插入之前,觸發器實質上會將提供的名稱轉換為 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;

引用自:https://dba.stackexchange.com/questions/151544