2010-03-10 4 views
1

Я преобразовываю в целочисленный первичный ключ, и у меня возникают проблемы с посевом новых данных столбца с количеством целых чисел.Как заполнить столбец количеством чисел?

Учитывая существующую таблицу:

create table t1 (
    Id uniqueidentifier, 
    NewId int, 
    Data nvarchar(100) 
) 

Как бы обновить существующие строки с числом чисел от 1 до # строк в результирующем наборе?

Итак:

|id  |NewId  |Data 
------------------------------- 
|ABC  |null  |first 
|DEF  |null  |second 
|GHI  |null  |third 

бы стать:

|id  |NewId |Data 
---------------------------- 
|ABC  |1  |first 
|DEF  |2  |second 
|GHI  |3  |third 

Это для миграции с использованием HILO первичного ключа с NHibernate, которая необходима, чтобы уменьшить круглые базы данных поездок с между моим приложением и ядро базы данных, поэтому IDENTITY для меня не вариант.

+0

Какая версия SQL Server? Сбрасывается ли последовательность? –

+0

SQL Server 2008. После заполнения данных я буду использовать другой метод управления основным ключом. Мне просто нужно заполнить существующие данные один раз. –

ответ

4

Вы можете использовать оконную функцию как row_number:

update t 
set NewId = sub.rn 
from YourTable t 
join (
    select 
     id 
    , row_number() over (order by id) as rn 
    from YourTable 
) sub on sub.id = t.id 
+0

Я пробовал это, и он говорит, что я должен объявить @t. Это отсутствует в примере? –

+1

@Michael: Упс, @t должен быть вашим. Отредактировано в ответ – Andomar

0

Вместо того, чтобы пытаться сделать это самостоятельно, почему бы просто не добавить столбец как личность.

ALTER TABLE YourTable 
    ADD NewId INT IDENTITY(1,1) 

Это позаботится об этом за вас.

+0

Причина, по которой я не буду использовать функциональность IDENTITY. Вместо этого я буду использовать алгоритм hilo через nhibernate, чтобы избежать взаимных посещений базы данных на вставках. –

+1

В этом случае решение, использующее Row_NUMBER, может быть лучшим способом. –

+0

Вы можете удалить IDENTITY после обновления данных, так что это выполняет ту же функцию, что и Row_Number, и я использовал ее в прошлом для этой же цели. – Rupert

1

не уверен, насколько эффективно это, но это работает - см команду обновления вблизи нижней

create table t1 (Id uniqueidentifier, 
       NewId int, 
       Data nvarchar(100)) 
create index idx_t1 on t1(data) 

insert into t1 values (newid(), null, 'B') 
insert into t1 values (newid(), null, 'A') 
insert into t1 values (newid(), null, 'F') 
insert into t1 values (newid(), null, 'C') 
insert into t1 values (newid(), null, 'E') 

update t1 
    set [newid]=(select count(*) from t1 as temp where temp.data <= t12.data) 
from t1 as t12 

select * from t1 
1
DECLARE @Id INT 
DECLARE @CurrentRow INT 
SET @CurrentRow = 1 

DECLARE SetIDCursor INSENSITIVE CURSOR FOR 
    SELECT Id 
    FROM t1 
    ORDER BY Id 
    FOR READ ONLY 

OPEN SetIDCursor 

WHILE (0=0) 
    BEGIN 
    FETCH NEXT FROM SetIDCursor 
    INTO @Id 

    IF (@@FETCH_STATUS <> 0) BREAK 

    UPDATE t1 
    SET NewID = @CurrentRow 
    WHERE Id = @Id 

    SET @CurrentRow = @CurrentRow + 1 
    END 

CLOSE SetIDCursor 
DEALLOCATE SetIDCursor 
+0

Этот пример работал и занял 30 секунд. Тот, который я принял, занял 1 секунду, поэтому я отметил это как ответил. Спасибо за вашу помощь. –

+1

Курсоры действительно должны быть последним средством –

2

использования RowNumber(), это отлично подходит для таких вещей:

;WITH SequencedData AS 
(
    SELECT Id, ROW_NUMBER() OVER (ORDER BY Id) Sequence 
    FROM [YourTable] 
) 
UPDATE t 
SET NewId = sd.Sequence 
FROM [YourTable] t 
JOIN SequencedData sd 
    ON sd.Id = t.Id 
2

Вы можете использовать переменную и увеличивать ее на 1 для каждой обновляемой строки.

DECLARE @id INT 
SET @id = 0 

UPDATE TableName 
SET @id = ColumnName = @id + 1 
+0

хороший с чистым и элегантным подходом. –

Смежные вопросы