创建一个唯一的约束/索引,它考虑了第二张表

问题描述 投票:0回答:2

在我的SQL Server数据库中,我想创建一个唯一约束,该约束考虑第二个表。我的表ChargeCarrier_Storage包含两个ID字段ID_ChargeCarrierID_Storage。我的Storage表包含两个字段IDID_StorageType。约束应该是,对于存储类型1,在ChargeCarrier_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

有一些简单的方法可以使这项工作吗?

sql sql-server unique-constraint unique-index
2个回答
3
投票

您无法在表上执行此操作,您需要使用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;

0
投票

这也是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

NoteTrigger code未测试且未优化。查询可以优化。

了解了ChargeCarrier_Storage的完整表结构并了解了如何在搜索中使用它以及在inChargeCarrier_Storage中将有多少数据,等等

所以它取决于情况,在某些情况下它[可能是]有益的。就像说如果我在上创建一个Non Clustered indexdbo.ChargeCarrier_Storage (ID_ChargeCarrier)则我不必为了约束而创建一个额外的唯一索引。

© www.soinside.com 2019 - 2024. All rights reserved.