1

テーブルでデータ検証を実行しようとしていますが、複数の行と列をチェックする必要があります。基本的に、特定のツールについて、アクティブ バージョンまたはベータ バージョンとしてフラグが付けられたバージョンが少なくとも 1 つ存在することを確認したいと考えています。

これを確認する唯一の方法は、ユーザー定義のスカラー関数とCHECK、関数を呼び出す制約を使用することです。期待どおりの結果を返す関数を作成できました (OK の場合は 0、そうでない場合は1 ) INSERTUPDATEorステートメントを実行するDELETEと、チェック制約は失敗しないため、どちらの場合も不正なデータになる可能性があります。

これは、私が使用しているテーブルと関数のサンプルです。

CREATE TABLE VersionTest(VersionID int NOT NULL, ToolID int NOT NULL, IsActiveVersion bit NOT NULL, IsBetaVersion bit NOT NULL)
GO

ALTER TABLE VersionTest ADD  CONSTRAINT [DF_VersionTest_IsActiveVersion]  DEFAULT ((0)) FOR [IsActiveVersion]
GO

ALTER TABLE VersionTest ADD  CONSTRAINT [DF_VersionTest_IsBetaVersion]  DEFAULT ((0)) FOR [IsBetaVersion]
GO

CREATE FUNCTION fn_ValidateVersionTest(@toolID int) RETURNS SMALLINT
AS
      BEGIN
      IF (@toolID = -1)
        BEGIN
          RETURN 0
        END
      ELSE
        BEGIN
            IF EXISTS (SELECT 1
                       FROM VersionTest
                       WHERE ToolID = @toolID
                       GROUP BY ToolID, IsActiveVersion, IsBetaVersion
                       HAVING (SUM(CASE WHEN IsActiveVersion = 1 THEN 1 ELSE 0 END) + 
                               SUM(CASE WHEN IsBetaVersion = 1 THEN 1 ELSE 0 END)) > 0)
              RETURN 0
        END
        RETURN 1      
    END
GO

ALTER TABLE VersionTest WITH CHECK ADD  CONSTRAINT [CK_VersionTest] CHECK  (([dbo].[fn_ValidateVersionTest]([ToolID])=(0)))
GO
ALTER TABLE VersionTest CHECK CONSTRAINT [CK_VersionTest]
GO

次の INSERT ステートメントは正常に機能します。

INSERT INTO VersionTest (ToolID, VersionID, IsActiveVersion, IsBetaVersion)
VALUES (1, 1, 1, 0)

INSERT INTO VersionTest (ToolID, VersionID, IsActiveVersion, IsBetaVersion)
VALUES (1, 2, 0, 0)

予想どおり、この INSERT ステートメントは失敗します。

INSERT INTO VersionTest (ToolID, VersionID, IsActiveVersion, IsBetaVersion)
VALUES (2, 1, 0, 0)

ただし、次の UPDATE および DELETE ステートメントは、期待どおりに失敗していません。

UPDATE VersionTest 
SET IsActiveVersion = 0, IsBetaVersion = 0
WHERE VersionID = 1

DELETE VersionTest WHERE VersionID = 1

これを行うべき別の方法はありますか?代わりにトリガーを使用する必要がありますか?

4

1 に答える 1

2

この方法で、更新時にチェックを強制できます。
このようなテーブルがあるとしましょう

create table UserTest(Id int, IsEnabled bit, [GroupId] int)

ここで、1 人のユーザーのみが有効になっていることを確認し[GroupId]ます。

通常、制約は次のようになります

ALTER TABLE [dbo].[UserTest] ADD CONSTRAINT CHK_OnlyOneEnabled  CHECK (dbo.checkOnlyOne(GroupId)=1)

を更新するまで、更新されたレコードに対してこの制約はトリガーされませんGroupId
したがって、次のようにして IsEnabled 列を検証するように制約を強制する必要があります。

ALTER TABLE [dbo].[UserTest] ADD CONSTRAINT CHK_OnlyOneEnabled  CHECK (dbo.checkOnlyOne(GroupId, IsEnabled )=1)

関数に IsEnabled 値を使用するかどうかは関係ありません。

于 2015-09-07T18:23:00.640 に答える