SQL Server 中的位運算與C#枚舉位運算的結合

首先來講講SQL Server 中的位運算:

在SQL Server ,採用1,2,4,8,16.....等用數字標識的狀態字段可以進行累加,對存在的幾種狀態進行組合,從而可形成各種組合狀態 

例如:一條記錄該字段原來的數字是,2,如我們想加上4,則可以用

update t_User set iFlag = iFlag | 4  where UserID = 1

(iFlag 爲該字段名)

例2:在加上4之後我們想去掉4怎麼辦呢,可以這樣實現

update t_User set iFlag = iFlag ^4 where UserID = 1

這樣就又把4從該記錄中去掉了.

如果我們想選擇所有爲2的記錄該怎麼做呢,可以這樣實現

select * from t_User where iFlag &2 = 2

SQL中的位運算不但可以取出各種值,而且我們可以對他對數據進行排序

舉例如下,新聞列表中的一個字段標識爲

1:置頂

2:不置頂

4:推薦

8:不推薦

該字段的值可以爲這4種狀態的組合,如果我們根據一定條件想把所有置頂的放在前面該如何做呢

select * from t_News order by iFlag & 1 desc

這樣我們就把所有置頂的貼子排在前面,當然這裏可以加上一定的Where 條件,在Where  裏也可可以加一定的位運算,

關於位運算可以查閱相應的SQL 幫助

下面來講一講C#中的枚舉位運算

這裏我們定義一個枚舉

    [Flags]
    enum UserFlag
    {
        a = 1,
        b = 2,
        c = 4,
        d = 8,
        e = 16,
        f = 32
    }

 

在代碼里加上如下處理

    protected void Page_Load(object sender, EventArgs e)
    {

        if (!IsPostBack)
        {

            string strSQL = "select * from v_User where iFlag & @iFlag = @iFlag";

            //SqlParameter parm = new SqlParameter("@iFlag",SqlDbType.Int,4);
            //parm.Value = UserFlag.a | UserFlag.b ;
            SqlConnection con = new SqlConnection("server=.;database=Sinvan_TexDB;User Id=sa;pwd=123;");

            SqlCommand comm = new SqlCommand(strSQL, con);

            comm.Parameters.Add("@iFlag", SqlDbType.Int, 4).Value = UserFlag.a | UserFlag.b;

            SqlDataAdapter adp = new SqlDataAdapter(comm);
            DataTable dTable = new DataTable();
            adp.Fill(dTable);


            UserFlag userFlag = (UserFlag)Enum.Parse(typeof(UserFlag), dTable.Rows[0][11].ToString());
           

        }
    }

 

進行處理之後userFlag就是數據庫中存在的各種組合

我們同樣可對其進行一定的位運算處理

如我們想加上 UserFlag.c 可進行如下操作

userFlag = userFlag | Userflag.c

如想去掉UserFlag.c 可進行如下操作

userFlag = userFlag ^ UserFlag.c

如我們要判斷是該標識中是否存在c可進行如下操作

(userFlag & UserFlag.c) == UserFlag.c

是不是與SQL Server 中的操作類似,位運算不管什麼語言都是通用的,呵呵

可惜Access 不支持位運算,這也是一個遺憾吧,不過有高人寫過一模塊,一起提供,沒進行過測試,供大家參考

 'Binary and operate
 Public Function BitAnd(ByVal a As Long, ByVal b As Long) As Boolean

     If (a <= 0 Or b <= 0) Then
         BitAnd = False
         Exit Function
     End If
     Dim b1() As Integer, b2() As Integer
     ToBytes a, b1
    ToBytes b, b2
    Dim i As Integer
    For i = 0 To 32
        If b1(i) = b2(i) And b1(i) = 1 Then
            BitAnd = True
            Exit Function
        End If
    Next i
    BitAnd = False
End Function

Private Sub ToBytes(ByVal v As Long, ByRef result() As Integer)

    ReDim result(32) As Integer
    Dim iLoc As Integer
    DecToBin v, result(), iLoc

End Sub

Private Sub DecToBin(ByVal v As Long, ByRef result() As Integer, ByRef iLoc As Integer)
    If v < 2 Then
        result(iLoc) = v
        Exit Sub
    End If
    Dim r As Integer
    r = v Mod 2
    result(iLoc) = r
    iLoc = iLoc + 1
    Dim m As Long
    m = v / 2
    DecToBin m, result, iLoc
End Sub

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章