id主键是String问题?谢谢了

lianlinyu 2011-09-16 07:54:15
table A 的id是字符串,而且生成的规则是abc201109160001 (abc是固定的,20110916获取时间,0001流水号)

所以啊~,当我插入数据的时候,需要自己写一个java方法,让用户在添加一个表单时候,每次按照规则插入数据。

下一个月的时候,流水帐号又从0001开始:abc201110010001

~------------------------
ZkSqNsrzgZb zgsqzb = new ZkSqNsrzgZb();

zgsqzb.setZgsqLsh("abc201109160001"); 我现在都是这样写死的 ~~~哭。。。


有那么大哥哥,大姐姐们帮个忙。谢谢了
...全文
769 38 打赏 收藏 转发到动态 举报
写回复
用AI写文章
38 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhang111jie 2011-11-01
  • 打赏
  • 举报
回复
每个月都会重0001开始
lianlinyu 2011-10-24
  • 打赏
  • 举报
回复
[Quote=引用 36 楼 zhang111jie 的回复:]
建议触发器少用:
我一般只用触发器做日志,或者备份,很少做业务处理


表结构:
-- Create table
create table AUTONO
(
targetnum CHAR(15) not null,
sex VARCHAR2(6),
name VARCHAR2(10)
)
tablespace USERS
pctfree 10
ini……
[/Quote]

如果下一个月,又会从001开始嘛???
zhang111jie 2011-09-24
  • 打赏
  • 举报
回复
建议触发器少用:
我一般只用触发器做日志,或者备份,很少做业务处理


表结构:
-- Create table
create table AUTONO
(
targetnum CHAR(15) not null,
sex VARCHAR2(6),
name VARCHAR2(10)
)
tablespace USERS
pctfree 10
initrans 1
maxtrans 255
storage
(
initial 64K
next 1M
minextents 1
maxextents unlimited
);
-- Create/Recreate primary, unique and foreign key constraints
alter table AUTONO
add constraint TARGETNUM_PK primary key (TARGETNUM)
using index
tablespace USERS
pctfree 10
initrans 2
maxtrans 255
storage
(
initial 64K
next 1M
minextents 1
maxextents unlimited
);
create or replace trigger AutoNum
before insert on autono
for each row
Declare
sTempNo Varchar2(20) := '';
Begin
Select nvl(substr(Trim(Max(t.targetnum)), -4, 4), 0) + 1
Into sTempNo
From autono t
Where t.targetnum Like 'abc%'
And substr(Trim(t.targetnum), -12, 8) =
to_char(Sysdate, 'yyyymmdd');
sTempNo := substr('0000' || sTempNo, -4, 4);
sTempNo := 'abc' || to_char(Sysdate, 'yyyymmdd') || sTempNo;
:new.targetnum := sTempNo;
End AutoNum;



测试语句:
insert into autono(sex,name) values('男','张三');
insert into autono(sex,name) values('女','李四');
insert into autono(sex,name) values('未确定','王五');

测试结果:
abc201109240001 男 张三
abc201109240002 女 李四
abc201109240003 未确定 王五
abc201109240004 男 张三
abc201109240005 女 李四
abc201109240006 未确定 王五
lianlinyu 2011-09-23
  • 打赏
  • 举报
回复
用触发器 怎么写?
zhang111jie 2011-09-20
  • 打赏
  • 举报
回复
写个函数:
function GetID return varchar2 is
sTempNo varchar2(20) := '';
begin
select nvl(substr(trim(max(t.targetnum)), -4, 4),0)+1 into sTempNo
from testno t
where t.targetnum like 'abc%'
and substr(trim(t.targetnum),-12,8) = to_char(sysdate, 'yyyymmdd');
sTempNo:=substr('0000'||sTempNo,-4,4);
sTempNo:='abc'||to_char(sysdate,'yyyymmdd')||sTempNo;
return sTempNo;
end GetID;


然后调用一下
如:insert into testno values (GetID);
cocolmalu 2011-09-20
  • 打赏
  • 举报
回复
触发器建议少用。刚才那个触发器可以改成一个函数,返回一个id。楼主这种生成ID方法是有问题的,并发要是处理不好,就希特勒!业务码+yyyymmdd+序列。
Cactus_hxk 2011-09-19
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 oxcow 的回复:]
使用oracle,可以用下触发器么。

SQL code


表结构:
CREATE TABLE "table_name"
( "ID" NUMBER(11,0),
"ENTITY_ID" NUMBER(10,0),
"ENTITY_CLASS" VARCHAR2(200 BYTE),
"MESSAGE" VARCHAR2(300……
[/Quote]
这个好,顶起!
scrack 2011-09-19
  • 打赏
  • 举报
回复
用触发器
hc_baby 2011-09-19
  • 打赏
  • 举报
回复

String hql="select count(*) from CstCustomer";

Integer index=(Integer)baseDAO.uniqueResult(hql, null);
String noStr="KH";//前缀
Date date=new Date();
String time=date.toLocaleString();

int index1=time.indexOf("-");
String year=time.substring(0, index1);

int index2=time.lastIndexOf("-");
String month=time.substring(index1+1,index2);
if(month.length()<2){
month="0"+month;
}

int index3=time.indexOf(" ");
String day=time.substring(index2+1,index3);
if(day.length()<2){
day="0"+day;
}
String count="";
if(index<10){
count="0000"+(index+1);
}else if(index<100){
count="000"+(index+1);
}else if(index<1000){
count="00"+(index+1);
}else if(index<10000){
count="0"+(index+1);
}else{
count=""+(index+1);
}
time+=year+month+day;
noStr+="_"+time+"_"+count;

我是用hibernate查的数据。。业务逻辑一样的。。
oxcow 2011-09-17
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 oxcow 的回复:]

使用oracle,可以用下触发器么。
SQL code

表结构:
CREATE TABLE "table_name"
( "ID" NUMBER(11,0),
"ENTITY_ID" NUMBER(10,0),
"ENTITY_CLASS" VARCHAR2(200 BYTE),
"MESSAGE" VARCHAR2(300 BYTE) NO……
[/Quote]


呵呵 ,忘记跨日重新计算流水号了,这个楼主自己试着解决,应该没什么困难!
冰岛男孩 2011-09-17
  • 打赏
  • 举报
回复
楼主简单点 UUID试看
阿诺 2011-09-17
  • 打赏
  • 举报
回复
楼主简单点 UUID试看
zmk1210 2011-09-17
  • 打赏
  • 举报
回复
/**
* 设置关键字段的编号
* @param biao 表的名称
* @param kaitou 开头的大写字母
* @param key 关键字段的名称
* @return
*/
public String setKeyWord(String biao,String kaitou,String key){
String sql="select count(*) as acount from " +biao;
String str = new SimpleDateFormat("yyyyMMdd").format(new Date());
int count=Integer.parseInt(this.getdb().executePreparedStatement(sql).get(0).get("acount").toString());
//System.out.println(count);
if(count==0){
String keyword=kaitou+"-"+str+"-00001";
return keyword;
}else{
sql="select * from "+biao+ " limit "+(count-1)+",1";
String keyword=this.getdb().executePreparedStatement(sql).get(0).get(key).toString();

if (keyword==null){

keyword=kaitou+"-"+str+"-00001";
}else{
String dateString=keyword.substring((keyword.length()-14),(keyword.length()-6));
if(!dateString.equals(str)){
keyword=kaitou+"-"+str+"-00001";
}else{
int endkeyword=Integer.parseInt(keyword.substring(keyword.length()-5))+1;
String strendkeyword="00000"+Integer.toString(endkeyword);
strendkeyword=strendkeyword.substring(strendkeyword.length()-5);
keyword=kaitou+"-"+str+"-"+strendkeyword;
}
}
return keyword;
}

}


这个应该可以,只是要改掉查询数据库获取keyString和count的值
niuniu20008 2011-09-17
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 bao110908 的回复:]
用业务字段作为主键,迟早会吃到苦头!
[/Quote]
恩,有理,比如学生表使用不要使用学生学号作为id
chenjunan888 2011-09-17
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 oxcow 的回复:]

使用oracle,可以用下触发器么。
SQL code

表结构:
CREATE TABLE "table_name"
( "ID" NUMBER(11,0),
"ENTITY_ID" NUMBER(10,0),
"ENTITY_CLASS" VARCHAR2(200 BYTE),
"MESSAGE" VARCHAR2(300 BYTE) NO……
[/Quote]

做如下修改更好,否则如果误修改了日期为昨天,而昨天已有数据,而编号又重1开始,就出错了。
若要想在每个月第一天重新开始编号,只要在if的地方做修改就行了
BEGIN
select max(message) into old_id from table_name t where t.message like '%' || to_char(sysdate, 'yyyymmdd') || '%'; -- --获取今天内最大的id,否则将日期修改了就可能出错
select to_char(sysdate, 'yyyymmdd') INTO cr_date from dual; -- 获取当前时间
IF (to_number(substr(old_id,10,2)) = to_number(substr(cr_date,7,2))) --如何是同一天,则编号加1
THEN
sNo:= lpad(to_char(to_number(substr(old_id,12,4))+1),4,'0'); -- 获取新的流水号
new_id:='abc' || cr_date || sNo; -- 生成新的ID
ELSE
new_id:='abc' || cr_date || '0001';
END IF;
:NEW.message:= new_id; -- 给插入时的主键赋值
END;
BearKin 2011-09-17
  • 打赏
  • 举报
回复
有些事情写到程序里不太方便 假设你做了集群 你生成ID的源必须得保证是一个 而服务器那么多 要保证起来就困难了点(生成个主键也没必要做什么WS吧)

这个还是写到数据库里吧 序列配合函数 我想不会太难的 (我们公司以前就是这样弄的)
oxcow 2011-09-16
  • 打赏
  • 举报
回复
使用oracle,可以用下触发器么。

表结构:
CREATE TABLE "table_name"
( "ID" NUMBER(11,0),
"ENTITY_ID" NUMBER(10,0),
"ENTITY_CLASS" VARCHAR2(200 BYTE),
"MESSAGE" VARCHAR2(300 BYTE) NOT NULL ENABLE,
"CREATED" DATE,
PRIMARY KEY ("MESSAGE"))
触发器:
CREATE OR REPLACE
TRIGGER AUTO_AUDIT_LOGS_PK -- 触发器名称
BEFORE INSERT ON YT_AUDIT_LOGS -- 设置在更新操作前
FOR EACH ROW -- 使用DML触发
DECLARE
old_id VARCHAR2(15); -- 数据库中当前主键
cr_date VARCHAR2(10); -- 当前日期yyyymmdd
new_id VARCHAR2(15); -- 根据规则生成的主键id
sNo VARCHAR2(4); -- 流水号
BEGIN
select max(message) into old_id from table_name; -- 获取当前数据库中最大的id
select to_char(sysdate, 'yyyymmdd') INTO cr_date from dual; -- 获取当前时间
IF length(old_id) > 14 THEN
sNo:= lpad(to_char(to_number(substr(old_id,12,4))+1),4,'0'); -- 获取新的流水号
new_id:='abc' || cr_date || sNo; -- 生成新的ID
ELSE
new_id:='abc' || cr_date || '0001';
END IF;
:NEW.message:= new_id; -- 给插入时的主键赋值
END;

插入SQL:
insert into yt_audit_logs(id, entity_class, entity_id, created)
values(1,'ac',2,sysdate); -- 插入时不用声明message主键,而是由触发器自动生成




这里只是提供一种可以实现你的业务逻辑方式的方法,至于是不是最优,那得看实际情况。仅供参考!
lezai001 2011-09-16
  • 打赏
  • 举报
回复
学习!
hou848366 2011-09-16
  • 打赏
  • 举报
回复
Date date = new Date();
SimpleDateFormat sp1 = new SimpleDateFormat("yyyyMMdd");
SimpleDateFormat sp2 = new SimpleDateFormat("yyyyMM");
String time = sp2.format(date);
//修改下在17楼的这部分,睡觉去了
String t1=oldId.substring(3,9);
if (time.equals(t1)) {

hou318750282 2011-09-16
  • 打赏
  • 举报
回复
09年及其以前的
加载更多回复(18)

81,092

社区成员

发帖
与我相关
我的任务
社区描述
Java Web 开发
社区管理员
  • Web 开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧