2017-01-04 135 views
1

我試圖創建一個存儲過程,將接受數據表和表名作爲參數,並創建一個表來創建表。這是該過程:將顯示存儲過程使用的數據表,表名作爲參數

ALTER PROCEDURE [dbo].[SPROC_IMPORT_UPLOADED_EXCEL_DATA] 
    @DataTbl emTable READONLY , 
    @TableName [varchar](50) 
AS 
BEGIN 

DECLARE @SQL nvarchar(MAX) 

------------------------------------------------------------------------------- 
--Check 1: Checking if the table is already present 
-------------------------------------------------------------------------------  

IF OBJECT_ID (@TableName,'U') IS NOT NULL 
     SET @SQL = N'INSERT INTO ' + @TableName + ' SELECT * FROM ' + @DataTbl 
    ELSE 
     SET @SQL = N'SELECT * INTO ' + @TableName + ' FROM ' + @DataTbl 

EXEC sp_executesql @SQL 
END 

以下錯誤:

Msg 137, Level 16, State 1, Procedure SPROC_IMPORT_UPLOADED_EXCEL_DATA, Line 8 [Batch Start Line 7] 
Must declare the scalar variable "@DataTbl". 

研究錯誤後,試圖通過將參數以使用sp_executesql來修改過程。

EXEC sp_executesql @SQL, 
    N'@DataTbl emTable READONLY' , 
    '@TableName [varchar](50)', 
    @DataTbl, 
    @TableName; 

但是,顯示相同的錯誤。有什麼建議麼?

+0

爲什麼使用'EXEC sp_executesql @ SQL'而不是'EXEC(@SQL)'? – LONG

+0

@LONG我寧願使用sp_executesql,因爲它允許參數。當然在這種情況下你不能使用參數。 :) –

+0

檢查我的答案@ H.Bandi,我修改了基於您的SP – LONG

回答

0

您遇到的問題是由於變量的範圍。您的表值參數超出了動態SQL中的範圍。但是,如果使用臨時表,則可以解決此問題,因爲臨時表仍將處於動態SQL中的範圍內。

像這樣的東西應該讓你接近。注意QUOTENAME的使用。這將極大地幫助最大限度地降低sql注入的風險。我建議將@TableName的數據類型改爲sysname而不是varchar(50)。

ALTER PROCEDURE [dbo].[SPROC_IMPORT_UPLOADED_EXCEL_DATA] 
@DataTbl emTable READONLY , 
@TableName [varchar](50) 
AS 
BEGIN 

select * 
into #TempData 
from @DataTbl 

DECLARE @SQL nvarchar(MAX) 

------------------------------------------------------------------------------- 
--Check 1: Checking if the table is already present 
-------------------------------------------------------------------------------  

IF OBJECT_ID (@TableName,'U') IS NOT NULL 
    SET @SQL = N'INSERT INTO ' + QUOTENAME(@TableName) + ' SELECT * FROM #TempData' 
ELSE 
    SET @SQL = N'SELECT * INTO ' + QUOTENAME(@TableName) + ' FROM #TempData' 

EXEC sp_executesql @SQL 
END 
+0

非常感謝!使用臨時表解決了我的問題。 –

0
ALTER PROCEDURE [dbo].[SPROC_IMPORT_UPLOADED_EXCEL_DATA] 
    @DataTbl [varchar](50) , 
    @TableName [varchar](50) 
AS 
BEGIN 

DECLARE @SQL nvarchar(MAX) 

------------------------------------------------------------------------------- 
--Check 1: Checking if the table is already present 
-------------------------------------------------------------------------------  

IF OBJECT_ID (@TableName,'U') IS NOT NULL 
     SET @SQL = N'INSERT INTO ' + @TableName + ' SELECT * FROM ' + @DataTbl 
    ELSE 
     SET @SQL = N'SELECT * INTO ' + @TableName + ' FROM ' + @DataTbl 

EXEC (@SQL) 
END 

當您嘗試exec的過程:使用EXEC SPROC_IMPORT_UPLOADED_EXCEL_DATA @DataTbl = ..., @TableName=...

更新時間:

如果你需要分析表變量,聲明@Table Table(col, type...)或者可以創建一個用戶定義函數返回一個表結果

+0

我很確定@DataTbl是一個表值參數而不是字符串值。 –

+0

無論什麼@DataTbl類型,基於'SELECT * FROM + @ DataTbl',它應該是一個varchar – LONG

+0

正確。但他們傳遞的是一個表值參數而不是字符串。因此,這是一個很好的例子,說明如何用varchar做到這一點,它不適用於OP。說實話,OP是一個有缺陷的概念。 –

相關問題