求一个自定义排序的存储过程

我想自定义每条记录的序列号,这个序列号在客户端输入,假如表格里已经有如下序列号的存在了:
id
1
2
3
5
8
现在我想新插入一条记录,并把新插入的序列号值设为2,可现在2号记录已经存在了,所以我想先把2号记录加1,3号记录加1,5号记录和8号记录不变。这个存储过程该如何写呢?恳请各位朋友指教。
[202 byte] By [bit_byte] at [2008-1-9]
# 1
自己顶个先
bit_byte at 2007-10-19 > top of Msdn China Tech,MS-SQL Server,疑难问题...
# 2
怎么没人帮忙啊。
bit_byte at 2007-10-19 > top of Msdn China Tech,MS-SQL Server,疑难问题...
# 3
先把2号记录加1,3号记录加1,5号记录和8号记录不变
??这是什么规律啊?
# 4
TO:gc_ding(E.T)

因为3号跟5号中间断号了。所以此时5号,8号不能加1。
bit_byte at 2007-10-19 > top of Msdn China Tech,MS-SQL Server,疑难问题...
# 5
嗯,看明白了,正在构思。。。
# 6
简单的触发器就行了!
# 7
好象我在另一贴中写得很明白了.
j9988-j9988 at 2007-10-19 > top of Msdn China Tech,MS-SQL Server,疑难问题...
# 8
两种思路:
1、变量循环 定义一个变量,作为循环计数器,从1开始循环,每次都将第一个在表格中不存在的值填充到表格且跳出循环;如果是一次填充多个,就在多个都填充完后才跳出循环;
2、如果填充的是一个物理临时表,为提高效率,可以建一个只有序列字段的物理表并为它填充尽量多的值后建立升序索引,每次需要定义记录序列号时,直接执行查询:select min(临时id) from 临时表 where not exists (select 1 from 目标表 where 填充序列字段 = 临时表.临时id) 来获取最新的可以填充的序列号
adaizi1980-阿代 at 2007-10-19 > top of Msdn China Tech,MS-SQL Server,疑难问题...
# 9
看看这个行么

create procedure pro(@num int)
as
declare @temp_id int
set @temp_id=''
declare @cur_num int
declare cur_num cursor for
select id from 表名 order by id
open cur_num

fetch next from cur_num into @cur_num
while @@fetch_status = 0
begin
if @cur_num=@num
begin
set @temp_id=@cur_num+1
update 表名 set id=@cur_num+1 where id=@cur_num
end
else if @cur_num=@temp_id
begin
update 表名 set id=@temp_id+1 where id=@cur_num
set @temp_id=@cur_num+1
end
fetch next from cur_num into @cur_num

end
close cur_num
deallocate cur_num

go
# 10
CREATE TRIGGER tg_insertdata ON [dbo].[num]
instead of INSERT
AS
begin
if exists(select id from num where id = (select id from inserted))
begin
-------------------如果存在此记录的话
declare @middle varchar(20)
select @middle=id from inserted
declare @table table (cid int)
insert into @table select id from num where id=@middle
set @middle=@middle+1
while @@rowcount > 0
begin
if exists(select id from num where id=@middle)
begin
insert into @table select @middle
set @middle=@middle+1
end
else
begin
break
end
end
update num set id=id+1 where id in (select cid from @table)
insert into num select id from inserted
end
else
begin
insert into num select id from inserted
end
end

# 12
我来写一个存储过程
# 13
create table ta(id int)
insert ta
select 1
union all select 2
union all select 3
union all select 5
union all select 8

创建存储过程:

create proc test_p @id int
as
update a
set id=id+1
from ta a
where (exists(select 1 from ta where a.id=id+1)
or exists(select 1 from ta where a.id=id-1) )
and id!<@id --更新

insert ta select @id--插入

测试:
exec test_p 2

select * from ta order by id
id
-----------
1
2
3
4
5
8

(所影响的行数为 6 行)

# 14
create table ta(id int)
insert ta
select 1
union all select 2
union all select 3
union all select 5
union all select 8

用触发器:
create trigger test_tr on ta
instead of insert
as
begin
DECLARE @i int
DECLARE roy CURSOR
FOR SELECT * from inserted
OPEN roy
FETCH next FROM roy into @i
WHILE @@FETCH_STATUS = 0
begin
if exists(select 1 from ta where id=@i)
begin
update a
set id=id+1
from ta a
where (exists(select 1 from ta where a.id=id+1)
or exists(select 1 from ta where a.id=id-1) )
and id!<@i
end
insert ta select @i
FETCH NEXT FROM roy INTO @i
end
CLOSE roy
DEALLOCATE roy
end

--测试
insert ta select 1 union all select 6

查询:

select * from ta order by id
id
-----------
1
2
3
4
5
6
8

(所影响的行数为 7 行)

# 15
好像有多个连续时不太正确
ccrr7758258- at 2007-10-19 > top of Msdn China Tech,MS-SQL Server,疑难问题...
# 16
楼上帅哥提得好,由于楼主的列子也没有考虑到这种情况。偶发完贴完也考虑到这个问题,不能连发三贴。
以下贴出正确答案。
create table ta(id int)
insert ta
select 1
union all select 2
union all select 3
union all select 6
union all select 7
union all select 12
union all select 13

用存储过程:
create proc test_p @id int
as
begin
declare @j int,@sql varchar(1000)
if exists(select 1 from ta where id=@id)
begin
select @j=@id,@sql=''
while exists(select 1 from ta where id=@j)
begin
select @sql=@sql+','+rtrim(id) from ta where id=@j
select @j=@j+1
end
set @sql=stuff(@sql,1,1,'')
exec('update ta set id=id+1 where id in ('+@sql+')')
insert ta select @id
end
else
insert ta select @id
end

测试:
exec test_p 1
exec test_p 8
--truncate table ta 清空表数据

用触发器:
create trigger test_tr on ta
instead of insert
as
begin
declare @id int,@j int,@sql varchar(1000)
declare roy cursor
for select id from inserted
open roy
fetch next from roy into @id
while @@fetch_status=0
begin
if exists(select 1 from ta where id=@id)
begin
select @j=@id,@sql=''
while exists(select 1 from ta where id=@j)
begin
select @sql=@sql+','+rtrim(id) from ta where id=@j
select @j=@j+1
end
set @sql=stuff(@sql,1,1,'')
exec('update ta set id=id+1 where id in ('+@sql+')')
end
insert ta select @id
fetch next from roy into @id
end
CLOSE roy
DEALLOCATE roy
end

测试:
insert ta
select 1
union all select 2
union all select 3

删除测试:
drop proc test_p
drop table ta
# 17
roy_88大哥,不行啊,我的表有好几个字段
bit_byte at 2007-10-19 > top of Msdn China Tech,MS-SQL Server,疑难问题...
# 18
其他字段你没写出来,人家没法写啊,当然只能给个大概思路了

自己稍微改造一下吧
# 19
to:bit_byte() ( ) 信誉:100 Blog
declare @id int,@j int,@sql varchar(1000)--@id是定义的变量列,定义多个就行了.
你把列的属性都贴出来给你改一下就行了
insert ta select @id,....增加新增的字段

如果只插入id其它列默认null时定义方法
create proc test_p (@id int
as
begin
declare @j int,@sql varchar(1000)
if exists(select 1 from ta where id=@id)
begin
select @j=@id,@sql=''
while exists(select 1 from ta where id=@j)
begin
select @sql=@sql+','+rtrim(id) from ta where id=@j
select @j=@j+1
end
set @sql=stuff(@sql,1,1,'')
exec('update ta set id=id+1 where id in ('+@sql+')')
insert ta(id) select @id--在这里用()指定列
end
else
insert ta(id) select @id--在这里用()指定名
end
# 20
以上的create proc test_p (@id int--把'('去掉
如果是触发器
insert ta select @id
改为
insert ta(id) select @id --除id列外,其它列为null
# 21
update ta set id=ta.id+1
where id>=5(要插入的id)
and id<=(select min(a.id+1) min_id FROM ta a
left join ta b on a.id=b.id-1
where a.id>=5(要插入的id)

and b.id is null)

insert into ta(id,...)
select 5(要插入的id)
,...

select * from ta
# 22
create proc test_p (@id int
as
begin
update ta set id=ta.id+1
where id>=@id and id<=(select min(a.id+1) min_id FROM ta a
left join ta b on a.id=b.id-1
where a.id>=@id

and b.id is null)

insert into ta(id,...)
select @id,...
end
# 23
create proc test_p (@id int)
as
begin
update ta set id=ta.id+1
where id>=@id and id<=(select min(a.id+1) min_id FROM ta a
left join ta b on a.id=b.id-1
where a.id>=@id

and b.id is null)

insert into ta(id)
select @id
end

刚才少了一个')'
# 24
xiequanqin(XQQ) 大哥,这样修改了一下,每次插入一条记录,所以大于@pid的数都加上了1,我希望如果有断号,后面就停止加1,下面是我修改后的代码,仍然没有达到我期望的要求。再请指教。roy_88大哥的代码不大看懂~~惭愧~~
alter proc test_p
(
@pid int,
@standard char(20),
@name_zh nvarchar(20),
@name_en char(50),
@img_path char(50)
)
as
begin
update product set pid=product.pid+1
where pid>=@pid and pid<=(select min(a.pid+1) min_id FROM product a
left join product b on a.pid=b.pid-1
where a.pid>=@pid

and b.pid is null)

insert into product(pid,standard,name_zh,name_en,img_path)
select @pid,@standard,@name_zh,@name_en,@img_path
end
bit_byte at 2007-10-19 > top of Msdn China Tech,MS-SQL Server,疑难问题...
# 25
xiequanqin(XQQ) 大哥,这样修改了一下,每次插入一条记录,所以大于@pid的数都加上了1,我希望如果有断号,后面就停止加1,下面是我修改后的代码,仍然没有达到我期望的要求。再请指教。roy_88大哥的代码不大看懂~~惭愧~~
alter proc test_p
(
@pid int,
@standard char(20),
@name_zh nvarchar(20),
@name_en char(50),
@img_path char(50)
)
as
begin
update product set pid=product.pid+1
where pid>=@pid and pid<=(select min(a.pid+1) min_id FROM product a
left join product b on a.pid=b.pid-1
where a.pid>=@pid

and b.pid is null)

insert into product(pid,standard,name_zh,name_en,img_path)
select @pid,@standard,@name_zh,@name_en,@img_path
end
bit_byte at 2007-10-19 > top of Msdn China Tech,MS-SQL Server,疑难问题...
# 26
xiequanqin(XQQ) 大哥,这样修改了一下,每次插入一条记录,所以大于@pid的数都加上了1,我希望如果有断号,后面就停止加1,下面是我修改后的代码,仍然没有达到我期望的要求。再请指教。roy_88大哥的代码不大看懂~~惭愧~~
alter proc test_p
(
@pid int,
@standard char(20),
@name_zh nvarchar(20),
@name_en char(50),
@img_path char(50)
)
as
begin
update product set pid=product.pid+1
where pid>=@pid and pid<=(select min(a.pid+1) min_id FROM product a
left join product b on a.pid=b.pid-1
where a.pid>=@pid

and b.pid is null)

insert into product(pid,standard,name_zh,name_en,img_path)
select @pid,@standard,@name_zh,@name_en,@img_path
end
bit_byte at 2007-10-19 > top of Msdn China Tech,MS-SQL Server,疑难问题...
# 27
create table product(
pid int,
standard char(20),
name_zh nvarchar(20),
name_en char(50),
img_path char(50)
)
GO

alter proc test_p
(
@pid int,
@standard char(20),
@name_zh nvarchar(20),
@name_en char(50),
@img_path char(50)
)
as
begin
update product set pid=product.pid+1
where pid>=@pid and pid<=ISNULL((select min(a.pid+1) min_id FROM product a
left join product b on a.pid=b.pid-1
where a.pid>=@pid and b.pid is null
AND EXISTS(SELECT pid from product where pid=@pid)
),-1)

insert into product(pid,standard,name_zh,name_en,img_path)
select @pid,@standard,@name_zh,@name_en,@img_path
end
GO

exec test_p 15,'aaaa','aa1','bb1','test1'

select * from product

呵呵。。少考虑了在最前面插入的情况
# 28
问题已解决,马上结帖,各位朋友能留下MSN或QQ吗。
bit_byte at 2007-10-19 > top of Msdn China Tech,MS-SQL Server,疑难问题...
# 29
感谢各位朋友的热心帮助!
bit_byte at 2007-10-19 > top of Msdn China Tech,MS-SQL Server,疑难问题...
# 30
可以交个朋友
以后多多交流

这个 用户名+Hotmail邮箱~