пакетная вставка возвращает поля идентичности неупорядоченности - PullRequest
1 голос
/ 05 марта 2011

У меня есть (таблица A) с одним полем идентификации (ID), мне нужно вставить несколько строк одновременно с помощью одной операции вставки, поэтому я использую структуру таблицы в качестве параметра передачи для моей хранимой процедуры

Мне нужен вставленный идентификатор в порядке вставки, поэтому я выполняю следующий запрос в моем SP (таблица B имеет ту же структуру, что и таблица A):

CREATE PROCEDURE ssp_Test
(
    tableA tableAType
)
AS
BEGIN

INSERT INTO tableB(field1, field2, ...)
OUTPUT INSERTED.ID
SELECT field1, field2, ... from tableA

END

Если я запускаю описанную выше процедуру с 100 записями, она возвращает новое поле идентификатора в порядке, который он вставил в таблицу B, но когда я запускаю его с 500 записями, все вставленные идентификаторы возвращаются без разумного порядка, почему это происходит?

Мне не нужна другая временная таблица, чтобы поместить ее туда, отсортировать и вернуть, я просто хочу знать, почему это происходит, и есть ли какое-либо решение без использования дополнительной временной таблицы для сортировки?

Ответы [ 4 ]

3 голосов
/ 05 марта 2011

В общем случае не существует такой вещи, как упорядоченная INSERT, но SQL Server поддерживает способ указания порядка, в котором значения IDENTITY назначаются операцией. Эта гарантия распространяется только на вставленную таблицу, работает только с INSERT ... SELECT (не SELECT INTO) и ничего не говорит о «порядке», в котором вставка строк фактически выполняется механизмом хранения.

Если вам нужно назначить значения идентификаторов в определенном порядке и вернуть сгенерированные значения идентификаторов в порядке , вы можете использовать табличную переменную с предложением OUTPUT:


-- New data values
DECLARE @Data
TABLE   (
        some_value BIGINT NOT NULL
        )
;
-- Table to be inserted to
DECLARE @Destination
TABLE   (
        row_id  INTEGER IDENTITY PRIMARY KEY CLUSTERED,
        data    BIGINT NOT NULL
        )
;
-- Table to hold IDs generated
DECLARE @IDs
TABLE   (
        row_id  INTEGER NOT NULL PRIMARY KEY CLUSTERED
        )
;
-- Sample new data values to add to destination
INSERT  @Data
VALUES  (1001), (996), (108), (250), (2000)
;
-- Do the insert, assign identity values
-- in the order of values going in,
-- and save the IDs generated in @IDs
INSERT  @Destination (data)
OUTPUT  inserted.row_id
INTO    @IDs (row_id)
SELECT  D.some_value
FROM    @Data AS D
ORDER   BY
        D.some_value ASC
;
-- Return the IDs in a particular order
SELECT  I.row_id
FROM    @IDs AS I
ORDER   BY
        I.row_id ASC
;

Для получения дополнительной информации см .: Гарантии заказа в SQL Server и Нет ремня безопасности - ожидается заказ без ORDER BY

3 голосов
/ 05 марта 2011

Если вы хотите что-то заказать, вам придется использовать предложение ORDER BY. Нет смысла пытаться полагаться на физический порядок (даже если вы думаете, что он существует (например, из-за кластерного индекса)

1 голос
/ 05 марта 2011

Посмотрите на эту статью: http://technet.microsoft.com/en-us/library/ms177564.aspx

В нем говорится: «Нет гарантии, что порядок, в котором изменения применяются к таблице, и порядок, в котором строки вставляются в выходную таблицуили табличная переменная будет соответствовать. "

Я предлагаю использовать выбор после вставки для получения идентификаторов.

0 голосов
/ 06 марта 2011

Чтобы заполнить столбец числовой последовательностью, используйте ROW_NUMBER () (или последовательность в SQL Server 2012). Не пытайтесь полагаться на столбец IDENTITY, потому что его поведение не всегда можно контролировать.

...