簡體   English   中英

創建一個唯一約束/索引,考慮第二個表

[英]Create a unique constraint/index, that considers a second table

在我的 SQL 服務器數據庫中,我想創建一個考慮第二個表的唯一約束。 我的表ChargeCarrier_Storage包含兩個 ID 字段ID_ChargeCarrierID_Storage My Storage表包含兩個字段IDID_StorageType 約束應該是,對於存儲類型1ChargeCarrier_Storage表中應該只有一個可能的條目。 對於任何其他存儲類型,可以有無限數量的條目。

我的第一種方法是在ChargeCarrier_Storage表上創建一個非聚集索引,但這顯然不起作用,因為看起來你不能在那里使用連接。

CREATE NONCLUSTERED INDEX UQX_OnePickingStoragePerCarrier  
    ON dbo.ChargeCarrier_Storage ccs (ID_ChargeCarrier, ID_Storage)  
    INNER JOIN dbo.Storage s ON s.ID = ccs.ID_Storage
    WHERE s.ID_StorageType = 1;  
GO

有沒有一些簡單的方法可以使這項工作?

您不能在表上執行此操作,您需要使用VIEW並在那里創建索引:

USE Sandbox;
GO

--Create sample tables
CREATE TABLE dbo.ChargeCarrier_Storage (ID_ChargeCarrier int,
                                        ID_Storage int);
CREATE TABLE dbo.Storage (ID int,
                          ID_StorageType int);
GO
--Create Schema bound View
CREATE VIEW dbo.OnePickingStoragePerCarrier WITH SCHEMABINDING
AS
    SELECT ccs.ID_ChargeCarrier,
           s.ID AS ID_Storage
    FROM dbo.ChargeCarrier_Storage ccs
         INNER JOIN dbo.Storage s ON s.ID = ccs.ID_Storage
    WHERE s.ID_StorageType = 1;  
GO
--Create unique (clustered) index
CREATE UNIQUE CLUSTERED INDEX UQX_OnePickingStoragePerCarrier ON OnePickingStoragePerCarrier (ID_ChargeCarrier,ID_Storage);
GO

--Sample data in Storage
INSERT INTO dbo.Storage (ID,
                         ID_StorageType)
VALUES(1,1),
      (2,1),
      (3,2);
GO

--Tests
INSERT INTO dbo.ChargeCarrier_Storage (ID_ChargeCarrier,
                                       ID_Storage)
VALUES(1,1); --Works
GO

INSERT INTO dbo.ChargeCarrier_Storage (ID_ChargeCarrier,
                                       ID_Storage)
VALUES(2,1); --Works
GO

INSERT INTO dbo.ChargeCarrier_Storage (ID_ChargeCarrier,
                                       ID_Storage)
VALUES(1,2); --Works
GO

INSERT INTO dbo.ChargeCarrier_Storage (ID_ChargeCarrier,
                                       ID_Storage)
VALUES(2,1); --fails due to duplicate
GO
INSERT INTO dbo.ChargeCarrier_Storage (ID_ChargeCarrier,
                                       ID_Storage)
VALUES(1,3); --works.

INSERT INTO dbo.ChargeCarrier_Storage (ID_ChargeCarrier,
                                       ID_Storage)
VALUES(1,3); --works, as not Storage ID 1, so duplicate allowed
GO

GO

DROP VIEW dbo.OnePickingStoragePerCarrier;
DROP TABLE dbo.Storage;
DROP TABLE dbo.ChargeCarrier_Storage;

這也是Instead of Insert and update理想方案。

CREATE  TRIGGER trgInsteadOfStorage ON dbo.ChargeCarrier_Storage
INSTEAD OF Insert,Update
AS

BEGIN 
 SET NOCOUNT ON
 if exists(select 1 from dbo.ChargeCarrier_Storage ccs 
 INNER JOIN dbo.Storage s ON s.ID = ccs.ID_Storage
 INNER JOIN inserted i on ccs.ID_ChargeCarrier=i.ID_ChargeCarrier
 and ccs.ID_Storage=i.ID_Storage
 where s.ID_StorageType = 1
 begin
 RAISERROR('Store Type cannot be duplicate',16,1);  
 end
END

注意Trigger code未經測試,未優化。查詢可以優化。

在了解了ChargeCarrier_Storage的完整表結構並了解它將如何用於搜索以及inChargeCarrier_Storage中將有多少數據等之后。

所以這取決於情況,在某些情況下它可能是有益的。 就像說如果我在dbo.ChargeCarrier_Storage (ID_ChargeCarrier)上創建一個Non Clustered index ,那么我不必僅為約束創建一個額外的唯一索引。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM