0

SQL Server の制約についてサポートが必要です。この状況は、テーブルの各 OrderID=1 (主キーではなく外部キーであるため、同じ ID を持つ複数の行がある) であり、ビット フィールドはそれらの行の 1 つに対してのみ 1 であり、OrderID=2 の各行に対して、ビット フィールドは 1 つの行に対してのみ 1 にすることができます。同じ OrderID を持つ他のすべての行に対しては 0 にする必要があります。ビット フィールドが 1 に設定されている OrderID を持つ行が既に存在する場合、ビット フィールドに 1 が含まれる新しいレコードはすべて拒否する必要があります。何かアイデアはありますか?

4

4 に答える 4

2
CREATE UNIQUE INDEX ON UnnamedTable (OrderID) WHERE UnnamedBitField=1

これはFiltered Indexと呼ばれます。2008 年より前のバージョンの SQL Server を使用している場合は、インデックス付きビューを使用して、フィルター処理されたインデックスに相当する簡易版を実装できます。

CREATE VIEW UnnamedView
WITH SCHEMABINDING
AS
    SELECT OrderID From UnnamedSchema.UnnamedTable WHERE UnnamedBitField=1
GO
CREATE UNIQUE CLUSTERED INDEX ON UnnamedView (OrderID)

SQL Server は列の制約と行の制約しかサポートしていないため、実際には制約として行うことはできません。テーブル内のすべての値を処理する制約を記述する (偽りのない) 方法はありません。

于 2013-04-10T06:36:19.990 に答える
1

スキーマをより完全に正規化することができます。これにより、既に設定されているビットを探す必要がなくなり、結合を使用することができます。ビット フィールドを削除し、OrderID とテーブルの主キーを含む X という新しいテーブルを作成する必要があります。X の主キーはこれらすべてのフィールドです。

これは、挿入するときに、元のテーブルと X f に挿入する必要があり、テーブルでビットを 1 に設定した場合にのみ必要であることを意味します。ビットが 1 に設定された元の行が既に存在するかのように、X に行が既に存在する場合、挿入は失敗します。

欠点は、これがスキーマよりも多くのスペースを占有することですが、ビットが 1 に設定された 2 つの行を持つことと同等にならないため、維持が容易です。

于 2013-04-09T22:51:28.603 に答える
0

私は他の答えに同意します。スキーマを変更できる場合はそれを行いますが、そうでない場合は、このようなことができると思います。

CREATE FUNCTION fnMyCheck
    (@id INT)
RETURNS INT
AS
BEGIN
    DECLARE @i INT

    SELECT @i = COUNT(*)
    FROM MyTable 
    WHERE FkCol = @id 
    AND BitCol = 1

    RETURN @i
END

ALTER TABLE YourTable
ADD CONSTRAINT ckMyCheck CHECK (fnMyCheck(FkCol)<=1)

しかし、このようなチェック制約で udf を使用すると、問題が発生する可能性があります。

この「ソリューション」の問題に関するコメントを追加するために編集します。

あなたがリンクしたものよりも簡単な問題があります。

INSERT INTO YourTable(FkCol,BitCol) VALUES (1,1),(1,0) 

に続く

UPDATE YourTable SET BitCol=1 

成功し、FkCol=1 および BitCol=1 の 2 つの行を残します

于 2013-04-09T23:12:48.737 に答える