3

データに次のチェック (制約?) が適用されていることを確認したい

  • このテーブルは、ハブ/カテゴリごとに 1 つの BorderColour のみを持つことができます。(例: #FFAABB)
  • ただし、複数の null を持つことができます。(このフィールドでは、他のすべての行は null です)

テーブル スキーマ

ArticleId INT PRIMARY KEY NOT NULL IDENTITY
HubId TINYINT NOT NULL
CategoryId INT NOT NULL
Title NVARCHAR(100) NOT NULL
Content NVARCHAR(MAX) NOT NULL
BorderColour VARCHAR(7) -- Can be nullable.

チェック制約を作成する必要があると思いますか?しかし、私はどのようにわからない、など。

サンプルデータ。

1, 1, 1, 'test', 'blah...', '#FFAACC'
1, 1, 1, 'test2', 'sfsd', NULL
1, 1, 2, 'Test3', 'sdfsd dsf s', NULL
1, 1, 2, 'Test4', 'sfsdsss', '#AABBCC'

今..次の行を追加すると、SQLエラーが発生するはずです....

INSERT INTO tblArticle VALUES (1, 2, 'aaa', 'bbb', '#ABABAB')

何か案は?

4

4 に答える 4

3

CHECK制約は通常、単一の行に適用されますが、UDFを使用してチートすることができます。

CREATE FUNCTION dbo.CheckSingleBorderColorPerHubCategory
(
    @HubID tinyint,
    @CategoryID int
)
RETURNS BIT
AS BEGIN
    RETURN CASE
        WHEN EXISTS
        (
            SELECT HubID, CategoryID, COUNT(*) AS BorderColorCount
            FROM Articles
            WHERE HubID = @HubID
                AND CategoryID = @CategoryID
                AND BorderColor IS NOT NULL
            GROUP BY HubID, CategoryID
            HAVING COUNT(*) > 1
        ) THEN 1
        ELSE 0
    END
END

次に、制約を作成し、UDFを参照します。

ALTER TABLE Articles
ADD CONSTRAINT CK_Articles_SingleBorderColorPerHubCategory
CHECK (dbo.CheckSingleBorderColorPerHubCategory(HubID, CategoryID) = 1)
于 2010-03-26T00:37:12.757 に答える
0

次のようなトリガーを実行することもできます(これは実際にはやり過ぎです-データベースがすでに有効な状態にあると想定することで、よりクリーンにすることができます-つまり、UNION allではなくUNIONなど):

IF EXISTS (
    SELECT COUNT(BorderColour)
    FROM (
             SELECT INSERTED.HubId, INSERTED.CategoryId, INSERTED.BorderColour
             UNION ALL
             SELECT HubId, CategoryId, BorderColour
             FROM tblArticle
             WHERE EXISTS (
                 SELECT *
                 FROM INSERTED
                 WHERE tblArticle.HubId = INSERTED.HubId
                       AND tblArticle.CategoryId = INSERTED.CategoryId
             )
    ) AS X
    GROUP BY HubId, CategoryId
    HAVING COUNT(BorderColour) > 1
)
RAISEERROR
于 2010-03-26T00:42:08.380 に答える
0

テーブルに一意の列がある場合は、コンピューターの列に一意の制約を作成することでこれを実現できます。

次のサンプルでは、​​要件で説明したとおりに動作するテーブルを作成し、UDF ベースのチェック制約よりも優れたパフォーマンスを発揮するはずです。計算列を永続化することで、パフォーマンスをさらに向上させることもできます。

CREATE TABLE [dbo].[UQTest](
    [Id] INT IDENTITY(1,1) NOT NULL,
    [HubId] TINYINT NOT NULL,
    [CategoryId] INT NOT NULL,
    [BorderColour] varchar(7) NULL,
    [BorderColourUNQ]  AS (CASE WHEN [BorderColour] IS NULL 
                               THEN cast([ID] as varchar(50))
                               ELSE cast([HuBID] as varchar(3)) + '_' + 
                                    cast([CategoryID] as varchar(20)) END
                           ),
 CONSTRAINT [UQTest_Unique] 
 UNIQUE  ([BorderColourUNQ])
) 

上記の実装の望ましくない側面の 1 つは、カテゴリ/ハブに Null と色の両方を定義できることです。これが問題である場合は、お知らせください。それに対処するために回答を微調整します。

PS: 以前の (間違った) 回答について申し訳ありません。質問をよく読んでいませんでした。

于 2010-03-26T01:34:36.463 に答える