2010-04-23 49 views
2

我正在學習如何使用SQL和存儲過程。我知道語法不正確:從存儲過程複製表格的數據

將數據從一個表複製到另一個具有存儲過程數據庫的表中。問題是我不知道要複製到哪個表或哪個數據庫。我希望它使用參數,而不是專門指定列。

我有2個數據庫(Master_db和Master_copy)和每個數據庫上的相同表結構。

我想在Master_db中快速選擇一個表格,並將該表格的數據複製到Master_copy表格中並使用相同的名稱。我想出了這樣的事情:

USE Master_DB 
CREATE PROCEDURE TransferData 
DEFINE @tableFrom, @tableTo, @databaseTo; 

INSERT INTO @[email protected] 
SELECT * FROM [email protected] 
GO; 

我能得到的最接近的是這樣的。現在的問題是,我有一個Timestamp列,並且出現錯誤:

「無法將明確值插入到時間戳列中。使用帶列列表的INSERT來排除時間戳列,或將DEFAULT插入時間戳柱。」

USE Kenneth_Integration 
GO 
CREATE PROCEDURE TransferData 
    @table SYSNAME 
    ,@databaseTo SYSNAME 
AS 
DECLARE @sql NVARCHAR(MAX) 

SET @sql = 'DELETE FROM ' + @databaseTo + '..' + @table + ' set identity_insert ' + @databaseTo + '.dbo.' + @table + 
    ' on INSERT INTO ' + @databaseTo + '.dbo.' + @table + ' SELECT * FROM Kenneth_Integration.dbo.' + @table 

EXEC sp_executesql @sql 
GO 

我該如何解決這個SP錯誤?

+0

如果您正在複製到可能已經包含一些您正在複製的數據的表中,您是否考慮了該怎麼做?身份專欄也可能是一個問題。 – amelvin 2010-04-23 10:29:14

回答

3

對象名稱查詢不能以您嘗試的方式參數化。

爲了得到這個工作,你需要使用動態SQL:

USE Master_DB 
CREATE PROCEDURE TransferData 
@tableFrom SYSNAME 
,@tableTo SYSNAME 
,@databaseTo SYSNAME 
AS 
DECLARE @sql NVARCHAR(MAX) 
SET @sql = 'INSERT INTO ' + @databaseTo+ '.dbo.' + @tableTo + ' 
      SELECT * FROM Master_DB.dbo.' + @tableFrom 

EXEC sp_executesql @sql 
GO; 
+0

「動態SQL」對我來說是新的,並且感謝您指引我朝着正確的方向發展。我相信你的查詢有一個錯誤。但你的回答是正確的!錯誤(@ databaseTo +'.dbo。'+ @databaseTo) – Niike2 2010-04-23 11:36:37

+0

@ Niike2 - 更正。 (我從你原來的帖子中複製錯誤) – 2010-04-23 12:18:07

+1

我建議每當做這樣的事情時,圍繞對象名稱使用QuoteName函數。 – MartW 2010-04-23 12:35:20

1

我的建議是寫函數返回表 不是使用插入SELECT語句的程序和功能之間

差異比你可以不寫 select procedure但 你可以寫在SQL 選擇功能

+0

好的,但這並不能幫助我更多,因爲我有SQL語言問題,我認爲語法是非常錯誤的。而且我不知道這是否可能? – Niike2 2010-04-23 08:48:54

1

只有動態SQL允許變量作爲表名。例如:

create procedure dbo.TransferData(
    @src varchar(50), 
    @dest varchar(50)) 
as 
declare @query varchar(500) 
set @query = 'INSERT INTO ' + @src + 
    'SELECT * FROM ' + @dest 
exec @query 
go 
1

我同意@EdHarper建立一個字符串,然後運行sp_executesql可能是你最好的答案。

兩件事情要牢記,我不能在以前的答案,請參閱:

1)您可以在數據已經複製到超過master_copy數據庫表之前,所以你可能需要刪除數據目標表您啓動複製操作之前。 2)如果您在Master_copy表中有任何標識列(因爲您使用相同的Sql腳本生成Master_db和Master_copy表)(例如),那麼您需要確保您可以覆蓋標識值(這可以完成由set identity_insert on命令)。

所以作爲替代(有沒有點到另一個重複回答),當你知道數據庫的名稱,你可以簡單地進行非規範化這一做法,並寫爲每個表一個簡單的存儲過程。

假設你有一個叫「人」表你可以寫:

create procedure TransferDataPerson 
as 

delete from Master_copy..Person 

set identity_insert Master_copy..Person on 

insert into Master_copy..Person 
select * from Master_db..Person 

...等等爲每個表。

+0

我已考慮您的觀點並將它們添加到查詢中。謝謝,非常好的答案!現在的問題已添加到此頁面上的答案。 – Niike2 2010-04-23 11:34:09