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
macheDas 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
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.
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.
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.
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.
Tags und Links sql sql-server-2008 bit-manipulation