当前位置: 代码迷 >> Oracle开发 >> 遇到了两个有关问题,路过的帮下忙,多谢
  详细解决方案

遇到了两个有关问题,路过的帮下忙,多谢

热度:94   发布时间:2016-04-24 08:03:09.0
遇到了两个问题,路过的帮下忙,谢谢
项目是用oralce 10g + tomcat +jsp的
  其中,有订单流水号,如年月日+7位流水号。以前做的东西里边因为订单少,就每次都去数据库取一次最后的订单号,再来生成新的订单好。但是现在这个项目里,每天的订单可能10W左右,而且下单时间比较集中。那该去怎么处理这个订单流水号?
  还有就是,要对用户的所有操作,主要是查看/购买商品,点击/购买广告产品的记录。做这种操作轨迹记录,该怎么设计表,以及如何做查询优化,现在已有20W用户操作。。。

  麻烦路过的大哥大姐帮帮忙,指点下。。。小弟先谢谢了

------解决方案--------------------
增加一个每日流水号的表,字段两个,一个是日期,一个是流水号(数值),先插入两年的记录,流水号都初始化为1。
每次需要新的流水号时,就用当前的日期去获取当天的流水号再补充0到7位,用了一个就把该表的流水号+1,相当于建立了一个动态的sequence。

------解决方案--------------------
用SEQUENCE吧 把SEQUENCE常驻在cache中 就不会丢失
第二个 应该是需要前台操作才能统计的吧 估计会要设计表格插入数据统计
20w每天产生100-200w数据很正常啊那就
你最终目的应该是要统计每个商品的 点击量 销售量吧
那就每天统计好 点击量 销售量 然后清掉 数据记录表
个人意见 一起学习
------解决方案--------------------
SQL code
---------------- 若订单流水号是字符串型的话:(Oracle 10g)  -----------------CREATE SEQUENCE order_id_seq INCREMENT BY 1 START WITH 1 MAXVALUE 9999999 CYCLE CACHE 10;SET SERVEROUTPUT ONDECLARE  order_id VARCHAR(17); -- 订单流水号BEGIN  SELECT to_char(SYSDATE,'YYYYMMDD')||LPAD( to_char(order_id_seq.nextval),7,'0') INTO order_id FROM dual;  DBMS_OUTPUT.PUT_LINE('当前流水号是:'||order_id);END;/---------------- 若订单流水号是数值型的话:(Oracle 10g)  -----------------CREATE SEQUENCE order_id_seq INCREMENT BY 1 START WITH 1 MAXVALUE 9999999 CYCLE CACHE 10;SET SERVEROUTPUT ONDECLARE  order_id NUMBER(18,0); -- 订单流水号BEGIN  SELECT to_number(to_char(SYSDATE,'YYYYMMDD')||LPAD( to_char(order_id_seq.nextval),7,'0')) INTO order_id FROM dual;  DBMS_OUTPUT.PUT_LINE('当前流水号是:'||order_id);END;/---------------- 若订单流水号是字符串型的话:(Oracle 11g)  -----------------CREATE SEQUENCE order_id_seq INCREMENT BY 1 START WITH 1 MAXVALUE 9999999 CYCLE CACHE 10;SET SERVEROUTPUT ONDECLARE  order_id VARCHAR(17); -- 订单流水号BEGIN  order_id := to_char(SYSDATE,'YYYYMMDD')||LPAD( to_char(order_id_seq.nextval),7,'0');  DBMS_OUTPUT.PUT_LINE('当前流水号是:'||order_id);END;/---------------- 若订单流水号是数值型的话:(Oracle 11g)  -----------------CREATE SEQUENCE order_id_seq INCREMENT BY 1 START WITH 1 MAXVALUE 9999999 CYCLE CACHE 10;SET SERVEROUTPUT ONDECLARE  order_id NUMBER(18,0); -- 订单流水号BEGIN  order_id := to_number(to_char(SYSDATE,'YYYYMMDD')||LPAD( to_char(order_id_seq.nextval),7,'0'));  DBMS_OUTPUT.PUT_LINE('当前流水号是:'||order_id);END;/
------解决方案--------------------
使用for update强制串行,每天从1开始,生成唯一流水号
每天10W,性能没问题
SQL code
--创建流水号表create table T_SERIALNO(  CURDAT     VARCHAR2(10) not null,  SERIALNUM  NUMBER(8) not null);--创建函数CREATE OR REPLACE FUNCTION GetSerialNo RETURN VARCHAR2 IS  v_DateStr   VARCHAR2(10); --系统日期对应的字符串  v_SerialNum NUMBER(7); --流水序号BEGIN  --取系统日期生成需要的字符串  v_DateStr := TO_CHAR(SYSDATE, ('YYYYMMDD'));  --生成产生流水号的序号  BEGIN    SELECT Decode(CurDat, v_DateStr, (SerialNum + 1), 1)      INTO v_SerialNum      FROM t_SerialNo       FOR UPDATE;  EXCEPTION    WHEN NO_DATA_FOUND THEN      v_SerialNum := 1;      INSERT INTO t_SerialNo (CurDat, SerialNum) VALUES (v_DateStr, v_SerialNum);  END;  --修改流水号参数  UPDATE t_SerialNo SET CurDat = v_DateStr, SerialNum = v_SerialNum;  COMMIT;  --得到需要的流水号  RETURN v_DateStr || Lpad(v_SerialNum, 7, '0');EXCEPTION  WHEN OTHERS THEN    ROLLBACK;    RETURN NULL;END;/
------解决方案--------------------
SQL code
Set Serveroutput oncreate or replace procedure CreSeq(AsSql in varchar2) is  iCurID  Integer;    -- 游标ID   iResult Integer;begin  iCurID:= Dbms_Sql.Open_Cursor;  Dbms_Sql.Parse(iCurID, AsSql, Dbms_Sql.V7);   iResult:= Dbms_Sql.Execute(iCurID);  Dbms_Sql.Close_Cursor(iCurID);end;/create or replace function GetSqlValue(AsSql in varchar2) return Integer is  iCurID  Integer;    -- 游标ID   iResult Integer;  iReturn Integer;begin  iCurID:= Dbms_Sql.Open_Cursor;  Dbms_Sql.Parse(iCurID, AsSql, Dbms_Sql.V7);   Dbms_Sql.Define_Column(iCurID, 1, iReturn);   iResult:= Dbms_Sql.Execute(iCurID);  if Dbms_Sql.Fetch_Rows(iCurID) > 0 then    Dbms_Sql.Column_Value(iCurID, 1, iReturn);  else    iReturn:= -1;    end if;  --Dbms_Sql.Close_Cursor(iCurID);  Return iReturn;exception  when Others then    --Dbms_Output.Put_Line(SqlErrm);    Return -2;end;/create or replace procedure GetMaxID(AdRq in Date, AnPlaces in Integer, AsOutOrderID out varchar2) is  sSql       Varchar2(4000);  sSeqName   Varchar2(30); -- 订单使用的Sequence名字  nPlaces    Integer;  nResult    Integer;  nOrderID   Integer;begin  AsOutOrderID:= '';  -- 检查  if AdRq is Null then    Return;  end if;  -- 检查流水号位数  if (Nvl(AnPlaces, 0) = 0) or (Nvl(AnPlaces, 0) < 0) then    nPlaces:= 7;  else    nPlaces:= AnPlaces;   end if;    sSeqName:= 'SEQ_ORDER' || To_Char(AdRq, 'YYYYMMDD');  select Count(1)    into nResult    from dual   where Exists (select 1                    from all_Sequences                  where Sequence_Name = Upper(sSeqName));    if nResult = 0 then    -- 创建Sequence    sSql:= 'create Sequence ' || sSeqName || ' INCREMENT BY 1 START WITH 1 MAXVALUE ' || Rpad(' ', nPlaces + 1, '9') || ' CYCLE CACHE 10 ';    --Dbms_output.put_line(sSql);        CreSeq(sSql);  end if;    -- 执行  sSql:= 'select ' || sSeqName || '.NextVal' || ' from Dual';  --Dbms_output.put_line(sSql);  nOrderID:= GetSqlValue(sSql);    if nOrderID <= 0 then    AsOutOrderID:= '';  else    AsOutOrderID:= To_Char(AdRq, 'YYYYMMDD') || Lpad(To_Char(nOrderID), nPlaces, '0');  end if;  --Dbms_output.Put_Line(Nvl(AsOutOrderID, 'Error'));exception  when others then    Return;    --Dbms_output.put_line(SqlErrm);end;/declare  sOrderID varchar2(200);begin  GetMaxID(sysdate, 8, sOrderID);  dbms_output.put_line(sOrderID);end;/2010042000000015PL/SQL procedure successfully completeddeclare  sOrderID varchar2(200);begin  GetMaxID(sysdate, 8, sOrderID);  dbms_output.put_line(sOrderID);end;/2010042000000016PL/SQL procedure successfully completed
  相关解决方案