2012-12-10 32 views
0

SQL Server的示例表。是否可以在創建時插入外鍵值?

  • MainRecordsid, record
  • AuxRecordsmainRecords_id, record
  • SourceRecordsrecord1, record2

MainRecords.id是自遞增的主身份密鑰。

是否有可能從SourceRecords選擇並插入MainRecordsAuxRecords同時使得MainRecords.record = record1AuxRecords.record = record2AuxRecords.mainRecords_id = MainRecords.id都在一個單獨的語句?

編輯:

基於從下面的提示,我想這...

DECLARE @MainRecords table(id int PRIMARY KEY IDENTITY, record varchar(5)) 
DECLARE @AuxRecords table(mainRecords_id int, record varchar(5)) 
DECLARE @SourceRecords table(record1 varchar(5), record2 varchar(5)) 

INSERT @SourceRecords VALUES ('a', 'a') 
INSERT @SourceRecords VALUES ('a', 'b') 
INSERT @SourceRecords VALUES ('a', 'c') 
INSERT @SourceRecords VALUES ('b', 'a') 
INSERT @SourceRecords VALUES ('b', 'b') 
INSERT @SourceRecords VALUES ('b', 'c') 
INSERT @SourceRecords VALUES ('c', 'a') 
INSERT @SourceRecords VALUES ('c', 'b') 
INSERT @SourceRecords VALUES ('c', 'c') 

INSERT INTO @MainRecords (record) 
    OUTPUT inserted.id, @SourceRecords.record2 
    INTO @AuxRecords (mainRecords_id, record) 
SELECT record1 FROM @SourceRecords 

select * from @MainRecords 
select * from @AuxRecords 

但不幸的是得到錯誤:

Msg 137, Level 16, State 1, Line 16 
Must declare the scalar variable "@SourceRecords". 

如果我改變這些表類型的變量轉化爲現實表我得到的錯誤:

Msg 4104, Level 16, State 1, Line 3 
The multi-part identifier "SourceRecords.record2" could not be bound. 

下面的工作很好,但顯然它不是一個完整的解決方案。我只是展示它來證明我的語法是正確的。

INSERT INTO @MainRecords (record) 
    OUTPUT inserted.id --, @SourceRecords.record2 
    INTO @AuxRecords (mainRecords_id) --, record) 
SELECT record1 FROM @SourceRecords 

所以...除非有一些竅門我缺少的,好像OUTPUT是這個問題的一個死衚衕的解決方案。

使用觸發器創建視圖或空表的其他建議不是解決此問題的「單一語句」解決方案。此外,它們增加了默默無聞,而添加一些額外的列和使用存儲過程同樣複雜,但更明顯和直接。

+4

爲什麼 「*在一條語句*」?只需在Transactions中使用存儲過程,無論如何你都應該這樣做。 – RBarryYoung

+0

OUTPUT子句可能能夠爲您工作。你並沒有提供足夠的模式信息。通過'OUTPUT',您通常可以返回一個結果集,插入/更新/刪除一個表,並在同一個語句中插入另一個表中。列可用性存在限制。在事務中編寫多個語句要容易得多,但是,即使這樣做,'OUTPUT'語句對於捕獲一組生成的標識也是必需的。 –

+0

@RBarryYoung與交易的過程是「我應該如何做這些事情」*如果沒有更優雅的方式。恕我直言,單一聲明*可以*,在理論上,更優雅。我編輯了我的問題,以表明我有多接近一個非常優雅的解決方案,但不幸的是,它似乎不起作用。此外,除非使用遊標或臨時表,或添加一些新的列等,否則您會看到您建議的內容不適用於我的精確示例;與我所希望的相比,這一切都有點混亂,但似乎是唯一的選擇。 –

回答

1

社區維基

沒有在這個問題足夠的信息來編寫代碼來解決這個問題。所以,這裏是一個「通用」輸出條款例如,這完全不涉及到這個問題,比其他的顯示輸出如何使用:

這將刪除,插入和返回多行單個語句

DECLARE @OldTable table(col1 int, col2 varchar(5), col3 char(5), col4  datetime) 
DECLARE @NewTable table(col1 int, column2 varchar(5), col3 int , col_date char(23), extravalue int, othervalue varchar(5)) 
INSERT @OldTable VALUES (1 , 'AAA' ,'A' ,'1/1/2010'   ) 
INSERT @OldTable VALUES (2 , 'BBB' ,'12' ,'2010-02-02 10:11:22') 
INSERT @OldTable VALUES (3 , 'CCC' ,null ,null    ) 
INSERT @OldTable VALUES (4 , 'B' ,'bb' ,'2010-03-02'  ) 

DELETE @OldTable   --<<<alter table 1 
    OUTPUT DELETED.col1 --<<<alter table 2 
      ,DELETED.col2 
      ,CASE 
       WHEN ISNUMERIC(DELETED.col3)=1 THEN DELETED.col3 
       ELSE NULL END 
      ,DELETED.col4 
      ,CONVERT(varchar(5),DELETED.col1)+'!!' 
     INTO @NewTable (col1, column2, col3, col_date, othervalue) 
    OUTPUT 'Rows Deleted: ', DELETED.* --<<<returns a result set 
    WHERE col1 IN (2,4) 

SELECT * FROM @NewTable 

OUTPUT:

   col1  col2 col3 col4 
-------------- ----------- ----- ----- ----------------------- 
Rows Deleted: 2   BBB 12 2010-02-02 10:11:22.000 
Rows Deleted: 4   B  bb 2010-03-02 00:00:00.000 

(2 row(s) affected) 

col1  column2 col3  col_date    extravalue othervalue 
----------- ------- ----------- ----------------------- ----------- ---------- 
2   BBB  12   Feb 2 2010 10:11AM  NULL  2!! 
4   B  NULL  Mar 2 2010 12:00AM  NULL  4!! 

(2 row(s) affected) 
+0

你得到了一個提示,並教給我一些新的東西,但它似乎不是一個正確的答案。根據您的提示查看我編輯的問題。也許你可以在我的推理中看到一個缺陷。 (作爲一個便箋,恕我直言,我的原始問題確實提供了「足夠的信息......來編寫代碼」,如果有人做出一些相當常見的假設,但編輯的問題更加清楚。) –

+0

您不能包含'@SourceRecords。record2'在你的OUTPUT子句中,只允許插入表中的列 –

+0

我接受這個答案。這不是現貨,但提供的是最好的。 AFAIK,沒有現場答案是可能的。 –

0

@DG你不能在一個語句中修改多個表。正如@RBarryYoung建議你應該使用存儲過程和事務來做這種事情。另一個更極端的選擇是在MainRecords和AuxRecords上創建一個將行連接在一起的視圖,然後在視圖上創建一個before觸發器,將其拆分爲兩個插入,每個插入一個針對每個基表。然後你的客戶可以對視圖執行一次插入。總而言之,我認爲存儲過程/交易方法更爲明顯。

+1

您可以在一條語句中修改多個乘法表,查看'OUTPUT INTO'子句。 –

+0

@KM在OUTPUT INTO上的優點。在這裏沒有想到它,因爲AuxRecords表需要MainRecords中不存在的值。 – BStateham

+0

我不記得在OUTPUT caluse之前我曾經做過的事情!我發現無法使用多行和標識列。 –

0

從實際的角度來看,@ BStateham和@RBarryYoung給了你正確和完整的答案。但是,如果這是一個技術問題,你只想知道它是否可行,我會說:是的。

引入包含兩列的僞造表:record1,record2。

然後在此表上創建一個INSTEAD OF INSERT觸發器,它只是將信息添加到其他兩個表中。

當您執行一條語句'INSERT INTO MyBogusTable(record1,record2)VALUES(1,2)'時,您將使用一條語句實際將值插入到兩個不同的表中。

無論如何,這是醜陋的,不推薦。這是愚蠢和莫名其妙(必須使用translate.google這個詞)。

但是:對於「是否可能?」這個問題回答「是」是一種可能性。 好吧,調用存儲過程也是'單一語句',但是......啊......好吧。

相關問題