主键自生成难题! 请高手救急!高分相送,我有数千可用分可用!!!

主键难题:

有一order表,字段如下:
order_id Char (12) 订购编号[定义为主键]
cust_id Char (05) 客户编号
order_date Datetime 订购时间
...

假如上月(2002.12)客户(编号:WX005)有5个订单,本月已有
2个订单,则数据如下:
[订购编号] [客户号] [订购日期]
WX0050212001 WX005 2002.12.01
WX0050212001 WX005 2002.12.11
WX0050212003 WX005 2002.12.15
WX0050212004 WX005 2002.12.21
WX0050212005 WX005 2002.12.28
WX0050301001 WX005 2003.01.03
WX0050301002 WX005 2003.01.05

可以看出,order_id由下列规则自动生成:
订单编号(12位)=客户编号(5位)+订购日期(4位)+自动递增流水号(3位)

问题: 在SQL Server中应怎样处理才能使[订购编号]按此规则自动生成,
难点在于它的流水号须随不同客户依次递增,且每月各客户的初始订购流
水号须初始为001,然后再递增.

请高手救急!高分相送,我有7480可用分可用!!!
---------------------------------------------------------------

sqlserver 2000吗? 可以写个函数.

把你的"客户号" 与 "日期" 传过去.

返回ID号.

---------------------------------------------------------------

你可以建一个表有两列,用户ID 流水号

当遇到不同用户你就在这个表找按相应的‘用户ID’,提取相应的‘流水号’
每个月末把这个表的‘流水号’列该成001就行了(update 表 set 流水号=001)
---------------------------------------------------------------

更正:是000
你提取时:

select 流水号
from 表
where 用户ID = 你的用户ID
当你保存数据时:
update 表
set 流水号 = 流水号+1; OK!

---------------------------------------------------------------

上百个都没关系呀,这样是指,每个用户用一个指定流水号行,你好好
看一下我上面的(你有多手客户呀)
---------------------------------------------------------------

declare @count int
declare @orderid varchar(12)
select @count=count(*) from table where 客户号='这个订单的客户号' and datediff(dd,定购日期,这个订单的日期)=0
select @orderid='这个订单的客户号'+substring(convert(varchar(8),这个订单的日期,12),3,6)+right(('00'+str(@count+1)),3)

记得要用transaction保证插入新的orderid时不会有别的插入,导致数据错误
---------------------------------------------------------------

right(('00'+str(@count+1)),3)
小错误
right(('00'+ltrim(str(@count+1))),3)

---------------------------------------------------------------

我们是放在前台做的
首先检索表中满足客户号=输入客户号,日期=输入日期的 后三位编号最大的记录,然后把编号+1 插入数据库
用语句
select max(substring(dgbh,10,3) from table where substring(dgbh,1,5)=WX0005 substring(dgbh,6,4)=0212

dgbh--定购编号 0212-是已经对日期做出了格式转换

---------------------------------------------------------------

那中方法是不会出现断号的你用if控制一下如果存取失败时流水号不自动加1

你可以这样来生成我刚建的哪个表
declare @id char(10)
declare cur_kk cursor for
select 用户ID
from 你的用户表中
open cur_kk
fetch cur_kk into @id
while @@fetch_status = 0
begin
insert into 表
(用户id,流水号)
values(@id,000)
end
close cur_kk

就OK了
---------------------------------------------------------------

我的东西已经很详细了阿,出来的@orderid就是你要的新的合同号,你仔细看一下,很容易明白的

你把这个transaction写成一个存储过程,然后执行sp就可以了,
我把sp给你写写把:
CREATE PROCEDURE sp_AddOrder
@AccountId varchar(5),
@SignDate datetime,
--你的其他参数,比如
@OrderName varchar(200),
...
AS

Begin Tran MyTran

declare @count int
declare @orderid varchar(12)
select @count=count(*) from table where 客户号=@AccountId and datediff(dd,定购日期,@SignDate)=0
select @orderid='这个订单的客户号'+substring(convert(varchar(8),@SignDate,12),3,6)+right(('00'+ltrim(str(@count+1))),3)

if @@ERROR<>0 ROLLBACK else Commit Tran Tran1stLevel
go

执行存储过程就像执行一个sql的函数,但是记得带上该带的参数,类型要准确
---------------------------------------------------------------

declare @count int
declare @orderid varchar(12)
select @count=count(*) from table where 客户号='这个订单的客户号' and datediff(dd,定购日期,这个订单的日期)=0
select @orderid='这个订单的客户号'+substring(convert(varchar(8),这个订单的日期,12),3,6)+right(('00'+str(@count+1)),3)

---------------------------------------------------------------

最后一个铁错了,不好意思
有点小错误
if @@ERROR<>0 ROLLBACK else Commit Tran MyTran --和上面名字一致
go
---------------------------------------------------------------

上百个表你还是要一个一个改去,当然你也可以直接对syscolumns 修改。

1、
订购编号:我建议在输入时设置其默认值即可,其默认值根据
[客户号] [订购日期]
这两个字段来处理,至于后面的001,则用自定义规则来处理

2、写触发器

---------------------------------------------------------------

做成主键就不允许重复了阿
---------------------------------------------------------------

事务
事务是作为单个逻辑工作单元执行的一系列操作。一个逻辑工作单元必须有四个属性,称为 ACID(原子性、一致性、隔离性和持久性)属性,只有这样才能成为一个事务:

原子性

事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。

一致性

事务在完成时,必须使所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。事务结束时,所有的内部数据结构(如 B 树索引或双向链表)都必须是正确的。

隔离性

由并发事务所作的修改必须与任何其它并发事务所作的修改隔离。事务查看数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据。这称为可串行性,因为它能够重新装载起始数据,并且重播一系列事务,以使数据结束时的状态与原始事务执行的状态相同。

持久性

事务完成之后,它对于系统的影响是永久性的。该修改即使出现系统故障也将一直保持。

指定和强制事务处理
SQL 程序员要负责启动和结束事务,同时强制保持数据的逻辑一致性。程序员必须定义数据修改的顺序,使数据相对于其组织的业务规则保持一致。然后,程序员将这些修改语句包括到一个事务中,使 Microsoft® SQL Server™ 能够强制该事务的物理完整性。

企业数据库系统(如 SQL Server)有责任提供一种机制,保证每个事务物理的完整性。SQL Server 提供:

锁定设备,使事务相互隔离。

记录设备,保证事务的持久性。即使服务器硬件、操作系统或 SQL Server 自身出现故障,SQL Server 也可以在重新启动时使用事务日志,将所有未完成的事务自动地回滚到系统出现故障的位置。

事务管理特性,强制保持事务的原子性和一致性。事务启动之后,就必须成功完成,否则 SQL Server 将撤消该事务启动之后对数据所作的所有修改。

---------------------------------------------------------------

隔离级别
当锁定用作并发控制机制时,它可以解决并发问题。这使所有事务得以在彼此完全隔离的环境中运行,但是任何时候都可以有多个正在运行的事务。

可串行性是通过运行一组并发事务达到的数据库状态,等同于这组事务按某种顺序连续执行时所达到的数据库状态。

SQL-92 隔离级别
尽管可串行性对于事务确保数据库中的数据在所有时间内的正确性相当重要,然而许多事务并不总是要求完全的隔离。例如,多个作者工作于同一本书的不同章节。新章节可以在任意时候提交到项目中。但是,对于已经编辑过的章节,没有编辑人员的批准,作者不能对此章节进行任何更改。这样,尽管有未编辑的新章节,但编辑人员仍可以确保在任意时间该书籍项目的正确性。编辑人员可以查看以前编辑的章节以及最近提交的章节。

事务准备接受不一致数据的级别称为隔离级别。隔离级别是一个事务必须与其它事务进行隔离的程度。较低的隔离级别可以增加并发,但代价是降低数据的正确性。相反,较高的隔离级别可以确保数据的正确性,但可能对并发产生负面影响。应用程序要求的隔离级别确定了 SQL Server 使用的锁定行为。

SQL-92 定义了下列四种隔离级别,SQL Server 支持所有这些隔离级别:

未提交读(事务隔离的最低级别,仅可保证不读取物理损坏的数据)。

提交读(SQL Server 默认级别)。

可重复读。

可串行读(事务隔离的最高级别,事务之间完全隔离)。
如果事务在可串行读隔离级别上运行,则可以保证任何并发重叠事务均是串行的。

下面四种隔离级别允许不同类型的行为。

隔离级别 脏读 不可重复读取 幻像
未提交读 是 是 是
提交读 否 是 是
可重复读 否 否 是
可串行读 否 否 否

事务必须运行于可重复读或更高的隔离级别以防止丢失更新。当两个事务检索相同的行,然后基于原检索的值对行进行更新时,会发生丢失更新。如果两个事务使用一个 UPDATE 语句更新行,并且不基于以前检索的值进行更新,则在默认的提交读隔离级别不会发生丢失更新。

Published At
Categories with 数据库类
Tagged with
comments powered by Disqus