现有一A用户新增了一笔采购单号(主键):20130528002没有保存,B用户也新增了一笔采购单号:20130528002,如果B用户先保存,那么A用户再保存就会产生主键重复,请教大家有没有好的处理方法,谢谢!!(不用自动增长列和GUID做主键)SQLC#

解决方案 »

  1.   

    其实在每次客户创建采购时,就应该生成采购单号(应该有张表单独存放当前最大采购单号,取当前数据库最大+1,获得单号后马上更新单号最大值,类似于oracle的序列)。这样,保证客户每次取得的单号是唯一的。
      

  2.   


    /// <summary>
            /// 获取表数据的主键,格式为前缀+时间+流水号 如CK20120102001
            /// </summary>
            /// <param name="Ext">前缀,可以为空</param>
            /// <param name="TableName">表名</param>
            /// <param name="ColName">列名</param>
            /// <param name="Format">时间格式化字符串(yyyyMMdd)</param>
            /// <param name="len">流水号长度</param>
            /// <returns>主键</returns>
            public static string GetTablePK(string Ext, string TableName, string ColName, string Format, int len)
            {
                string time = Ext + DateTime.Now.ToString(Format);
                string sql = "select max(right(" + ColName + "," + len.ToString() + ")+1) from " + TableName + " where " + ColName + " like '" + time + "%'";
                object o = dosoft.DAL.DbHelperSQL.GetSingle(sql);
                if (o == null || o.ToString() == "")
                {
                    return time + "1".PadLeft(len, '0');
                }
                else
                {
                    return time + o.ToString().PadLeft(len, '0');
                }
            }
    Userinfo u=new Userinfo();
    u.id=GetTablePK("User","Userinfo","id","yyyyMMdd",3);
    //结果就是
    User20121212001
      

  3.   

    Oracle 提供了一种叫 序列,
    可以控制的初始值 和 步长 做到不重复
      

  4.   

    笨哦,你先算出来的啊,单号当然是插入时自动生成的。建议写一个SQL函数,将主键字段默认值设置为该函数,这样这个问题以后都可以不用管了。具体思路:建立一个表记录流水号,一条记录即可,触发器设置每天0点将计数清0每查询一次自+1;
    加一SQL函数
    create function  dbo.PrintCounter ()
    RETURNS varchar(12)
    begin
    declare @r varchar(12)
    Select @r=CONVERT(varchar(12), GETDATE(), 112)+right('000'+cast(max(流水号)+1 as varchar),3) from 流水表
    return @r
    end
    这样插入时调用PrintCounter()就得到不会重复的单据号了,用法和Sum(XX),newid(),一样爽
      

  5.   


    请问什么问题?我可能没有注意到,请说明,让我改进。
    你执行下 select PrintCounter() 看看?如果你说流水不连号,这个是的,你要流水连号干什么?
    流水本来就是流水的往下走,不可逆的,
    举例说明:我开一张单001,报废了,下一张单开还是001?
    这个时候别人拿着报废的001单据去仓库,你给他发货不?
    当然,这个时候是002就不一样了,001在电脑上已经查不到了。
    当然这个是做项目的一些经验,你的项目可能特殊,那你另外想想吧,哈
      

  6.   


    请问什么问题?我可能没有注意到,请说明,让我改进。
    你执行下 select PrintCounter() 看看?如果你说流水不连号,这个是的,你要流水连号干什么?
    流水本来就是流水的往下走,不可逆的,
    举例说明:我开一张单001,报废了,下一张单开还是001?
    这个时候别人拿着报废的001单据去仓库,你给他发货不?
    当然,这个时候是002就不一样了,001在电脑上已经查不到了。
    当然这个是做项目的一些经验,你的项目可能特殊,那你另外想想吧,哈
    你没有设置前导0的位数,假如序号是10呢,流水号不也是'00010'?正确的应该是'010'
      

  7.   

    在SQL中建立一个表维护这些单据号了,让其自动生成.你可以做一个配置单据号的界面处理.
      

  8.   


    你试过没有?right就是补位操作了,请试过后再说,谢谢。