急——用存储过程解决自增字段的问题

时间:2022-02-15 13:59:05
我希望能用存储过程解决自增字段的问题

我有十好几个表有自增的需要,而且它们之间还会有关联,所以我要建一个表(例如表Y),存放其他表的表名、最大ID号,在其他表(例如A表)执行insert语句之前先执行这个存储过程,让存储过程把Y表里相关记录的值+1(记录A表里id最大值的那条记录),然后锁上住这条记录,不允许其他用户对这条记录的并发操作,然后取出+1后的值(是个number的值)插入到A表中或做其他操作,事务执行完后commit提交,其他人 才可对Y表这条记录update

我写不好,但是急用,也没有时间看书了,肯请大家帮助,帮我把这个存储过程完成,并且告诉我怎么调用,我使用 jsp + javabean 

我想把这个存储过程应用到多个表,所以最理想的结果是传入表名、列名(id列的列名和具有唯一标识的一个列名),最后要返回一个最新插入的id值

如果不能应用到多个表,就请大家帮我写个对单个表操作的存储过程,传入列名,传出最新更新的id值,然后告诉我怎样调用

急用,谢谢大家!

12 个解决方案

#1


对了,我用的是oracle9i

#2


我朋友哪里有这个函数,我已经把帖子号给他了。

#3


下面是我自己写的:

table_maxid表结构:

----名称-----数据类型---大小---小数位---是否为空?----默认值
tablename----varchar2----30---------------------------------
maxid----------number----10--------0------------------------


建表后,先插入一条记录:
insert into table_maxid (tablename,maxid) values ('table1',0);

存储过程:testproc
 (table_name in varchar2, newmaxid out number)
as
begin
  update Table_MaxID set MaxID = MaxID + 1 where TableName=table_name;
  select maxid into newmaxid from Table_MaxID where TableName=table_name;
end;

调用:
execute testproc('table1');出错, 我就不会写了,呵呵,晕菜!!

感谢楼上,一定结贴!!!

#4


CREATE  PROCEDURE PROC_AUTOID @IDName char(10),@IDString char(20)  out  as  
begin
   Declare @length char(20),@tempid char(20),@tempkind Char(2),@templength int
               Declare @tempint int
               Declare @yy char(2),@mm char(2),@dd char(2),@tempdate char(6)
   Declare ID_cursor Cursor For Select lastid,idname,idkind,idlength From autoid Where idname=@IDName
               Open ID_cursor
               Fetch Next From ID_cursor into @length,@tempid,@tempkind,@templength
               set @length=rtrim(@length)
               If  @@FETCH_STATUS = 0
                    begin

                         if @tempkind='1'
                         begin
                               set @yy=convert(char(2),right(year(getdate()),2))
                               set @mm=convert(char(2),month(getdate()))
                               if (len(@mm)=1)
                                      set @mm='0'+@mm
                               set @dd=convert(char(2),day(getdate()))
                               if (len(@dd)=1)
                                      set @dd='0'+@mm
                               set @tempdate=@yy+@mm+@dd
                               
                               if  @tempdate=left(@length,6)
                                    begin
                                           set @tempint=convert(int, right(rtrim(@length),4))
                                           set @tempint= @tempint+1                               
                                           set @IDString=@tempdate+left('0000',4-len(@tempint))+convert(char,@tempint)
                                    end                             
                              else
                                   begin
                                         set @IDString=@tempdate+'0001'
                                   end
           end

                   if @tempkind='2'
                         begin
                               if  @length=null
                                    begin
                                         set @IDString='0001'
                                    end                             
                              else
                                   begin
                                        set @tempint=convert(int,@length)
                                        set @tempint= @tempint+1
                                        set @IDString=left('0000',4-len(@tempint))+convert(char,@tempint)
                                   end
           end
         
                          If  @tempkind='3'
                         begin      
                                  If  (@length=null) or  (isnumeric(@length)=0)
                                       begin
                                                set @IDString='000001'
                                       end
                                  else
                                       begin
                                               set @tempint=convert(int,@length)
                                               set @tempint= @tempint+1
                                               set @IDString=left('000000',6-len(@tempint))+convert(char,@tempint)
                                       end
                         end

           end
   close ID_cursor          
   deallocate ID_cursor   
   
   update autoid set lastid=@IDString where idname= @IDName        
    
    select lastid from autoid where idname= @IDName 

    --客户编号加前缀‘N’
   if @IDName='khbh'
     set  @IDString='N'+@IDString

end
GO
麻烦吧
还得建表autoid 
调用
public String executeProc(String IDName)
{
String returnstr,sqlstr,rsstr;
rs=null;
sqlstr = "{call PROC_AUTOID(?,?)}"; 
try
{
if (conn!=null)
       {
    conn.close();
       }
           conn = DriverManager.getConnection(sConnStr,UseName,PassWord);
   CallableStatement stmt = conn.prepareCall(sqlstr);
   stmt.setString(1,IDName); 
   stmt.registerOutParameter(2,Types.CHAR); 
   rs=stmt.executeQuery();
   rs.next();
   rsstr = rs.getString(1); 
   returnstr = stmt.getString(2);
   rs.close();
   stmt.close();
   conn.close();
}
catch (Exception erproc)
{
  return null;
}
return returnstr;
}

#5


楼上,第一行返回下述错误:

行号= 1 列号= 29 错误文本= PLS-00103: 出现符号 "CREATE"在需要下列之一时:  ( ; is with authid as    cluster compress order using compiled wrapped external    deterministic parallel_enable pipelined 

这是什么意思啊?

#6


select ..for update;

#7


楼上的写法是sql server的t-sql语法,不适用于oracle。
不明白楼主为什么不用sequence,那简单很多啊

#8


先执行+1操作

锁住记录:select col1 from tablename for update;

#9


to 弱水三千:不用序列是因为那一系列操作中一旦出错,就无法回滚,用存储过程就可以。如果你有好的方法,请告知,急啊

#10


不用序列,那只能你自己解决并发问题了,不是很容易的.

#11


如果我把存储过程写成这样:

存储过程名:testproc

内容:
 (table_name in varchar2, newmaxid out number)
as
begin
  update Table_MaxID set MaxID = MaxID + 1 where TableName=table_name;
  select maxid into newmaxid from Table_MaxID where TableName=table_name;
end;

比如里面有一条记录,
insert into table_maxid (tablename,maxid) values ('table1',0);
应怎么调用呢?
execute testproc('table1'...);
上面这行,有三个点的地方应怎么写呢?

请教!!

#12


up一下,再不解决就结贴了!

#1


对了,我用的是oracle9i

#2


我朋友哪里有这个函数,我已经把帖子号给他了。

#3


下面是我自己写的:

table_maxid表结构:

----名称-----数据类型---大小---小数位---是否为空?----默认值
tablename----varchar2----30---------------------------------
maxid----------number----10--------0------------------------


建表后,先插入一条记录:
insert into table_maxid (tablename,maxid) values ('table1',0);

存储过程:testproc
 (table_name in varchar2, newmaxid out number)
as
begin
  update Table_MaxID set MaxID = MaxID + 1 where TableName=table_name;
  select maxid into newmaxid from Table_MaxID where TableName=table_name;
end;

调用:
execute testproc('table1');出错, 我就不会写了,呵呵,晕菜!!

感谢楼上,一定结贴!!!

#4


CREATE  PROCEDURE PROC_AUTOID @IDName char(10),@IDString char(20)  out  as  
begin
   Declare @length char(20),@tempid char(20),@tempkind Char(2),@templength int
               Declare @tempint int
               Declare @yy char(2),@mm char(2),@dd char(2),@tempdate char(6)
   Declare ID_cursor Cursor For Select lastid,idname,idkind,idlength From autoid Where idname=@IDName
               Open ID_cursor
               Fetch Next From ID_cursor into @length,@tempid,@tempkind,@templength
               set @length=rtrim(@length)
               If  @@FETCH_STATUS = 0
                    begin

                         if @tempkind='1'
                         begin
                               set @yy=convert(char(2),right(year(getdate()),2))
                               set @mm=convert(char(2),month(getdate()))
                               if (len(@mm)=1)
                                      set @mm='0'+@mm
                               set @dd=convert(char(2),day(getdate()))
                               if (len(@dd)=1)
                                      set @dd='0'+@mm
                               set @tempdate=@yy+@mm+@dd
                               
                               if  @tempdate=left(@length,6)
                                    begin
                                           set @tempint=convert(int, right(rtrim(@length),4))
                                           set @tempint= @tempint+1                               
                                           set @IDString=@tempdate+left('0000',4-len(@tempint))+convert(char,@tempint)
                                    end                             
                              else
                                   begin
                                         set @IDString=@tempdate+'0001'
                                   end
           end

                   if @tempkind='2'
                         begin
                               if  @length=null
                                    begin
                                         set @IDString='0001'
                                    end                             
                              else
                                   begin
                                        set @tempint=convert(int,@length)
                                        set @tempint= @tempint+1
                                        set @IDString=left('0000',4-len(@tempint))+convert(char,@tempint)
                                   end
           end
         
                          If  @tempkind='3'
                         begin      
                                  If  (@length=null) or  (isnumeric(@length)=0)
                                       begin
                                                set @IDString='000001'
                                       end
                                  else
                                       begin
                                               set @tempint=convert(int,@length)
                                               set @tempint= @tempint+1
                                               set @IDString=left('000000',6-len(@tempint))+convert(char,@tempint)
                                       end
                         end

           end
   close ID_cursor          
   deallocate ID_cursor   
   
   update autoid set lastid=@IDString where idname= @IDName        
    
    select lastid from autoid where idname= @IDName 

    --客户编号加前缀‘N’
   if @IDName='khbh'
     set  @IDString='N'+@IDString

end
GO
麻烦吧
还得建表autoid 
调用
public String executeProc(String IDName)
{
String returnstr,sqlstr,rsstr;
rs=null;
sqlstr = "{call PROC_AUTOID(?,?)}"; 
try
{
if (conn!=null)
       {
    conn.close();
       }
           conn = DriverManager.getConnection(sConnStr,UseName,PassWord);
   CallableStatement stmt = conn.prepareCall(sqlstr);
   stmt.setString(1,IDName); 
   stmt.registerOutParameter(2,Types.CHAR); 
   rs=stmt.executeQuery();
   rs.next();
   rsstr = rs.getString(1); 
   returnstr = stmt.getString(2);
   rs.close();
   stmt.close();
   conn.close();
}
catch (Exception erproc)
{
  return null;
}
return returnstr;
}

#5


楼上,第一行返回下述错误:

行号= 1 列号= 29 错误文本= PLS-00103: 出现符号 "CREATE"在需要下列之一时:  ( ; is with authid as    cluster compress order using compiled wrapped external    deterministic parallel_enable pipelined 

这是什么意思啊?

#6


select ..for update;

#7


楼上的写法是sql server的t-sql语法,不适用于oracle。
不明白楼主为什么不用sequence,那简单很多啊

#8


先执行+1操作

锁住记录:select col1 from tablename for update;

#9


to 弱水三千:不用序列是因为那一系列操作中一旦出错,就无法回滚,用存储过程就可以。如果你有好的方法,请告知,急啊

#10


不用序列,那只能你自己解决并发问题了,不是很容易的.

#11


如果我把存储过程写成这样:

存储过程名:testproc

内容:
 (table_name in varchar2, newmaxid out number)
as
begin
  update Table_MaxID set MaxID = MaxID + 1 where TableName=table_name;
  select maxid into newmaxid from Table_MaxID where TableName=table_name;
end;

比如里面有一条记录,
insert into table_maxid (tablename,maxid) values ('table1',0);
应怎么调用呢?
execute testproc('table1'...);
上面这行,有三个点的地方应怎么写呢?

请教!!

#12


up一下,再不解决就结贴了!