下面的两个存储过程是用来给给顾客发会员卡和会员卡冲消费积分金额的,第一个存储过程有时候无法
把变参中的的数据插入tr_customer表中,第二个存储过程,如果是本店卡和当日的信用卡,将从retjels中取xulh,riqi,shoukyh三个字段插入tr_jifen表,然后把retjels中当前xulh的yishj更新为否。但是,如果再多台机器同时写入的时候,此存储过程可能会只运行
create PROCEDURE tr_jifen_pro
(
    @cd char(8) ,
    @xph char(12) ,
    @kh decimal(15,2),
    @ky char(6)
--设置变参
)
 AS
if not exists   --判断下面的select是否返回值,如果不返回值,执行下面的语句,如果返回跳到else
  (select 1 from tr_customer where cardno =@cd)   --直接判断卡号是否在tr_customer表中
 begin
  insert into tr_jifen
  (cardno,xulh,riqi,shishje,kouhj,jiqrq,shoukyh,jfsky,ontime)
  select '非本店卡',xulh,riqi,shishje,@kh,convert(char(10),getdate(),120),shoukyh,@ky,convert(char(10),getdate(),8)
  from retjels
  where xulh=@xph and yishj='否'  --当选定的小票号在retjels中的yishj字段为否,查询纪录插入tr_jifen表 end
else
 begin  insert into tr_jifen
  (cardno,xulh,riqi,shishje,kouhj,jiqrq,shoukyh,jfsky,ontime)
  select @cd,xulh,riqi,shishje,@kh,convert(char(10),getdate(),120),shoukyh,@ky,convert(char(10),getdate(),8)
  from retjels
  where xulh=@xph and yishj='否'  ----当选定的小票号在retjels中的yishj字段为否,查询纪录插入tr_jifen表
  update retjels set yishj='是' where xulh=@xph  --当选定的小票号在retjels中的yishj字段为是   update tr_jifen set xulh='非本日小票' where jiqrq<>riqi and cardno=@cd  
 endselect top 10 *
from tr_jifen
where jfsky=@ky
order by ontime descGO上面的存储过程,所用到的表及其结构
retjels中的字段有,xulh,riqi,shoukyh,yishj
tr_customer的表结构
create table tr_customer --创建新tr_customer表
(
    xh int identity(1,1), 
    cardno char(8) not null,
    certif_no char(18) not null,
    certif char(8) not null,
    uname char(8) not null,
    sex char(2) null,
    phone char(12) null,
    fkrq char(10) null
)
tr_jifen表的结构
create table tr_jifen  --创建新tr_jifen表
(
    cardno char(8) not null,
    xulh char(12) not null,
    riqi char(10) null,
    shishje decimal(15,2) null default 0,
    kouhj decimal (15,2) null default 0,
    jiqrq char(10) null,
    shoukyh char(6) null,
    jfsky char(6) null,
    ontime char(10) null,
    beizhu char(50) null
)

解决方案 »

  1.   

    上面的是第二个存储过程,第一个存储过程拉下了
    在这里
    CREATE PROCEDURE tr_customer_pro
    (
        @cd char(8) ,
        @cto char(18) ,
        @ctf char(8) ,
        @xm char(8) ,
        @xb char(2) ,
        @tel char(12)
    )as
    if not exists
    (select 1 from tr_customer where cardno=@cd or CERTIF_NO=@cto) 
    --判断变参中的卡号和身份证号是否在tr_customer表中存在,存在返回1值
    insert into tr_customer
    (cardno,certif_no,certif,uname,sex,phone,fkrq)
    select  @cd,@cto,@ctf,@xm,@xb,@tel,convert(char(10),getdate(),120)--返回当前日期select xh as 序号,cardno,certif_no,certif,uname,sex,phone,fkrq
    from tr_customer 
    where cardno=@cd
      

  2.   

    我觉得好象很多SQL的资料书里都有类似的案例的.象我买的SQL 2000 BIBLE中就有,比如第一个存储过程改为:
    if not exists
    (select 1 from tr_customer where cardno=@cd or CERTIF_NO=@cto) 
    --判断变参中的卡号和身份证号是否在tr_customer表中存在,存在返回1值
    insert into tr_customer
    (cardno,certif_no,certif,uname,sex,phone,fkrq)
    select  @cd,@cto,@ctf,@xm,@xb,@tel,convert(char(10),getdate(),120)--返回当前日期
    select @inerror=@@error
    if @inerror<>0
    begin 
    print '插入失败'
    return @inerror
    end
    select xh as 序号,cardno,certif_no,certif,uname,sex,phone,fkrq
    from tr_customer 
    where cardno=@cd只要流程语句写好了就可以达到你的要求了.
      

  3.   

    谢谢您的帮助,刚接触SQL,本人较穷,现在就是看联机帮助和CSDN
      

  4.   

    SQL在连续执行一些语句时可能会出现不能执行的情况,原因不太清楚,一般情况下我是将执行快的放在前面执行,相反的放在后面执行
      

  5.   

    单机执行没有任何问题,但是多台机器同时执行,就会有无法插入的现象,但是最后一个update是执行的
      

  6.   

    create PROCEDURE tr_jifen_pro
    (
        @cd char(8) ,
        @xph char(12) ,
        @kh decimal(15,2),
        @ky char(6)
    --设置变参
    )
     AS
    if not exists   --判断下面的select是否返回值,如果不返回值,执行下面的语句,如果返回跳到else
      (select 1 from tr_customer where cardno =@cd)   --直接判断卡号是否在tr_customer表中
     begin
      insert into tr_jifen
      (cardno,xulh,riqi,shishje,kouhj,jiqrq,shoukyh,jfsky,ontime)
      select '非本店卡',xulh,riqi,shishje,@kh,convert(char(10),getdate(),120),shoukyh,@ky,convert(char(10),getdate(),8)
      from retjels
      where xulh=@xph
      and xulh not in (select distinct xulh from tr_jifen where riqi=convert(char(10),getdate(),120) and cardno<>'非本店卡')    --当选定的小票号在retjels中的yishj字段为否,查询纪录插入tr_jifen表 end
    else
     begin
      insert into tr_jifen
      (cardno,xulh,riqi,shishje,kouhj,jiqrq,shoukyh,jfsky,ontime)
      select @cd,xulh,riqi,shishje,@kh,convert(char(10),getdate(),120),shoukyh,@ky,convert(char(10),getdate(),8)
      from retjels
      where xulh=@xph 
      and xulh not in (select distinct xulh from tr_jifen where riqi=convert(char(10),getdate(),120) and cardno<>'非本店卡')  
     ----当选定的小票号在retjels中的yishj字段为否,查询纪录插入tr_jifen表
    endselect top 10 *
    from tr_jifen
    where jfsky=@ky
    and riqi=convert(char(10),getdate(),120)
    order by ontime desc
    GO
    存储过程我修改了一下,虽然解决了最后不进行update的问题,但是还没有解决同时插入时无法插入的问题。
      

  7.   

    恩 可能是并发问题了。
    试一试提高事物隔离级别
    set transaction isolation level 
    --------
    语法
    SET TRANSACTION ISOLATION LEVEL
        { READ COMMITTED
            | READ UNCOMMITTED
            | REPEATABLE READ
            | SERIALIZABLE 
        }参数
    READ COMMITTED指定在读取数据时控制共享锁以避免脏读,但数据可在事务结束前更改,从而产生不可重复读取或幻像数据。该选项是 SQL Server 的默认值。READ UNCOMMITTED执行脏读或 0 级隔离锁定,这表示不发出共享锁,也不接受排它锁。当设置该选项时,可以对数据执行未提交读或脏读;在事务结束前可以更改数据内的数值,行也可以出现在数据集中或从数据集消失。该选项的作用与在事务内所有语句中的所有表上设置 NOLOCK 相同。这是四个隔离级别中限制最小的级别。REPEATABLE READ锁定查询中使用的所有数据以防止其他用户更新数据,但是其他用户可以将新的幻像行插入数据集,且幻像行包括在当前事务的后续读取中。因为并发低于默认隔离级别,所以应只在必要时才使用该选项。SERIALIZABLE在数据集上放置一个范围锁,以防止其他用户在事务完成之前更新数据集或将行插入数据集内。这是四个隔离级别中限制最大的级别。因为并发级别较低,所以应只在必要时才使用该选项。该选项的作用与在事务内所有 SELECT 语句中的所有表上设置 HOLDLOCK 相同。注释
    一次只能设置这些选项中的一个,而且设置的选项将一直对那个连接保持有效,直到显式更改该选项为止。这是默认行为,除非在语句的 FROM 子句中在表级上指定优化选项。SET TRANSACTION ISOLATION LEVEL 的设置是在执行或运行时设置,而不是在分析时设置。示例
    下例为会话设置 TRANSACTION ISOLATION LEVEL。对于每个后续 Transact-SQL 语句,SQL Server 将所有共享锁一直控制到事务结束为止。SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
    GO
    BEGIN TRANSACTION
    SELECT * FROM publishers
    SELECT * FROM authors
    ...
    COMMIT TRANSACTION