Wie behandelt man viele Flags für einen SQL-Datensatz?

7

Ich brauche Ratschläge, wie man relativ große Mengen von Flags in meiner SQL2k8-Tabelle behandelt.

Zwei Fragen, bitte mit mir:)

Nehmen wir an, ich habe 20 Flaggen, die ich für einen Datensatz speichern möchte.

Zum Beispiel:

CanRead = 0x1 CanWrite = 0x2 CanModify = 0x4 ... und so weiter zur letzten Flagge 2 ^ 20

Nun, wenn ich die folgende Kombination eines Datensatzes einstelle: Permissions = CanRead | CanWrite

Ich kann leicht überprüfen, ob dieser Datensatz eine Erlaubnis benötigt, indem ich WHERE (Permissions & amp; CanRead) = CanRead

mache

Das funktioniert.

Aber ich möchte auch alle Datensätze abrufen, die entweder schreiben oder ändern können.

Wenn ich WHERE ausstelle (Berechtigungen & amp; (CanWrite | CanModify)) = (CanWrite | CanModify), werde ich offensichtlich meinen Datensatz nicht bekommen, der Berechtigungen auf CanRead gesetzt hat CanWrite

Mit anderen Worten, wie kann ich Datensätze finden, die mit einem der Flags in meiner Maske übereinstimmen, die ich an die Prozedur sende?

Zweite Frage, wie performant SQL 2008 ist? Wäre es tatsächlich besser, 20-Bit-Felder zu erstellen?

Danke für Ihre Hilfe

    
ErikE 01.10.2008, 16:32
quelle

8 Antworten

12

Ich nehme an, dass Ihre Berechtigungsspalte ein Int ist. Wenn es so ist, ermutige ich Sie, mit dem Beispielcode herumzuspielen, den ich unten zur Verfügung stelle. Dies sollte Ihnen einen deutlichen Hinweis darauf geben, wie die Funktionalität funktioniert.

%Vor%

Wenn Sie logisch und verwenden, erhalten Sie entsprechend Ihrer Bedingung eine Nummer, die mit den 1en übereinstimmt. Wenn nichts übereinstimmt, ist das Ergebnis 0. Wenn eine oder mehrere Bedingungen übereinstimmen, ist das Ergebnis größer als 0.

Lassen Sie mich Ihnen ein Beispiel zeigen.

Angenommen, CanRead = 1, CanWrite = 2 und CanModify = 4. Die gültigen Kombinationen lauten:

%Vor%

Nehmen Sie nun an, Sie möchten das Lesen oder Ändern testen. Von Ihrer App aus würden Sie reingehen (CanRead | CanModify). Dies wäre 101 (binär).

Zuerst testen wir das mit einer Zeile in der Tabelle, die NUR gelesen hat.

%Vor%

Nun, lassen Sie uns gegen eine Zeile testen, die nur Write hat.

%Vor%

Jetzt testen Sie es gegen Zeile, die alle 3 Berechtigungen hat.

%Vor%

Ich hoffe, dass Sie sehen können, dass, wenn das Ergebnis der UND-Operation zu einem Wert = 0 führt, keine der getesteten Berechtigungen für diese Zeile gilt. Wenn der Wert größer als 0 ist, ist mindestens eine Zeile vorhanden.

    
G Mastros 01.10.2008 17:11
quelle
11

Tun Sie das nicht. Es ist so, als würde man eine CSV-Zeichenfolge in einem Memofeld speichern und den Zweck einer Datenbank vereiteln.

Verwenden Sie für jedes Flag einen booleschen (Bit-) Wert. In diesem speziellen Beispiel finden Sie alles, was Sie lesen und schreiben oder ändern können:

%Vor%

Einfaches reines SQL ohne clevere Hacks. Die zusätzlichen 7 Bits, die Sie für jede Flagge verschwenden, sind die Kopfschmerzen nicht wert.

    
VVS 01.10.2008 16:52
quelle
6

Was ist mit

? %Vor%

?

    
Vinko Vrsalovic 01.10.2008 16:39
quelle
3

WHERE (Berechtigungen & amp; CanWrite) = CanWrite ODER (Berechtigungen & amp; CanModify) = CanModify

Ich denke

    
Sijin 01.10.2008 16:42
quelle
3

Ist es nicht so einfach wie ...

%Vor%

... da jedes 'Bit' auf 1 gesetzt wird, ergibt sich ein Wert ungleich Null für das '& amp;' Betreiber.

Es ist spät am Tag, und ich bin gerade dabei, nach Hause zu gehen, also könnte mein Gehirn ineffizient arbeiten.

    
belugabob 01.10.2008 16:50
quelle
1

Es wäre wesentlich besser, ein anderes Berechtigungsmodell zu haben.

20 Flags würden mir zeigen, dass ein Umdenken erforderlich ist, die meisten Ablagesysteme können mit 12 Basisflags und ACLS auskommen - vielleicht mit einer separaten Tabelle, die nur Berechtigungen gewährt, oder Gruppierung von Objekten oder Accessoren, um unterschiedliche Kontrolle zu ermöglichen. p>

Ich würde erwarten, dass eine Auswahl schneller 20 separate Felder hat - aber ich würde auch keine 20 Felder für die Leistung hinzufügen.

- Aktualisierung -

die ursprüngliche Abfrage geschrieben als

%Vor%

würde ausreichen, es klingt jedoch so, als ob das, was Sie in der Datenbank haben, eine Menge von Attributen ist, die eine Entität haben kann. In diesem Fall ist die einzige sinnvolle (in Bezug auf die Datenbank) Art, dies zu tun, eine Eins-zu-Viele-Beziehung zu einer Attributtabelle.

    
Richard Harrison 01.10.2008 16:48
quelle
0

Nein, das wird nicht funktionieren.

Ich sende nur eine Maske an die Prozedur

Etwas wie @filter, das in C # mit @filter = CanModify | gefüllt wird CanWrite

Also, die Prozedur erhält den ODER-Wert als Filter.

Oh, und übrigens, es ist kein Berechtigungsmodell, ich benutze das nur als Beispiel.

Ich habe wirklich rund 20 eindeutige Flags, die mein Objekt haben kann.

    
mijo 01.10.2008 16:49
quelle
0

Tun Sie dies nur, wenn Sie auch nach einem anderen Schlüssel suchen.

Tun Sie dies nicht, wenn Sie nach Flag-Kombinationen suchen. Ein Index für diese Spalte hilft Ihnen im Allgemeinen nicht. Sie sind auf Table-Scans beschränkt.

    
Amy B 01.10.2008 20:10
quelle