您可能希望在Row_Number上进行分区OrderNo,但这应该可以帮助您入门:
declare @LineItems as Table ( LineItem Int Identity, Id VarChar(16) );
insert into @LineItems ( Id ) values
  ( '01' ), ( 'CA800' ), ( 'BERRY' ),
  ( '02' ), ( 'MSIJ54' ), ( '92-D-06' ), ( 'BERRY' );
with LineItems as (
  select LineItem, Id, Row_Number() over ( order by LineItem ) as RN
    from @LineItems
  ),
  PrefixedLineItems as (
  select LineItem, Id, Id as Prefix, Cast( NULL as VarChar(16) ) as Result, RN
    from LineItems
    where RN = 1
  union all
  select LI.LineItem, LI.Id,
    case when IsNumeric( LI.Id ) = 1 then LI.Id else PLI.Prefix end,
    case when IsNumeric( LI.Id ) = 1 then NULL else Cast( PLI.Prefix + '-' + LI.Id as VarChar(16) ) end, LI.RN
    from PrefixedLineItems as PLI inner join
      LineItems as LI on LI.RN = PLI.RN + 1
  )
  select LineItem, Id, Result
    from PrefixedLineItems
    order by LineItem
    option ( MaxRecursion 0 )
如果重要 ID值必须从 开始01并计数到 ,则可以添加额外的测试20。
编辑:嗯,这很糟糕。
生成附加样本数据的版本是:
-- Sample data.
if Object_Id( 'tempdb..#LineItems', N'U' ) is not NULL
  drop table #LineItems;
create table #LineItems ( LineItem Int Identity Primary Key, Id VarChar(32) not null );
insert into #LineItems ( Id ) values
  ( '01' ), ( 'CA800' ), ( 'BERRY' ),
  ( '02' ), ( 'MSIJ54' ), ( '92-D-06' ), ( 'BERRY' );
-- Generate some additional sample data.
declare @Count as Int = 1000;
while @Count > 0
  begin
  if Rand() < 0.1 -- Make about 10% of the entries numeric.
    insert into #LineItems ( Id ) values ( Right( '0' + Cast( Floor( Rand() * 20 ) + 1 as VarChar(2) ), 2 ) );
  else
    insert into #LineItems ( Id ) values ( 'Foo ' + Cast( Rand() as VarChar(16) ) );
  set @Count = @Count - 1;
  end;
-- Time the query.
declare @Start as DateTime = SysDateTime();
with NumberedLineItems as (
  select LineItem, Id, Row_Number() over ( order by LineItem ) as RN
    from #LineItems
  ),
  PrefixedLineItems as (
  select LineItem, Id, Id as Prefix, Cast( NULL as VarChar(16) ) as Result, RN
    from NumberedLineItems
    where RN = 1
  union all
  select LI.LineItem, LI.Id,
    case when IsNumeric( LI.Id ) = 1 then LI.Id else PLI.Prefix end,
    case when IsNumeric( LI.Id ) = 1 then NULL else Cast( PLI.Prefix + '-' + LI.Id as VarChar(16) ) end, LI.RN
    from PrefixedLineItems as PLI inner join
      NumberedLineItems as LI on LI.RN = PLI.RN + 1
  )
  select LineItem, Id, Result
    from PrefixedLineItems
    order by LineItem
    option ( MaxRecursion 0 );
select DateDiff( ms, @Start, SysDateTime() ) as [Elapsed Milliseconds],
  ( select Count(*) from #LineItems ) as [Rows];
这种 RBAR 方法可以更有效地扩展:
-- Sample data.
if Object_Id( 'tempdb..#LineItems', N'U' ) is not NULL
  drop table #LineItems;
create table #LineItems ( LineItem Int Identity Primary Key, Id VarChar(32) not null );
insert into #LineItems ( Id ) values
  ( '01' ), ( 'CA800' ), ( 'BERRY' ),
  ( '02' ), ( 'MSIJ54' ), ( '92-D-06' ), ( 'BERRY' );
-- Generate some additional sample data.
declare @Count as Int = 10000;
while @Count > 0
  begin
  if Rand() < 0.1 -- Make about 10% of the entries numeric.
    insert into #LineItems ( Id ) values
      ( Right( '0' + Cast( Floor( Rand() * 20 ) + 1 as VarChar(2) ), 2 ) )
  else
    insert into #LineItems ( Id ) values ( 'Foo ' + Cast( Rand() as VarChar(16) ) )
  set @Count = @Count - 1;
  end;
-- Create a fiendish thingy.
declare Plod cursor fast_forward for
  select LineItem, Id
    from #LineItems
    order by LineItem;
declare @LineItem as Int;
declare @Id as VarChar(32);
declare @Prefix as VarChar(2)
-- Create a table to hold the results.
if Object_Id( 'tempdb..#PrefixedLineItems', N'U' ) is not NULL
  drop table #PrefixedLineItems;
create table #PrefixedLineItems
  ( LineItem Int Primary Key, Id VarChar(32) not null, Prefix VarChar(2) null );
-- RBAR.
declare @Start as DateTime = SysDateTime();
open Plod;
fetch next from Plod into @LineItem, @Id;
while @@Fetch_Status = 0
  begin
  set @Prefix = case when IsNumeric( @Id ) = 1 then @Id else @Prefix end;
  insert into #PrefixedLineItems ( LineItem, Id, Prefix ) values
    ( @LineItem, @Id, case when IsNumeric( @Id ) = 1 then NULL else @Prefix end );
  fetch next from Plod into @LineItem, @Id;
  end;
close Plod;
deallocate Plod;
-- That's all, folks!
select LineItem, Id, Prefix
  from #PrefixedLineItems
  order by LineItem;
select DateDiff( ms, @Start, SysDateTime() ) as [Elapsed Milliseconds],
  ( select Count(*) from #LineItems ) as [Rows]