SQL Server 2005 ROW_NUMBER () без ORDER BY - PullRequest
29 голосов
/ 27 января 2011

Я пытаюсь вставить из одной таблицы в другую, используя

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

INSERT INTO TargetTable(ID, FIELD)
SELECT [Increment] + @IDOffset ,FeildValue
FROM SourceTable
WHERE [somecondition]

TargetTable.ID не является столбцом идентификаторов, поэтому я должен найти способ его автоматического увеличения.

Я знаю, что могу использовать курсор или создать переменную таблицы со столбцом идентификаторов и полем FieldValue, заполнить его, а затем использовать его в моем insert into...select, но это не очень эффективно. Я попытался использовать функцию ROW_NUMBER для увеличения, но у меня действительно нет допустимого поля ORDER BY в SourceTable, которое я могу использовать, и хотел бы сохранить исходный порядок SourceTable (если возможно).

Кто-нибудь может предложить что-нибудь?

Ответы [ 2 ]

76 голосов
/ 27 января 2011

Вы можете избежать указания явного порядка следующим образом:

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};

Тем не менее, обратите внимание, что это всего лишь способ избежать указания порядка, и НЕ гарантирует того, что любые исходные данные будут сохранены. Есть и другие факторы, которые могут привести к упорядочению результата, например ORDER BY во внешнем запросе. Чтобы полностью понять это, нужно понимать, что понятие «не упорядочено (определенным образом)» не то же самое, что «сохранение первоначального порядка» (которое упорядочено определенным образом!) Я считаю, что с точки зрения чисто реляционной базы данных, последняя концепция не существует , по определению (хотя могут существовать реализации базы данных, которые нарушают это, SQL Server не является одним из них) .

Причина подсказок блокировки состоит в том, чтобы предотвратить случай, когда какой-либо другой процесс вставляет значение, которое вы планируете использовать, между частями выполняемого запроса.

Примечание. Многие люди используют (SELECT NULL), чтобы обойти ограничение "не допускается использование констант в предложении ORDER BY оконной функции". По какой-то причине я предпочитаю 1 над NULL.

Также: я думаю, что столбец идентификаторов намного лучше и должен использоваться вместо него. Для параллелизма не рекомендуется блокировать только целые таблицы. Занижение.

4 голосов
/ 19 июля 2016

Вы можете игнорировать порядок, используя order by (select null), например:

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]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...