zoukankan      html  css  js  c++  java
  • SQL 位运算

    在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";

              这是第二种写法:   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 不支持位运算

    select 2|8       --10 
    select 2|8|1    --11

    select 10&8    --8,包含,10=8+2 
    select 10&2    --2,包含,10=2+8 
    select 10&4    --0,不包含 
    select 19&16  --16,包含,19=16+2+1 
    select 19&8    --0,包含,19=16+2+1

    select * from SqlBitOperation where FBitTags&4=4

     

    在权限中的应用

    1、两张表

    (1)、操作与权限标志表

    if exists (select * from sysobjects where id = OBJECT_ID('[RightTags]') and OBJECTPROPERTY(id, 'IsUserTable') = 1) 
    DROP TABLE [RightTags]

    CREATE TABLE [RightTags] ( 
    [Pkid] [int]  IDENTITY (1, 1)  NOT NULL, 
    [RightsName] [nvarchar]  (50) NOT NULL, 
    [RightsTag] [int]  NOT NULL DEFAULT (0))

    ALTER TABLE [RightTags] WITH NOCHECK ADD  CONSTRAINT [PK_RightTags] PRIMARY KEY  NONCLUSTERED ( [Pkid] ) 

    SET IDENTITY_INSERT [RightTags] ON 
    INSERT [RightTags] ([Pkid],[RightsName],[RightsTag]) VALUES ( 1,'吃饭',1) 
    INSERT [RightTags] ([Pkid],[RightsName],[RightsTag]) VALUES ( 2,'拉屎',2) 
    INSERT [RightTags] ([Pkid],[RightsName],[RightsTag]) VALUES ( 3,'打炮',4) 
    INSERT [RightTags] ([Pkid],[RightsName],[RightsTag]) VALUES ( 4,'泡妞',8) 
    INSERT [RightTags] ([Pkid],[RightsName],[RightsTag]) VALUES ( 5,'生子',16) 
    INSERT [RightTags] ([Pkid],[RightsName],[RightsTag]) VALUES ( 6,'包二奶',32) 
    SET IDENTITY_INSERT [RightTags] OFF

    20100205011709875

    (2)、用户与权限表

    if exists (select * from sysobjects where id = OBJECT_ID('[RightUsers]') and OBJECTPROPERTY(id, 'IsUserTable') = 1) 
    DROP TABLE [RightUsers]

    CREATE TABLE [RightUsers] ( 
    [Pkid] [int]  IDENTITY (1, 1)  NOT NULL, 
    [FUser] [nvarchar]  (50) NOT NULL, 
    [UserRights] [int]  NOT NULL DEFAULT (0))

    ALTER TABLE [RightUsers] WITH NOCHECK ADD  CONSTRAINT [PK_RightUsers] PRIMARY KEY  NONCLUSTERED ( [Pkid] ) 

    SET IDENTITY_INSERT [RightUsers] ON 
    INSERT [RightUsers] ([Pkid],[FUser],[UserRights]) VALUES ( 1,'张三',7) 
    INSERT [RightUsers] ([Pkid],[FUser],[UserRights]) VALUES ( 2,'李四',9) 
    INSERT [RightUsers] ([Pkid],[FUser],[UserRights]) VALUES ( 3,'王老板',63) 
    INSERT [RightUsers] ([Pkid],[FUser],[UserRights]) VALUES ( 4,'朱麻子',0) 
    SET IDENTITY_INSERT [RightUsers] OFF

    20100205011725281

     

    2、访问判断是否有权限

    --1.查询权限 
    declare @iRights as int 
    select @iRights=(select top 1 RightsTag from RightTags where RightsName='打炮') 
    --print @iRights 
    select * from RightUsers where UserRights&@iRights=@iRights --所有可以打炮的人 
    select * from RightUsers where FUser='李四' and UserRights&@iRights=@iRights   --此人是否可以打炮(有无记录集) 
    select * from RightUsers where FUser='王老板' and UserRights&@iRights=@iRights --此人是否可以打炮(有无记录集)

    go

     

    3、设置权限

    --2.设置权限 
    declare @yourRights int 
    select @yourRights=(select sum(RightsTag) from RightTags where RightsName in('吃饭','拉屎','打炮')) 
    --print @yourRights

    update RightUsers set UserRights=@yourRights where FUser='张三' 
    go

     

    4、查看此人的所有权限

    --3.查看此人的所有权限 
    declare @yourRights as int 
    select @yourRights=(select UserRights from RightUsers where FUser='李四') 
    print @yourRights

    select * from RightTags where @yourRights&RightsTag=RightsTag 
    go

     

    5、检测权限表权限值是否为2的整数次方(操作权限标志的有效性:唯一+2的整数次方)

    select power(2,6) --64
    select power(2.000,5.500) --45.255

    select log(64.000)/log(2.000)--6.0

    ------------------------------
    declare @setNewOperateRightTags int --添加一个新操作权限
    set @setNewOperateRightTags=64  --64是2的整数次方
    --set @setNewOperateRightTags=63  --63不是2的整数次方

    declare @number float
    set @number=log(@setNewOperateRightTags)/log(2.000)
    --print @number
    if(ceiling(@number)=floor(@number))--取最大整数=取最小整数
    begin
      print cast(@setNewOperateRightTags as varchar(16)) + '是2的整数次方,可以用作权限标志值'
    end
    else
    begin
      print cast(@setNewOperateRightTags as varchar(16)) + '不是2的整数次方,不能用作权限标志值'
    end

    ------------------------------ 

  • 相关阅读:
    Xcode编译WebDriverAgentRunner报错:The bundle identifier for IntegrationApp.app couldn’t be read.解决方案
    python+django更新表结构执行相关命令报错:No installed app with label 'interface_crud'解决方案
    python激活虚拟环境env报错:no such file or directory: env/Scripts/activate解决方案
    Django创建api_crud app时报错:file "manage.py", line 16 ) from exc ^ SyntaxError: invalid syntax解决方案
    Redis未授权访问漏洞复现
    逻辑漏洞小结之SRC篇
    Linux下清空用户登录记录和命令历史的方法
    linux下直接清空日志的方法
    Linux Hackers/Suspicious Account Detection
    linux查看所有用户信息
  • 原文地址:https://www.cnblogs.com/goody9807/p/2480895.html
Copyright © 2011-2022 走看看