2017-07-14 69 views
0

我有一個表,看起來像這樣:使用rowversion更新行時出現異常?

CREATE TABLE [dbo].[akut_prioritering] 
(
    [behandling_id] [int] NOT NULL, 
    [akutstatus] [int] NOT NULL, 
    [nasta_dag] [bit] NOT NULL, 
    [sort_order] [bigint] NOT NULL, 
    [rowversion] [timestamp] NOT NULL, 

    CONSTRAINT [XPKakut_prioritering] 
     PRIMARY KEY CLUSTERED ([behandling_id] ASC) 
) ON [PRIMARY] 

然後我試圖在這個表中更新的行此存儲過程:

ALTER PROCEDURE [dbo].[akutlistaSave] 
    @behandlingSortOrder dbo.akutlista_sortorder_tabletype READONLY 
AS 
BEGIN 
    SET NOCOUNT ON; 

    DECLARE @behandlingId INT; 
    DECLARE @sortOrder BIGINT; 
    DECLARE @rowversion ROWVERSION; 

    DECLARE sortOrderCursor CURSOR LOCAL SCROLL STATIC FOR 
     SELECT behandling_id, sort_order FROM @behandlingSortOrder 

    OPEN sortOrderCursor 

    BEGIN TRAN 

     FETCH NEXT FROM sortOrderCursor INTO @behandlingId, @sortOrder, @rowversion 

     WHILE @@FETCH_STATUS = 0 
     BEGIN 
      IF EXISTS(SELECT * 
         FROM akut_prioritering ap 
         WHERE ap.behandling_id = @behandlingId 
         AND ap.rowversion = @rowversion) 
      BEGIN 
       UPDATE akut_prioritering 
       SET sort_order = @sortOrder 
       WHERE behandling_id = @behandlingId; 
      END 
      ELSE 
      BEGIN 
       RAISERROR ('Rowversion not correct.', 16, 1); 
      END 

      FETCH NEXT FROM sortOrderCursor INTO @behandlingId, @sortOrder, @rowversion 
     END 

     CLOSE sortOrderCursor 

     SELECT 
      ap.behandling_id, ap.rowversion 
     FROM 
      akut_prioritering ap 
     INNER JOIN 
      @behandlingSortOrder bso ON ap.behandling_id = bso.behandling_id; 

     DEALLOCATE sortOrderCursor 
END 

的inparameter類型如下:

CREATE TYPE [dbo].[akutlista_sortorder_tabletype] AS TABLE 
      (
       [behandling_id] [int] NULL, 
       [sort_order] [bigint] NULL, 
       [rowversion] [timestamp] NULL 
      ) 

運行此我得到一個SqlException

無法將明確的值插入到時間戳列中。對列列表使用INSERT來排除時間戳列,或者將DEFAULT插入到時間戳列中。

從我所瞭解的rowversion列中應該自動更新一個新值,在我的情況下沒有理由將其設置爲手動。

+0

如果最終使用遊標執行*單個*更新,則使用存儲過程在批處理中執行樂觀更新沒有多大意義。這最終會比發送單獨的UPDATE語句慢*。更好的選擇是在目標表和輸入之間進行連接,並僅更新具有匹配rowversions的行。 *然後*選擇並返回所有*不匹配rowversions的那些 –

+0

一個ORM將產生類似的代碼*,而沒有遊標引入的懲罰。 –

回答

3

您不能設置在dbo.akutlista_sortorder_tabletyperowversion值,因爲它是不可更新的:它是自動生成的

然而,rowversion(又名棄用timestamp)是一個簡單的(VAR)二進制(8),還有一些特殊規則。您可以二進制的dbo.akutlista_sortorder_tabletype(8)定義和設置(VAR)和UPDATE

上比較從第一個鏈接

一個不可爲空的rowversion列在語義上等同於一個二進制文件(8)列。可空的rowversion列在語義上等同於varbinary(8)列。

0

它看起來像你正試圖insert在自定義表類型timestamp值,然後傳遞,爲您的存儲過程。正如您的錯誤所示,您不能將insert明確的timestamp值轉換爲timestamp列。

您將需要找到一種將表值傳遞給此存儲過程的不同方法。

+0

這不是OP要求的。代碼似乎沒有在任何地方修改rowversion –

+0

@PanagiotisKanavos存儲過程採用自定義表類型作爲包含'timestamp'列的參數,如果不是'insert'ed直接呈現任何'timestamp'比較無用。 – iamdave

+1

這不是問題。比較是允許的。問題是,* TVP *甚至不能被*客戶端*填充,因爲rowversion不能被修改 –