题目:
现在数据库由于需要要自己定义唯一编号,唯一编号由3个数字组成。这三个数字我存储为nvarchar.
由于唯一编号在使用中不可能超过999条记录,所以3个足够用。但是碰到一个问题.第一次使用时添加记录可以001,002,003...这样顺序添加.
当对这些记录进行删除之后再次添加.要核对输入的记录是否重复。这样非常被动。
每次添加记录都要验证该编号是否存在。设计这样的数据库,实在是没辙.
现在有没有办法能够自己得出一个在999内的未使用的编号呢。
非常感谢。用存储过程亦可。我有想过遍历,但是效率不高。希望有更简洁的方式。再谢.http://community.csdn.net/Expert/topic/5152/5152276.xml?temp=.9417536
现在数据库由于需要要自己定义唯一编号,唯一编号由3个数字组成。这三个数字我存储为nvarchar.
由于唯一编号在使用中不可能超过999条记录,所以3个足够用。但是碰到一个问题.第一次使用时添加记录可以001,002,003...这样顺序添加.
当对这些记录进行删除之后再次添加.要核对输入的记录是否重复。这样非常被动。
每次添加记录都要验证该编号是否存在。设计这样的数据库,实在是没辙.
现在有没有办法能够自己得出一个在999内的未使用的编号呢。
非常感谢。用存储过程亦可。我有想过遍历,但是效率不高。希望有更简洁的方式。再谢.http://community.csdn.net/Expert/topic/5152/5152276.xml?temp=.9417536
1 张山
3 历史
4 王无
6 李强
桥三
大兵我想对没有编号的进行编号的自动处理,但是已经有编号的不要进行修改。
如果发现有断号的就将号码分配给没有编号的。
结果如下:
编号 姓名
1 张山
3 历史
4 王无
6 李强
2 桥三
5 大兵
遍历记录,如果id为空,则找出最小未使用id,然后update找最小未使用id如下:
select (case when exists (select 1 from test where id=1)
then min(id+1) else 1 end)
from test
where id not in(select id-1 from test)
GO
update autokey
set no = right('00'+cast(id as varchar),3)select * from 表 where 编号 not in (select no from autokey)
select no from autokey where no not in (select distinct 编号 from 表)
if object_id('pubs..t') is not null
drop table t
gocreate table t(id char(3))select (case when exists (select 1 from t where cast(id as int)=1)
then right('00' + rtrim(cast(min(id + 1) as char(3))) , 3) else '001' end)
as 最小数据
from t
where id not in(select id - 1 from t)drop table t--结果
最小数据
-----
001(所影响的行数为 1 行)
--2、有数据且连号。
if object_id('pubs..t') is not null
drop table t
gocreate table t(id char(3))insert into t(id) values('001')
insert into t(id) values('002')
insert into t(id) values('003')select (case when exists (select 1 from t where cast(id as int)=1)
then right('00' + rtrim(cast(min(id + 1) as char(3))) , 3) else '001' end)
as 最小数据
from t
where id not in(select id - 1 from t)drop table t--结果
最小数据
-----
004(所影响的行数为 1 行)
--3、有数据但断号
if object_id('pubs..t') is not null
drop table t
gocreate table t(id char(3))insert into t(id) values('001')
insert into t(id) values('002')
insert into t(id) values('004')select (case when exists (select 1 from t where cast(id as int)=1)
then right('00' + rtrim(cast(min(id + 1) as char(3))) , 3) else '001' end)
as 最小数据
from t
where id not in(select id - 1 from t)drop table t--结果
最小数据
-----
003(所影响的行数为 1 行)
怎样理解呢?这句
create function roy_fun(@id char(3)=null)
returns char(3)
as
begin
declare @new char(3)
(select @new=replicate('0',(3-len(max(cast(isnull(id,0) as int))+1)))
+cast((max(cast(id as int))+1)as varchar)
from roy)
return(@new)
end
--定义触发器
create trigger roy_tr on roy
for insert
as
update roy
set id=isnull(dbo.roy_fun(null),'001')
where id is null
--测试
insert into roy(name) values('a')select * from roy
结果:
id name
---- -----
001 a
002 a(所影响的行数为 2 行)
select replicate('0',(3-len(max(cast(isnull(id,0) as int))+1)))
+cast((max(cast(id as int))+1)as varchar)
from roy
create proc test
as
update roy
id=replicate('0',(3-len(max(cast(isnull(id,0) as int))+1)))
+cast((max(cast(id as int))+1)as varchar)
from roy where id is null
--存储查询下一个值
create proc test
as
select replicate('0',(3-len(max(cast(isnull(id,0) as int))+1)))
+cast((max(cast(id as int))+1)as varchar)
from roy
create table test_ta(id char(3),name varchar(10))
--定义一个函数
create function test_fun(@id char(3)=null)
returns char(3)
as
begin
declare @new char(3)
(select @new=isnull(replicate('0',(3-len(max(cast(isnull(id,0) as int))+1)))
+cast((max(cast(id as int))+1)as varchar),'001')
from test_ta)
return(@new)
end
insert test_ta select dbo.test_fun(null),2--测试新增记录
select *from test_ta--查看结果
--定义触发器(用于批量新增记录)
create trigger test_ta_tr on test_ta
for insert
as
declare @i int
set @i=0
set nocount on
update test_ta
set id=replicate('0',3-len((select isnull(max(cast(id as int)),0) from test_ta)+@i))+
cast((select isnull(max(cast(id as int)),0) from test_ta)+@i as varchar)
,@i=@i+1
where id is null
set nocount off
--测试一次增加999记录
--truncate table test_ta --清空表
declare @i int,@j int
select @i=1,@j=999
while @i!>@j
begin
set nocount on
insert test_ta(name) VALUES(@i)
set nocount off
select @i=@i+1
end
--触发器是更新id为空值的值
--由于id有空值,isnull会有这样提示:警告: 聚合或其它 SET 操作消除了空值。
select * from test_ta--查看结果--drop function test_fun--删函数
--drop table test_ta--删测试表
1>加表方式(FreeKeyTable表),根据主表的所有可用的主键生成到FreeKeyTable表中.
主表添加一个有效的就删除一个FreeKeyTable中的键(一定要有事务[它们是同一个事务])
2>通过编程实现(一定要保证一个实现[单例])
原理大同小异,所有的键操作都通过一个类来完成.
初始化工作(生成有效键)
获取有效键
回收有效键根据以上功能可以这样定义接口
public interface IFreeKeyManager
{
void Init();
bool IsInit{get;}
int getFreeKey();
void Recycle(int key);
}public class FreeKeyManager:IFreeKeyManager
{
protected IList keys=new ArrayList();
protected bool isInit=false; public bool IsInit{get{return isInit;}}
public void Init()
{
//自己实现主键中没有用过的键添加到keys中
isInit=true;
}
public int getFreeKey()
{
if(keys==null||keys.Count<=0)
throw new Exception("键集合没有初始化或已经没有可用的键");
int key=(int)keys[0];
keys.Remove(0);
return key;
}
//添加不成功或删除某键进行回收
public void Recycle(int key)
{
keys.Add(key);
}
}当然这是简单的例子,还可以扩展存储方式.
如:
public interface IFreeKeyManager
{
void Init();
bool IsInit{get;}
int getFreeKey();
Recycle(int key);
SaveKeys();
}
将键值直接保存(文件,数据库或各种形式接下来写一个单例
public class FreeKeyManagerFactory
{
static IFreeKeyManager keys=new FreeKeyManager();
private FreeKeyManagerFactory(); public static IFreeKeyManager getInstance()
{
return keys;
}
}这样你可以轻松进行了使用了
在系统加载的时候
IFreeKeyManager keyManager FreeKeyManagerFactory.getInstance();
if(!keyManager.IsInit)
keyManager.Init();
在添加时
int key=FreeKeyManagerFactory.getInstance().getFreeKey();
删除时
FreeKeyManagerFactory.getInstance().Recycle(key);//删除的key
select top 1 code from A where not exists(select 1 from 表 B where A.code=b.code) order by A.Code