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
(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
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
------------------------------