-- 定位数据
-- 设计思路:
-- 保存要被移动记录的原主键值和新主键值(如果有主键的话),然后比较两个主键值的大小(记录信息按升序排列),
-- 如果原主键值大,表明该记录被移动到前面的新位置,可将原位置的记录信息保存下来,并将从新位置的记录信息到
-- 原记录的前一条记录的信息顺次往下移动,把保存的原记录移动到新位置即可。
-- 如果原主键值小,表明该记录被移动到后面的新位置,可将原位置的记录信息保存下来,并将从新位置的记录信息到
-- 原记录的下一条记录的信息顺次往上移动,把保存的原记录移动到新位置即可。实际上就是记录块的移动.
-- 但是,如果数据表中的数据非常庞大,该存储过程的执行效率将会下降.
use zzydb
--创建举例表(学生信息表)
create table t_studentsinfo
(i_id int identity(1,1), --系统自增流水号
c_stu_id nvarchar(10), --学号
c_classname nvarchar(50), --班级
d_birthday datetime) --出生日期
go
--向举例表中插入4条学生信息,以验证下面的存储过程(sp_myadjustrecordorder)
insert into t_studentsinfo values('001', '大二三班', '1978-01-25')
insert into t_studentsinfo values('002', '大一六班', '1979-02-05')
insert into t_studentsinfo values('003', '大四三班', '1981-07-15')
insert into t_studentsinfo values('004', '大三一班', '1976-01-05')
select * from t_studentsinfo
if object_id('sp_myadjustrecordorder') <> 0
drop proc sp_myadjustrecordorder
go
create proc sp_myadjustrecordorder(@oldstuid nvarchar(10), @newstuid nvarchar(10))
as
[email protected] 学生学号(用以表示被移动的记录),
[email protected] 学生学号(用以表示将被移动的记录插入的新位置)
begin
declare @old_i_id int, @new_i_id int
declare @i_blockcount int--即将被移动的记录块条数
declare @i int--循环变量
--获得id值
select @old_i_id = (select i_id from t_studentsinfo where c_stu_id = @oldstuid)
select @new_i_id = (select i_id from t_studentsinfo where c_stu_id = @newstuid)
select @i_blockcount = abs(@old_i_id - @new_i_id)
--保存被移动的学生信息
select c_stu_id, c_classname, d_birthday
into new_studentsinfo--临时创建的表,用完后删除
from t_studentsinfo
where c_stu_id = @oldstuid
if @new_i_id < @old_i_id --将原记录信息移动到了前面
begin
select @i = 0
while @i <= @i_blockcount - 1
begin
update t_studentsinfo
set c_stu_id = t2.c_stu_id,
c_classname = t2.c_classname,
d_birthday = t2.d_birthday
from t_studentsinfo , t_studentsinfo t2
where (t_studentsinfo.i_id = @old_i_id - @i) and
(t2.i_id = @old_i_id - @i - 1)
select @i = @i + 1
end
end
if @new_i_id > @old_i_id --将原记录信息移动到了后面
begin
select @i = 0
while @i <= @i_blockcount - 1
begin
update t_studentsinfo
set c_stu_id = t2.c_stu_id,
c_classname = t2.c_classname,
d_birthday = t2.d_birthday
from t_studentsinfo, t_studentsinfo t2
where (t_studentsinfo.i_id = @old_i_id + @i) and
(t2.i_id = @old_i_id + @i + 1)
select @i = @i + 1
end
end
update t_studentsinfo
set c_stu_id = t3.c_stu_id,
c_classname = t3.c_classname,
d_birthday = t3.d_birthday
from t_studentsinfo t1, new_studentsinfo t3
where (t1.i_id = @new_i_id )
drop table new_studentsinfo
--if @new_i_id = @old_i_id --位置未发生改变,不做任何处理
end
go
--使用举例
--要求:将c_stu_id为'004'的学生信息移动到c_stu_id为'002'的学生信息之前的位置.
--调用存储过程 sp_myadjustrecordorder('004','002')即可.
--注意:这里的i_id必须是顺序的。
--备份表数据信息,以便于比较
select *
into studentsinfobackup
from t_studentsinfo
--比较结果是否一致
select * from studentsinfobackup
select * from t_studentsinfo
--移动数据记录信息,调用存储过程
exec sp_myadjustrecordorder '003', '002'
--比较结果是否改动
select * from studentsinfobackup
select * from t_studentsinfo