2010-05-14 6 views
3

РЕЗЮМЕ:
мне нужно использовать OUTPUT clause на INSERT заявление вернуть столбцы, которые не существуют на столе, в которую я вставляя. Если я могу избежать этого, Я не хочу добавлять столбцы в таблицу, в которую я вставляю.Вывод столбцов не в таблице назначения?

ДЕТАЛИ:
Моя FinishedDocument таблица имеет только один столбец. Это таблица, в которую я вставляю.

FinishedDocument
- DocumentID

Моя таблица Документ содержит два столбца. Это таблица, из которой мне нужно вернуть данные.

Документ
- DocumentID
- Описание

Ниже вставляет одну строку в FinishedDocument. Его предложение OUTPUT возвращает DocumentID, который был вставлен. Это работает, но это не дает мне описание вставленного документа.

INSERT INTO FinishedDocument 
OUTPUT INSERTED.DocumentID 
SELECT DocumentID 
FROM Document 
WHERE DocumentID = @DocumentID 

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

Какой синтаксис мне нужно снять? Я думаю, что это возможно только с одним заявлением INSERT, путем настройки предложения OUTPUT (каким образом я, очевидно, не понимаю)?

Есть ли более умный способ, который не похож на путь, по которому я иду сюда?

EDIT: SQL Server 2005

+1

Я с ума сошел, или вы упростили это, так что реальная проблема не очевидна? Вам не нужно выводить документацию, она уже хранится в переменной. – HLGEM

ответ

2

Посмотрите на Example A:

DECLARE @temp TABLE (DocumentID int) 

INSERT INTO FinishedDocument 
    OUTPUT INSERTED.DocumentID 
    INTO @temp 
SELECT DocumentID 
FROM Document 
WHERE DocumentID = @DocumentID 

SELECT Document.DocumentId, Document.Description 
FROM @temp AS t 
INNER JOIN Document 
    ON t.DocumentID = Document.DocumentID 
+0

Связанная вами страница утверждает, что «предложение OUTPUT INTO не поддерживается в инструкциях INSERT, содержащих предложение ». Оказывается, что мой запрос реального мира становится жертвой этого , – lance

+0

Не совсем эффективный, но, похоже, единственный способ выполнить эту работу. –

1

Интересно, если вы можете бэкдор это так (если это касается меня, что я на самом деле рассмотреть возможность сделать это таким образом?):

;WITH r (DocumentID) 
    AS (INSERT INTO FinishedDocument 
     OUTPUT INSERTED.DocumentID 
     SELECT DocumentID 
      FROM Document 
      WHERE DocumentID = @DocumentID) 
SELECT d.DocumentID, d.DocumentName 
    FROM Document d 
    JOIN r 
    ON d.DocumentID = r.DocumentID 

Ваш insert все еще использует предложение OUTPUT, но как встроенную таблицу, которая затем связывается с документом, чтобы получить необходимую информацию. Хотя по какой-то причине я не могу избежать чувства, что это безнадежно улаживает предложение WITH ...

+0

+1 избили меня, и у вас был полный пример. – NotMe

+3

INSERT недействителен в CTE (синтаксическая ошибка) – sqlvogel

+0

Я убежден, что CTE может иметь только инструкцию SELECT внутри ... так что, как выглядит этот отзыв, я сомневаюсь, что это сработает. –

1

Предложение OUTPUT может содержать любое из полей, на котором оно работает, например. в вашем случае: любое из полей, в которые вы вставляете данные. Это означает: любой из столбцов таблицы FinishedDocument.

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

0

Оберните вставку в CTE, а затем выберите соединение, чтобы вернуться к таблице документов.

0

В 2008 году вы можете сделать это с помощью заявления MERGE. Возможно, вы могли бы рассмотреть возможность обновления :)

MERGE INTO FinishedDocument 
USING Document d ON 1=0 
WHEN NOT MATCHED AND d.DocumentID = @DocumentID THEN 
INSERT (DocumentID) VALUES (@DocumentID) 
OUTPUT d.DocumentID, d.Description; 

Предлагаю вам проверить план выполнения, прежде чем пытаться это сделать.

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

+0

Мой реальный мир немного сложнее, чем мой вопрос. В моем реальном мире это находится в хранимой процедуре, которую одновременно будут вызывать несколько пользователей, а @DocumentID - это фактически условие, которое пройдет до тех пор, пока не произойдет INSERT. Поэтому я боюсь, что SELECT-then-INSERT может привести к тому, что два пользователя вернут один и тот же документ (поскольку UserB вызвал sproc и SELECTed RowX после того, как UserA выбрал RowX (но до UserA INSERTed, что помешало бы пользователю получить тот же самый строка). – lance

+0

Сделайте это наоборот. Выведите идентификатор из инструкции INSERT и затем ВЫБРАТЬ описание впоследствии. – sqlvogel

+0

Когда я выводя идентификатор - в какой я его храню (для последующего использования в запросе SELECT)? попытался сохранить его в переменной, но я не смог понять синтаксис, и «предложение OUTPUT INTO не поддерживается в инструкциях INSERT, содержащих предложение » (http://msdn.microsoft.com/en- us/library/ms177564.aspx), поэтому я не могу использовать временную таблицу? – lance

0

Как о чем-то вроде этого?

create table FinishedDocument (
    DocumentId int 
) 

create table Document (
    DocumentId int, 
    Description nvarchar(100) 
) 

create table #tmpDoc (
    DocumentId int 
) 

insert into Document 
    (DocumentId, Description) 
    values 
    (1, 'Test') 

insert into FinishedDocument 
    (DocumentId) 
    output Inserted.DocumentId into #tmpDoc 
    select D.DocumentId 
     from Document D 
     where D.DocumentId = 1 

select D.DocumentId, D.Description 
    from #tmpDoc t 
     inner join Document D 
      on t.DocumentId = D.DocumentId 

drop table #tmpDoc  
drop table FinishedDocument 
drop table Document 
+0

http://msdn.microsoft.com/en-us/library/ms177564.aspx заявляет, что «предложение OUTPUT INTO не поддерживается в инструкциях INSERT, содержащих предложение ». Оказывается, мой реальный запрос становится жертвой этого. :( – lance

+0

Не могли бы вы выбрать свой в таблице temp и использовать его для вставки? –