前几天有一个需求很头痛,部门是有上下级关系的,在给部门的经理赋予角色和权限的时候,通常我们都会认为假如经理A的部门是1,那么我给了他部门1 的管理权限,那么1的下级部门101,102,103 “自然而然的”都应该给他管理。

这个自然而然可不是想当然的那么自然,尤其系统没有设置批量添加功能的时候,靠人工一个个的去添加下级部门真的是不现实。更过分的是,用户要求整个公司的管理人员都要自动的拥有其所在部门的所有下级部门的某个权限,emmmm,烦死了,领导那么多,做事的小弟却只有一个,一个个手动添加到何时???

由于整个系统都是依赖sql存储过程,别问我为什么不写java啊net啊c#啊什么的,这个系统是公司购买的,全部都是存储过程,几千上万个吧,几千行的存储过程能把人看瞎咯!没办法只能随行就市写起来咯。

思路也很清楚,首先要把这些管理人员和所在部门找到,这是其一,其二是要把这些管理人员的下级部门找到,这两个都找到以后,要顺序循环管理人员,然后把他的部门和权限关联起来。说起来容易做起来难,尤其我的存储过程还没达到精通的程度,也是反复琢磨,终于给搞出来了。

以下就是具体代码,仅供参考:

首先准备部门和下级部门数据,这个就比较简单了,一个简单的递归查询,写成存储过程以便调用。

CREATE PROCEDURE [dbo].[rsp_selectTreeofsubDep]  --查询下级部门
-- Add the parameters for the stored procedure here
@depid int --父部门id
AS
BEGIN
with cte as (
select d.depID ,d.AdminID from Department d
where DepID = @depid
union all
select d.DepID ,d.AdminID from Department d
inner join cte o on o.DepID = d.AdminID
)
select DepID from cte
END GO

  然后就是主存储过程,用来循环批量插入数据的:

CREATE Procedure [dbo].[rsp_insertMultitiesofDep]      --代理部门批量插入      

AS
DECLARE @i int, @RoleID int,@Depid int ----循环角色ID DECLARE @UserDepidTemp TABLE --部门负责人代号和其所在部门
(
UserID varchar(10),
Depid int
)
DECLARE @subDepidTemp TABLE --部门负责人的下级部门
(
Depid int
)
DECLARE @UserDepidRoleTemp TABLE --部门负责人角色和其所在部门
(
RoleID int,
Depid int,
FlagID TINYINT
)
BEGIN
--整理部门负责人代号和所在部门 ,将部门负责人的用户名和部门编号放到临时表
insert into @UserDepidTemp
select UserID,Depid from employee
where UserID in (select distinct e.UserID from employee e
left join Department d on e.DepID = d.DepID
join employee p on e.NID = p.MANAGER ) --整理部门负责人的角色ID和部门,将角色表的部门经理的角色和用户表的部门经理的部门放到临时表,标志位全部置0
insert into @UserDepidRoleTemp(RoleID,Depid,FlagID)
select RoleID ,depid ,0 from USER_ROLE u left join @UserDepidTemp b on u.UserID = b.UserID
where depid is not null ---开始循环角色,用户取自上面的角色代号和部门代号的临时表
SET @i=1
WHILE( @i>=1)
BEGIN
SELECT @RoleID=''
SELECT TOP 1 @RoleID = RoleID FROM @UserDepidRoleTemp WHERE FlagID=0 --顺序读取表中的第一个角色用户,即当前角色用户
SET @i=@@ROWCOUNT --受影响行数为1 select @Depid=''
select top 1 @Depid = Depid from @UserDepidRoleTemp WHERE RoleID=@RoleID --获取当前用户角色所在部门作为父部门,以便下一行查询下级部门列表
insert into @subDepidTemp EXEC rsp_selectTreeofsubDep @Depid --获取下级部门结果集
insert into ROLE_DEPT (ROLEID,DepID) SELECT @Roleid,Depid from @subDepidTemp --将当前循环表中的用户角色和查询到的下级部门放入角色部门表
IF @i<=0 GOTO Return_Lab --当i小于0时跳出循环
IF @@error=0
delete from @subDepidTemp --千万记得要删除下级部门临时表,这个表放的是当前角色用户的下级部门
UPDATE @UserDepidRoleTemp SET FlagID=1 WHERE ID = @ID --将用户角色和所在部门的标志位置1,下次循环将跳过该数据
Return_Lab:
END
END GO

嗯,如上,就上面这个存储过程,现在来看也不复杂,可是我还是写了好久,好几个地方数据都拿错了,导致测试表的结果总不对。

当然现在这种批量事务一般都用其他服务端语言解决了,仍然用纯sql实现的方案比较少了,我也是赶鸭子上架硬着头皮写,总算写出来了也算完成了一件事。

换新工作后每天就是sql,各种眼花缭乱的sql整到没脾气,存储过程虽然也能写,但是更深层次的事务管理和锁啊同步啊互斥啥的都没理解,能用就行,还需慢慢修行吧!也不知道纯sql能找到工作否。

sql存储过程中循环批量插入的更多相关文章

  1. SQL存储过程+游标 循环批量()操作数据

    本人收集的,挺有用的 1. 利用游标循环更新.删除MemberAccount表中的数据 DECLARE My_Cursor CURSOR --定义游标 FOR (SELECT * FROM dbo.M ...

  2. mysql 循环批量插入

    背景 前几天在MySql上做分页时,看到有博文说使用 limit 0,10 方式分页会有丢数据问题,有人又说不会,于是想自己测试一下.测试时没有数据,便安装了一个MySql,建了张表,在建了个whil ...

  3. sql server 使用SqlBulkCopy批量插入数据库

    sql server sqlbulkcopy 批量数据插入数据库使用的是System.Data.SqlClient中的 SqlBulkCopy批量数据插入数据库 sql server 使用SqlBul ...

  4. 在SQL存储过程中给条件变量加上单引号

    在SQL存储过程中给条件变量加上单引号,不加语句就会出问题,以下就是在存储过程中将条件where设置成了动态变化的,给where赋完值再和前面的语句拼接,再execute(SQL) ), )), )+ ...

  5. sql存储过程中使用 output

    1.sql存储过程中使用 output CREATE PROCEDURE [dbo].[P_Max] @a int, -- 输入 @b int, -- 输入 @Returnc int output - ...

  6. sql存储过程中使用 output、nvarchar(max)

    1.sql存储过程中使用 output CREATE PROCEDURE [dbo].[P_Max] @a int, -- 输入 @b int, -- 输入 @Returnc int output - ...

  7. JDBC中的批量插入和乱码解决

    字符集-乱码问题 用JDBC访问MySql数据库的时候,如果JDBC使用的字符集和MySql使用的字符集不一致,那么会导致乱码发生.解决办法当时是在使用JDBC的时候指定和数据库一样的字符集.我们可以 ...

  8. mysql使用存储过程&函数实现批量插入

    写这边文章的目的,是想结合mysql 存储过程+函数完成一个批量删除的功能吧...正好也好加深下对procedure和function的熟练操作吧...废话不多说,我就直接上表结构啦哈,如下: cre ...

  9. 怎样SQL存储过程中执行动态SQL语句

    MSSQL为我们提供了两种动态执行SQL语句的命令,分别是EXEC和sp_executesql;通常,sp_executesql则更具有优势,它提供了输入输出接口,而EXEC没有.还有一个最大的好处就 ...

随机推荐

  1. 用链表和数组实现HASH表,几种碰撞冲突解决方法

    Hash算法中要解决一个碰撞冲突的办法,后文中描述了几种解决方法.下面代码中用的是链式地址法,就是用链表和数组实现HASH表. he/*hash table max size*/ #define HA ...

  2. kuangbin专题 专题一 简单搜索 Fire Game FZU - 2150

    题目链接:https://vjudge.net/problem/FZU-2150 题意:’ . '代表火无法烧着的地方,‘ # ’表示草,火可以烧着.选择任意两个‘ # ’(可以两个都选同一个 ‘ # ...

  3. JavaScript循环及输出方式

    好一段时间没写了,今天写一下JavaScript的循环和输出吧! 其实JavaScrip的循环跟C#.Java的循环用法是相同的. <!DOCTYPE html> <html> ...

  4. Bzoj: 2073 [POI2004]PRZ 题解

    2073: [POI2004]PRZ Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 401  Solved: 296[Submit][Status][D ...

  5. python实现DFA模拟程序(附java实现代码)

    DFA(确定的有穷自动机) 一个确定的有穷自动机M是一个五元组: M=(K,∑,f,S,Z) K是一个有穷集,它的每个元素称为一个状态. ∑是一个有穷字母表,它的每一个元素称为一个输入符号,所以也陈∑ ...

  6. python爬虫常用正则表达式组合匹配

    ["\']匹配什么?(.*?)匹配什么? ["\']       -----------     匹配单双引号 (.*?)xxx ----------- 匹配任意长度字符+xxx ...

  7. 最全caffe安装踩坑记录(Anaconda,nvidia-docker,Linux编译)

    Anaconda,nvidia-docker,Linux三种方式安装caffe 1.Anaconda安装caffe 1.首先安装anaconda 2.创建虚拟环境(python2.7) conda c ...

  8. [剑指offer] 54. 字符流中第一个不重复的字符

    题目描述 请实现一个函数用来找出字符流中第一个只出现一次的字符.例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g".当从该字符流中读出 ...

  9. fiddle知识点六、如何使用fiddle进行模拟弱网

    为什么要模拟弱网 随着互联网的快速发展,越来越多的应用核心功能需要网络进行实现.同一应用在2G.3G.4G和WiFi的不停网络下,响应各有不同.但是因为现在的网络普遍为4G网络,为了保证应用在不同的网 ...

  10. 面向对象和pickle模块结合

    面向对象和pickle模块相关 1.面向对象: class 类名: def init(self,参数1,参数2): self.对象的属性1 = 参数1 self.对象的属性2 = 参数2 def 方法 ...