declare @LastYe money
  set @LastYe = 0  
  update TmpAccount set @LastYe = @LastYe + (mDebit - mCredit),mBanlance = @LastYe
  
  TmpAccount表有主键,有一个ID列是主键。为什么这样更新后mBanlance 结果总是不定呢?

解决方案 »

  1.   

    Create table TmpAccount(
        iID int IDENTITY (1, 1) ,
        mDebit money,
        mCredit money,
        mBanlance money)iID         mDebit                mCredit               mBanlance             
    ----------- --------------------- --------------------- --------------------- 
    1           20000.0000            .0000                 20000.0000
    2           11115.7000            .0000                 31115.7000
    3           8673.4000             .0000                 39789.1000
    4           9041.5000             .0000                 48830.6000
    5           25297.8000            .0000                 74128.4000
    6           73838.1800            .0000                 147966.5800
    7           384430.0900           .0000                 532396.6700
    8           40622.6100            .0000                 573019.2800
    9           198973.5600           .0000                 771992.8400
    10          350579.6400           .0000                 1122572.4800
    11          3148013.4500          .0000                 4270585.9300
    12          1785807.7900          .0000                 6056393.7200
    13          173966.1800           .0000                 6230359.9000
    14          34323.0500            .0000                 6264682.9500
    15          534763.6500           .0000                 6799446.6000
    16          544445.0900           .0000                 7343891.6900
    17          496244.7700           .0000                 7840136.4600
    18          280845.0000           .0000                 8120981.4600
    19          1000.0000             .0000                 8121981.4600
    20          191655.0000           .0000                 8313636.4600
    21          594980.1900           .0000                 8908616.6500
    22          485091.2600           .0000                 9393707.9100
    23          498903.9400           .0000                 9892611.8500
    24          5200.0000             .0000                 9897811.8500
    25          10000.0000            .0000                 9907811.8500
    26          11000.0000            .0000                 9918811.8500
    27          15000.0000            .0000                 9933811.8500
    28          3000.0000             .0000                 9936811.8500
    29          5306.0000             .0000                 9942117.8500
    30          2653.0000             .0000                 9944770.8500
    31          3630.0000             .0000                 9948400.8500
    32          1980.0000             .0000                 9950380.8500
    33          2740.0000             .0000                 9953120.8500
    34          2300.0000             .0000                 9955420.8500
    35          3000.0000             .0000                 9958420.8500
    36          2300.0000             .0000                 9960720.8500
      

  2.   

    这样试一下
    update TmpAccount SET mBanlance = @LastYe + (mDebit - mCredit)
      

  3.   

    晕,你不重新给@LastYe赋值的话没有任何的意义啊!
      

  4.   

    wwh999(印钞机V2.0...开发中....) ,按你说的做了一下,mBanlance的值全是0。
      

  5.   

    try putting this update query in a transaction
      

  6.   

    LouisXIV(夜游神):
       和事务有关系么?我总共就只有一条词句啊!
      

  7.   

    我需要的是将 mBanlance字段的值逐条记录累加,不想用游标。
      

  8.   

    LouisXIV(夜游神):   按你说的做了,还是没用。
      

  9.   

    update t
    set
        mBanlance=isnull((select sum(mDebit-mCredit) from TmpAccount where ID<t.ID),0)
    from
        TmpAccount t
      

  10.   

    update t
    set
        mBanlance=isnull((select sum(mDebit-mCredit) from TmpAccount where ID<=t.ID),0)
    from
        TmpAccount t
      

  11.   

    不按照主键的顺序来更新,应该算是SQL的BUG了,既然是按照ID的顺序累计mDebit-mCredit的值到mBanlance字段,不需要用变量,用上面的SQL可以实现。
      

  12.   

    不,我的@LastYe可能还有值的!就是说在update之前,@LastYe可能还计算出了一个值。
      

  13.   

    另外,libin_ftsafe(子陌红尘:当libin告别ftsafe) ,你的语句好象效率太低了,我执行你给的语句要花29秒,而我用游标才9秒呢。
      

  14.   

    试试:
    declare @LastYe money
      set @LastYe = 0  
      update TmpAccount set @LastYe = mBanlance = @LastYe + (mDebit - mCredit)同时:你的SQLSERVER 打补丁了没?? ID确认是主键?
      

  15.   

    Create table TmpAccount(
        iID int IDENTITY (1, 1) PRIMARY KEY,<<<--
        mDebit money,
        mCredit money,
        mBanlance money)
      

  16.   

    试试这样:
    declare @LastYe money
    set @LastYe = 0  Update a
    Set @LastYe = @LastYe + (mDebit - mCredit),mBanlance = @LastYe
    From
    (
    Select * From TmpAccount Order By ID
    ) a
      

  17.   

    update 不能进行order by 它的执行计划跟表结构和表中的数据有关, 而这个执行计划是否走索引, 走的那个索引, 都会影响最终的结果.
      

  18.   

    所以这样update的结果是不可控的
      

  19.   

    解决的方法是像 libin_ftsafe 那样, 通过条件确定执行顺序.
      

  20.   

    -- 另一种方法是通过 WITH 选项固定 update 要走的索引, 这样就可以保证更新按索引顺序进行的
    declare @LastYe money
    set @LastYe = 0  
    update A set 
    @LastYe = @LastYe + (mDebit - mCredit),mBanlance = @LastYe
    FROM TmpAccount WITH(INDEX=PK_TmpAccount)  -- 注意把 PK_TmpAccount 换成你的主键名称(注意不是列名)
      

  21.   

    -- 查询主键名用下面的语句:EXEC sp_pkeys @table_name = N'TmpAccount'如果你的update不是按主键顺序, 则为其他顺序建立索引, 并且将主键名改为对应的索引名
    (这个问题我的书上有讲, 并且有示例说明此问题)
      

  22.   

    update 不能进行order by 
    ===========
    是的,当时没有测试环境,没有测试 :)
    用With指定索引的方法可以以更好的速度实现。
      

  23.   

    看来是麻烦了,因为我的表是表变量。即通过declare @TmpAccount table ()这样得来的,没有给建立索引的。怎么办呢?
      

  24.   

    昨天就回复了,表声明时加primary key, 不认真看.