7

SQL2k8テーブルで比較的大きなフラグのセットを処理する方法についてアドバイスが必要です。

2つの質問、我慢してください:)

1つのレコードに保存したいフラグが20個あるとします。

例えば:

CanRead = 0x1 CanWrite = 0x2 CanModify =0x4...などで最終フラグ2^20

ここで、1つのレコードの次の組み合わせを設定すると、次のようになります。書ける

WHERE(Permissions&CanRead)= CanReadを実行すると、そのレコードに許可が必要かどうかを簡単に確認できます。

それはうまくいきます。

ただし、書き込みまたは変更が可能なすべてのレコードも取得したいと思います。

WHERE(Permissions&(CanWrite | CanModify))=(CanWrite | CanModify)を発行すると、アクセス許可がCanRead|に設定されているレコードを取得できません。書ける

言い換えると、プロシージャに送信しているマスク内のフラグのいずれかに一致するレコードを見つけるにはどうすればよいですか?

2番目の質問、SQL 2008のパフォーマンスはどの程度ですか?実際には、20ビットフィールドを作成する方が良いでしょうか?

ご協力いただきありがとうございます

4

8 に答える 8

12

あなたの Permissions 列は Int だと思います。そうである場合は、以下に示すサンプル コードを試してみることをお勧めします。これにより、機能がどのように機能するかが明確に示されます。

Declare @Temp Table(Permission Int, PermissionType VarChar(20))

Declare @CanRead Int
Declare @CanWrite Int
Declare @CanModify Int

Select @CanRead = 1, @CanWrite = 2, @CanModify = 4

Insert Into @Temp Values(@CanRead | @CanWrite, 'Read,write')
Insert Into @Temp Values(@CanRead, 'Read')
Insert Into @Temp Values(@CanWrite, 'Write')
Insert Into @Temp Values(@CanModify | @CanWrite, 'Modify, write')
Insert Into @Temp Values(@CanModify, 'Modify')

Select * 
From   @Temp 
Where  Permission & (@CanRead | @CanWrite) > 0

Select * 
From   @Temp 
Where  Permission & (@CanRead | @CanModify) > 0

論理積を使用すると、条件に応じて 1 が適切に設定された数値が得られます。何も一致しない場合、結果は 0 になります。1 つ以上の条件が一致する場合、結果は 0 より大きくなります。

例を示しましょう。

CanRead = 1、CanWrite = 2、および CanModify = 4 とします。有効な組み合わせは次のとおりです。

Modify Write Read Permissions
------ ----- ---- -----------
  0       0    0   Nothing
  0       0    1   Read
  0       1    0   Write
  0       1    1   Read, Write
  1       0    0   Modify
  1       0    1   Modify, Read
  1       1    0   Modify, Write
  1       1    1   Modify, Write, Read

ここで、読み取りまたは変更をテストするとします。アプリから (CanRead | CanModify) を渡します。これは 101 (2 進数) になります。

最初に、これを ONLY が読み取ったテーブルの行に対してテストしてみましょう。

   001 (Row from table)
&  101 (Permissions to test)
------
   001 (result is greater than 0)

では、書き込みしかない行に対してテストしてみましょう。

   010 (Row from table)
&  101 (Permission to test)
------
   000 (result = 0)

次に、3 つの権限すべてを持つ行に対してテストします。

   111 (Row from table)
&  101 (Permission to test)
------
   101 (result is greater than 0)

AND 演算の結果が値 = 0 になった場合、テストされた権限のいずれもその行に適用されないことがわかります。値が 0 より大きい場合、少なくとも 1 つの行が存在します。

于 2008-10-01T17:11:30.257 に答える
11

そうしないでください。CSV 文字列をメモ フィールドに保存して、データベースの目的を無効にするようなものです。

すべてのフラグにブール (ビット) 値を使用します。この特定のサンプルでは、​​読み取り、書き込み、または変更が可能なすべてのものを見つけています。

WHERE CanRead AND (CanWrite OR CanModify)

巧妙なハックのない単純な純粋な SQL。フラグごとに浪費している余分な 7 ビットは、頭を悩ませる価値はありません。

于 2008-10-01T16:52:05.170 に答える
6

どうですか

WHERE (Permissions & CanWrite) = CanWrite 
OR (Permissions & CanModify) = CanModify

于 2008-10-01T16:39:48.240 に答える
3

WHERE(Permissions&CanWrite)= CanWrite OR(Permissions&CanModify)= CanModify

おもう

于 2008-10-01T16:42:36.267 に答える
3

というほど単純ではないでしょうか...

WHERE (Permissions & ( CanWrite | CanModify )) > 0

...「ビット」が 1 に設定されると、「&」演算子の値がゼロ以外になるためです。

もうすぐ帰宅する深夜なので、脳の働きが悪いのかもしれません。

于 2008-10-01T16:50:30.803 に答える
1

別の権限モデルを使用する方がかなり良いでしょう。

20個のフラグは、再考が必要であることを示しています。ほとんどのファイリングシステムは、12個の基本的なフラグとACLで対応できます。おそらく、権限を付与するだけの別のテーブルがあるか、オブジェクトやアクセサーをグループ化して別の制御を許可します。

20個の個別のフィールドがある方が選択が速くなると思いますが、パフォーマンスのために20個のフィールドを追加することもしません。

- アップデート -

次のように記述された元のクエリ

 WHERE (Permissions & ( CanWrite | CanModify )) > 0

十分ですが、データベースにあるのは、エンティティが持つことができる属性のセットであるかのように聞こえます。この場合、これを行うための(データベース用語での)唯一の賢明な方法は、属性テーブルとの1対多の関係を使用することです。

于 2008-10-01T16:48:35.817 に答える
0

いいえ、それはうまくいきません。

手順にマスクを1つだけ送信します

C# で @filter = CanModify | で埋める @filter のようなもの。書ける

そのため、プロシージャは OR された値をフィルターとして取得します。

ところで、これは許可モデルではありません。例として使用しています。

オブジェクトが持つことができる約 20 の一意のフラグが実際にあります。

于 2008-10-01T16:49:25.923 に答える
0

これは、他のキーでもクエリを実行している場合にのみ実行してください。

フラグの組み合わせでクエリを実行している場合は、これを行わないでください。この列に対するインデックスは、一般的に役に立ちません。テーブルスキャンに制限されます。

于 2008-10-01T20:10:50.183 に答える