创建一个独特的 constraint/index,考虑第二个 table
Create a unique constraint/index, that considers a second table
在我的 SQL 服务器数据库中,我想创建一个唯一约束,考虑第二个 table。我的 table ChargeCarrier_Storage
包含两个 ID 字段 ID_ChargeCarrier
和 ID_Storage
。我的 Storage
table 包含两个字段 ID
和 ID_StorageType
。约束应该是,对于存储类型 1
,ChargeCarrier_Storage
table 中应该只有一个可能的条目。对于任何其他存储类型,可以有无限数量的条目。
我的第一个方法是在 ChargeCarrier_Storage
table 上创建一个非聚集索引,但这显然行不通,因为看起来你不能在那里使用连接.
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
是否有一些简单的方法来完成这项工作?
您不能在 table 上执行此操作,您需要使用 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
未经测试,不optimize.Query可以优化。
了解 ChargeCarrier_Storage
的完整 table 结构并了解它将如何用于搜索以及那里有多少数据后 inChargeCarrier_Storage
等
所以这要视情况而定,在某些情况下它可能是有益的。
就像说如果我创建一个 Non Clustered index
dbo.ChargeCarrier_Storage (ID_ChargeCarrier)
这样我就不必为约束创建一个额外的唯一索引。
在我的 SQL 服务器数据库中,我想创建一个唯一约束,考虑第二个 table。我的 table ChargeCarrier_Storage
包含两个 ID 字段 ID_ChargeCarrier
和 ID_Storage
。我的 Storage
table 包含两个字段 ID
和 ID_StorageType
。约束应该是,对于存储类型 1
,ChargeCarrier_Storage
table 中应该只有一个可能的条目。对于任何其他存储类型,可以有无限数量的条目。
我的第一个方法是在 ChargeCarrier_Storage
table 上创建一个非聚集索引,但这显然行不通,因为看起来你不能在那里使用连接.
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
是否有一些简单的方法来完成这项工作?
您不能在 table 上执行此操作,您需要使用 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
未经测试,不optimize.Query可以优化。
了解 ChargeCarrier_Storage
的完整 table 结构并了解它将如何用于搜索以及那里有多少数据后 inChargeCarrier_Storage
等
所以这要视情况而定,在某些情况下它可能是有益的。
就像说如果我创建一个 Non Clustered index
dbo.ChargeCarrier_Storage (ID_ChargeCarrier)
这样我就不必为约束创建一个额外的唯一索引。