Что же такое битовая маска.
Битовая маска (определение взято Википедии) — определённые данные, которые используются для выбора битов из двоичной строки или числа. Например, для получения значения пятого бита (считая слева) числа 10111011 нужно использовать маску 00001000 и применить операцию побитового алгебрологического «И» (конъюнкцию). В результате получится:
10111011 ^ 00001000 = 00001000
Битовые маски используются, например, для выбора битов из IP-адреса для адресации подсети.
Для чего это все необходимо.
Пусть есть таблица, содержащая телефонные звонки абонентов:

В поле статус хранится вид звонка:
- Answer
- Outgoing
- Abort
- Cancel
И стоит задача выбрать из таблицы все записи, удовлетворяющие определенному условию статуса. Несколько условий могут использоваться одновременно, например: необходимо выбрать и Abort и Cancel телефонные звонки.
Решение данной проблемы
Создадим тестовый проект консольного приложения и объявим в нем перечисление State, которое помечено атрибутом Flags:
C#
[Flags]
enum State : int
{
Answer=1,
Outgoing=2,
Abort=4,
Cancel=8
}
VB.NET
<Flags()> _
Enum State As Integer
Answer = 1
Outgoing = 2
Abort = 4
Cancel = 8
End Enum
Атрибут Flags указывает, что перечисление можно рассматривать как битовое поле, то есть теперь с таким перечислением можно выполнять операции логического ИЛИ (комбинировать значения).
Проведем тестирования такого функционала, для этого создадим функцию, которая будет выводить все возможные комбинации элементов перечисления:
С#
using System;
namespace BitMask
{
class Program
{
[Flags]
enum State : int
{
Answer = 1,
Outgoing = 2,
Abort = 4,
Cancel = 8
}
static void Main(string[] args)
{
ShowAllСombination();
Console.ReadKey();
}
static void ShowAllСombination()
{
for (int i = 1; i < 16; i++)
Console.WriteLine("{0} - {1}", i, (State)i);
}
}
}
VB.NET
Module BitMask_VB
<Flags()> _
Enum State As Integer
Answer = 1
Outgoing = 2
Abort = 4
Cancel = 8
End Enum
Sub Main()
ShowAllСombination()
Console.ReadKey()
End Sub
Sub ShowAllСombination()
For i As Integer = 1 To 15
Console.WriteLine("{0} - {1}", i, CType(i, State))
Next
End Sub
End Module
После выполнения данной программы на экране будут отображены все возможные комбинации значений перечисления:
1 - Answer
2 - Outgoing
3 - Answer, Outgoing
4 - Abort
5 - Answer, Abort
6 - Outgoing, Abort
7 - Answer, Outgoing, Abort
8 - Cancel
9 - Answer, Cancel
10 - Outgoing, Cancel
11 - Answer, Outgoing, Cancel
12 - Abort, Cancel
13 - Answer, Abort, Cancel
14 - Outgoing, Abort, Cancel
15 - Answer, Outgoing, Abort, Cancel
Заполнение таблицы тестовыми данными
Для того, что бы заполнить созданную таблицу данными, выполним несколько запросов, которые создадут необходимую для тестирования информацию:
INSERT INTO Calls VALUES (1,'Иванов','911',1) --Answer
INSERT INTO Calls VALUES (2,'Петров','924',2) --Outgoing
INSERT INTO Calls VALUES (3,'Сидоров','941',4) --Abort
INSERT INTO Calls VALUES (4,'Иванов','941',4) --Abort
INSERT INTO Calls VALUES (5,'Сидоров','971',8) --Cancel
INSERT INTO Calls VALUES (6,'Иванов','941',8) --Cancel
INSERT INTO Calls VALUES (7,'Иванов','913',8) --Cancel
INSERT INTO Calls VALUES (8,'Петров','943',1) --Answer
INSERT INTO Calls VALUES (9,'Иванов','976',2) --Outgoing
После выполнения запросов в таблице будет содержаться следующая информация:

Теперь все готово для создания хранимой процедуры, которая и будет получать необходимую информацию, используя битовую маску:
CREATE PROCEDURE dbo.GetCallsByState
@State int
AS
SELECT ID, Name, Phone, State
FROM Calls
WHERE (State & @State = State)
При выполнении хранимой процедуры происходит следующее:
SQL Server получает двоичное представлениеState и @State, выполняет логическую операцию И (результат операции логическое И будет истинным лишь тогда, когда истинны оба операнда). В результате чего получается число, которое потом сравнивается со значение State.
Пример:
State = 4
@State=5
4 в двоичной системе счисления 100, 5 – 101
100 - State
101 - @State
100 – Результат (если перевести 100 в десятичную систему счисления, то получится 4)
Вызов хранимой процедуры
Для демонстрации использования хранимой процедуры создадим консольное приложение:
C#
using System;
using System.Data;
using System.Data.SqlClient;
namespace BitMask
{
class Program
{
[Flags]
enum State : int
{
Answer = 1,
Outgoing = 2,
Abort = 4,
Cancel = 8
}
static void Main(string[] args)
{
Console.WriteLine();
ShowCalls(State.Abort | State.Answer);
Console.ReadKey();
}
static void ShowCalls(State state)
{
using (SqlConnection con = new SqlConnection("Data Source=(local);Initial Catalog=tester;Integrated Security=True"))
{
con.Open();
SqlCommand cmd = con.CreateCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "GetCallsByState";
cmd.Parameters.AddWithValue("@State", state);
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
Console.WriteLine(reader["ID"]);
Console.WriteLine(reader["Name"]);
Console.WriteLine(reader["Phone"]);
Console.WriteLine((State)reader["State"]);
Console.WriteLine("----------------------");
}
con.Close();
}
}
}
}
VB.NET
Imports System.Data.SqlClient
Module BitMask_VB
<Flags()> _
Enum State As Integer
Answer = 1
Outgoing = 2
Abort = 4
Cancel = 8
End Enum
Sub Main()
ShowCalls(State.Abort Or State.Answer)
Console.ReadKey()
End Sub
Sub ShowCalls(ByVal value As State)
Using con As New SqlConnection("Data Source=(local);Initial Catalog=tester;Integrated Security=True")
con.Open()
Dim cmd As SqlCommand = con.CreateCommand()
cmd.CommandType = CommandType.StoredProcedure
cmd.CommandText = "GetCallsByState"
cmd.Parameters.AddWithValue("@State", value)
Dim reader As SqlDataReader = cmd.ExecuteReader()
While (reader.Read())
Console.WriteLine(reader("ID"))
Console.WriteLine(reader("Name"))
Console.WriteLine(reader("Phone"))
Console.WriteLine(CType(reader("State"), State))
Console.WriteLine("----------------------")
End While
con.Close()
End Using
End Sub
End Module
Результат работы программы будет следующий:
1
Иванов
911
1
----------------------
3
Сидоров
941
4
----------------------
4
Иванов
941
4
----------------------
8
Петров
943
1
----------------------
Теперь что бы получить любую комбинацию необходимо объединить несколько значений перечисления.
Используемые источники
- http://msdn.microsoft.com/
- SQL Server Books Online
- http://ru.wikipedia.org
|