SQL Server 2005 ROW_NUMBER() without ORDER BY

后端 未结 2 1743
心在旅途
心在旅途 2020-11-29 09:17

I am trying to insert from one table into another using

DECLARE @IDOffset int;
SELECT @IDOffset = MAX(ISNULL(ID,0)) FROM TargetTable

INSERT INTO TargetTable         


        
相关标签:
2条回答
  • 2020-11-29 09:48

    You can avoid specifying an explicit ordering as follows:

    INSERT dbo.TargetTable (ID, FIELD)
    SELECT
       Row_Number() OVER (ORDER BY (SELECT 1))
          + Coalesce(
             (SELECT Max(ID) FROM dbo.TargetTable WITH (TABLOCKX, HOLDLOCK)),
             0
          ),
       FieldValue
    FROM dbo.SourceTable
    WHERE {somecondition};
    

    However, please note that is merely a way to avoid specifying an ordering and does NOT guarantee that any original data ordering will be preserved. There are other factors that can cause the result to be ordered, such as an ORDER BY in the outer query. To fully understand this, one must realize that the concept "not ordered (in a particular way)" is not the same as "retaining original order" (which IS ordered in a particular way!). I believe that from a pure relational database perspective, the latter concept does not exist, by definition (though there may be database implementations that violate this, SQL Server is not one of them).

    The reason for the lock hints is to prevent the case where some other process inserts using the value you plan to use, in between the parts of the query executing.

    Note: Many people use (SELECT NULL) to get around the "no constants allowed in the ORDER BY clause of a windowing function" restriction. For some reason, I prefer 1 over NULL.

    Also: I think an identity column is far superior and should be used instead. It's not good for concurrency to exclusively lock entire tables. Understatement.

    0 讨论(0)
  • 2020-11-29 09:57

    You can ignore the ordering by using order by (select null) like this:

    declare @IDOffset int;
    select  @IDOffset = max(isnull(ID, 0)) from TargetTable
    
    insert  into TargetTable(ID, FIELD)
    select  row_number() over (order by (select null)) + @IDOffset, FeildValue
      from  SourceTable
     where  [somecondition]
    
    0 讨论(0)
提交回复
热议问题