0

一連のオプションを切り替えるために、一連のビット フィールドを含むテーブルを作成するよう求められています。これは、ac# flag enum がこれらすべてのビットをテーブル内の単一の int "options" フィールドに結合するのに最適な場所です。

問題は、SQL クエリでこれらのフラグを読み取ってクエリを実行する必要がある c# 以外のものがあることです。int を一連のフラグ値に分解できると思われるものは何も見つかりませんでした。私が探しているのは (私が思うに)、int をバイナリに変換してから n 番目の値を選択し、それを特定のオプションの bool として報告するものです。これを手動で行うこともできますが、パフォーマンスの低下に加えて、非常に複雑なソリューションで大量のビット列を回避しようとすることによる「@ss を迂回して肘に到達する」効果が心配です。

4

3 に答える 3

1

これは、ac# flag enum がこれらすべてのビットをテーブル内の単一の int "options" フィールドに結合するのに最適な場所です。

いいえそうではありません。これは、SQL の 16 ビット フィールドがストレージで最適化されていることを認識していないことを示すのに最適な場所です。また、メンテナンスの悪夢を作成し、アンチパターンを使用できることを示すのに最適な場所です。

int を一連のフラグ値に分解できると思われるものは何も見つかりませんでした

そのためには何もありません。これはアンチパターンです。

ビット列。それが SQL が望んでいる方法です。

于 2014-06-05T13:29:09.400 に答える
1

楽しみのために、私はあなたの質問に直接答えます。大規模なデータでは、これはうまく機能しませんが、多くのビット列もうまく機能しません。

全体的な設計が正しいデータベース設計を持ち、多数のビット列を持たず、それでもうまく機能するための答えは、メインテーブルから 1 対多のテーブルを作成することだと思います。ここで、レコードが存在するということは、オプションが有効になっていることを意味します。 . これは適切にインデックス化され、適切に実行されます。以下で使用している同様のルックアップ テーブルの構成に従って、子テーブルの複数の行にわたって SUM() と組み合わせて、複数のレコードを C# 列挙型に変換することもできます。テーブルの更新は、巧妙に作成された MERGE ステートメントでも実行できます。ただし、そのソリューションのコードは少し引き出されており、元の質問の範囲外です。

CREATE TABLE dbo.Data
    (
        ID int IDENTITY(1,1) NOT NULL PRIMARY KEY,
        Name varchar(50) NOT NULL,
        Flags int NOT NULL DEFAULT(0)
    );

CREATE TABLE dbo.Flag
    (
        Value int NOT NULL PRIMARY KEY,
        Name varchar(50) NOT NULL
    );

INSERT INTO dbo.Flag
    SELECT 1, 'Option A'
    UNION ALL
    SELECT 2, 'Option B'
    UNION ALL
    SELECT 4, 'Option C';

INSERT INTO dbo.Data (Name, Flags)
    SELECT 'George', 0
    UNION ALL
    SELECT 'Bob', 1
    UNION ALL
    SELECT 'Bill', 3;

-- for C#
SELECT
    d.ID,
    d.Name,
    d.Flags
FROM
    dbo.Data d;

-- for other callers vertical
SELECT
    d.ID,
    d.Name,
    d.Flags,
    f.Name AS Flag,
    f.Value
FROM
    dbo.Data d
        LEFT JOIN dbo.Flag f ON
            d.Flags & f.Value = f.Value;

-- for other callers horizontal
SELECT
    p.Name,
    p.[Option A],
    p.[Option B],
    p.[Option C]
FROM
    (
        SELECT
            d.Name,
            f.Name AS Flag,
            f.Value
        FROM
            dbo.Data d
                LEFT JOIN dbo.Flag f ON
                    d.Flags & f.Value = f.Value
    ) d
PIVOT
(
    COUNT(d.Value)
    FOR d.Flag IN ([Option A], [Option B], [Option C])
) p;

SELECT
    d.ID,
    d.Name,
    d.Flags
FROM
    dbo.Data d
WHERE
    EXISTS
    (
        SELECT *
        FROM
            dbo.Flag f
        WHERE
            d.Flags & f.Value = f.Value AND
            f.Name IN ('Option A', 'Option B')
    );
于 2014-06-06T03:35:43.243 に答える
1

SQLのFlag Enumに10個のオプションが設定されており、これをint値としてデータベースに保存したいということだと思います

例えば

[Flags]
public enum Options
{
0 = None
1 = OP1
2 = OP2
4 = OP3
...
}

これを C# 以外でチェックする必要がある場合は、Bit Wise 操作を使用してチェック対象を確認するだけです。これは & 演算子を使用して SQL で行うことができます (ここで確認してください)。ほとんどの言語にはビット単位の実装もあると思います。

于 2014-06-05T13:57:48.863 に答える