2015-11-06 77 views
1

我有一種方法,它可以很好地獨立工作,我希望變成一個函數或SP。我已經通過大量在線問題和答案進行了搜索,但沒有人給我足夠的信息來找出錯誤。創建函數以返回SQL Server 2008中的表的結果

表本身並不需要是一個變量,因爲它總是相同的,但查找類型(@FindTypeID),數量(@qtyfld)和權重(@wtfld)字段可以不同。

CREATE FUNCTION ReturnFindsWithNotes 
    (@table nvarchar(50), @FindTypeID int, @qtyfld nvarchar(50), @wtfld nvarchar(50)) 
    RETURNS @query TABLE 
    (
     [SiteCodeID] int NULL, 
     [TrenchID] int NULL, 
     [Context] [nvarchar](20), 
     [FindsID] int NULL, 
     [BagNo] [nvarchar](20), 
     [FindTypeID] [int] NULL, 
     [FindQty] [int] NULL, 
     [FindWeight] [float] NULL, 
     [FindNotes] [nvarchar](500) NULL 
    ) 
    AS 
    BEGIN 
     INSERT @query 
     SELECT 
      'SELECT * INTO #temp1 
      FROM 
      (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS ID, SiteCodeID, TrenchID, Context, findsID, BagNo, ' + @FindTypeID + ' As FindTypeID, ' + @qtyfld + ' AS FindQty, ' + @wtfld + ' AS FindWeight, Notes, NotesToType 
       ,LTRIM(RTRIM((b.splitdata))) AS FindNotes 
      FROM ' + @table + 
      ' CROSS APPLY dbo.fnSplitString(FindsNWW.Notes,''^'') AS b 
      ) AS k 

      SELECT * INTO #temp2 
      FROM 
      (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS ID, SiteCodeID, TrenchID, Context, findsID, BagNo, ' + @FindTypeID + ' As FindTypeID, ' + @qtyfld + ' AS FindQty, ' + @wtfld + ' AS FindWeight, Notes, NotesToType 
       ,LTRIM(RTRIM((c.splitdata))) As FindTypeIDFromNotes 
      FROM ' + @table + 
      ' CROSS APPLY dbo.fnSplitString(FindsNWW.NotesToType,''^'') AS c 
      ) AS l 
      INSERT INTO @query ([SiteCodeID], [TrenchID], [Context], [FindsID], [BagNo], [FindTypeID], [FindQty], [FindWeight], [FindNotes]) 
      SELECT #temp1.SiteCodeID, #temp1.TrenchID, #temp1.Context, #temp1.FindsID, #temp1.BagNo, #temp1.FindTypeID, #temp1.FindQty, #temp1.FindWeight, FindNotes 
      FROM #temp1 JOIN #temp2 on #temp1.ID = #temp2.ID WHERE FindTypeIDFromNotes = ' + @FindTypeID + ' 
      DROP TABLE #temp1 
      DROP TABLE #temp2' 
     FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @table 
     RETURN 
    END 

以上是我得到了,但在執行創建函數時,我得到的錯誤:

Msg 213, Level 16, State 1, Procedure ReturnFindsWithNotes, Line 16
Column name or number of supplied values does not match table definition.

而且我將承擔以下檢索數據。

SELECT * 
FROM ReturnFindsWithNotes ('FindsNWW', 12, 'PotWt', 'PotWt') 

非常感謝@Spock。隨着一些額外的東西我留在外面,它現在工作。以下是我的工作。

CREATE PROCEDURE ReturnFindsWithNotes 
     @table   nvarchar(50), 
     @FindTypeID  int, 
     @qtyfld   nvarchar(50), 
     @wtfld   nvarchar(50) 
AS 
BEGIN 
    DECLARE @SQL NVARCHAR(MAX); 
    SET @SQL = ' 
    CREATE TABLE #temp1(
    [SiteCodeID] int, 
    [TrenchID] int, 
    [Context] [nvarchar](20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, 
    [FindsID] int, 
    [BagNo] [nvarchar](20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, 
    [FindTypeID] [int] NULL, 
    [FindQty] [int] NULL, 
    [FindWeight] [float] NULL, 
    [FindNotes] [nvarchar](500) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
) 

select * into #temp2 
from 
(SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS ID, SiteCodeID, TrenchID, Context, findsID, BagNo, 1 As FindTypeID, OtherQty, OtherWt, Notes, NotesToType 
    ,ltrim(rtrim((b.splitdata))) AS Notes1 
FROM FindsNWW 
CROSS APPLY dbo.fnSplitString(FindsNWW.Notes,''^'') AS b 
) AS k 

select * into #temp3 
from 
(SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS ID, SiteCodeID, TrenchID, Context, findsID, BagNo, 1 As FindTypeID, OtherQty, OtherWt, Notes, NotesToType 
    ,ltrim(rtrim((c.splitdata))) As Notes2 
FROM FindsNWW 
CROSS APPLY dbo.fnSplitString(FindsNWW.NotesToType,''^'') AS c 
) AS l 
INSERT INTO [#temp1] ([SiteCodeID], [TrenchID], [Context], [FindsID], [BagNo], [FindTypeID], [FindQty], [FindWeight], [FindNotes]) 
select #temp2.SiteCodeID, #temp2.TrenchID, #temp2.Context, #temp2.FindsID, #temp2.BagNo, #temp2.FindTypeID,#temp2.OtherQty, #temp2.OtherWt, Notes1 
from #temp2 join #temp3 on #temp2.ID = #temp3.ID Where Notes2 = 1 
drop table #temp2 
drop table #temp3 

CREATE TABLE #temp4(
    [SiteCodeID] int NULL, 
    [TrenchID] int NULL, 
    [Context] [nvarchar](20) NULL, 
    [FindsID] int NULL, 
    [BagNo] [nvarchar](20) NULL, 
    [FindTypeID] [int] NULL, 
    [FindQty] [int] NULL, 
    [FindWeight] [float] NULL, 
    [FindNotes] [nvarchar](500) NULL 
) ON [PRIMARY] 

INSERT INTO #temp4 ([SiteCodeID], [TrenchID], [Context], [FindsID], [BagNo], [FindTypeID], [FindQty], [FindWeight], [FindNotes]) 
SELECT [SiteCodeID], [TrenchID], [Context], [FindsID], [BagNo], [FindTypeID], [FindQty], [FindWeight], 
CASE WHEN [FindNotes] = '''' THEN NULL ELSE [FindNotes] END 
FROM [#temp1] ORDER BY SiteCodeID,[TrenchID], Context, [FindsID], BagNo, FindTypeID 
DROP TABLE #temp1 
SELECT * FROM #temp4 ORDER BY FindsID 
DROP TABLE #temp4' 

EXEC sp_executesql @SQL, N'@FindTypeID INT', @FindTypeID 

END 
+4

過多的失誤是沒有指出。首先你不能在函數內部創建'temp tables',所以把這個過程設爲 –

+1

這個錯誤是因爲你試圖插入你的表中,但是你的select語句中只有一列,那是一個很大的醜陋的動態sql字符串。這需要對你正在嘗試做的事情有一個全面的反思。臨時表在這裏毫無意義,一個cte會更好。 –

回答

1

您不能爲此使用UDF。 您將需要動態SQL來解決問題。

UDF有一些限制。 其中,您不能在UDF中使用EXEC函數。 您必須要解決存儲過程才能執行動態SQL。

有些事情,我不得不提到....或面臨downvote ;-)

1)使用動態SQL 2時當心SQL注入)構建動態SQL 時,應使用QUOTENAME函數3)當您使用動態SQL

試試這個數據庫管理員不喜歡它......

CREATE PROCEDURE ReturnFindsWithNotes 
     @table   nvarchar(50), 
     @FindTypeID  int, 
     @qtyfld   nvarchar(50), 
     @wtfld   nvarchar(50) 
AS 
BEGIN 
    DECLARE @SQL NVARCHAR(MAX); 

    SET @SQL = ' 
SELECT * INTO #temp1 
FROM 
(SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS ID, SiteCodeID, TrenchID, Context, findsID, BagNo, @FindTypeID As FindTypeID, ' + @qtyfld + ' AS FindQty, ' + @wtfld + ' AS FindWeight, Notes, NotesToType 
,LTRIM(RTRIM((b.splitdata))) AS FindNotes 
FROM ' + @table + 
' CROSS APPLY dbo.fnSplitString(FindsNWW.Notes,''^'') AS b 
) AS k 

SELECT * INTO #temp2 
FROM 
(SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS ID, SiteCodeID, TrenchID, Context, findsID, BagNo, @FindTypeID As FindTypeID, ' + @qtyfld + ' AS FindQty, ' + @wtfld + ' AS FindWeight, Notes, NotesToType 
,LTRIM(RTRIM((c.splitdata))) As FindTypeIDFromNotes 
FROM ' + @table + 
' CROSS APPLY dbo.fnSplitString(FindsNWW.NotesToType,''^'') AS c 
) AS l 
INSERT INTO @query ([SiteCodeID], [TrenchID], [Context], [FindsID], [BagNo], [FindTypeID], [FindQty], [FindWeight], [FindNotes]) 
SELECT #temp1.SiteCodeID, #temp1.TrenchID, #temp1.Context, #temp1.FindsID, #temp1.BagNo, #temp1.FindTypeID, #temp1.FindQty, #temp1.FindWeight, FindNotes 
FROM #temp1 JOIN #temp2 on #temp1.ID = #temp2.ID WHERE FindTypeIDFromNotes = @FindTypeID 
DROP TABLE #temp1 
DROP TABLE #temp2' 


    EXEC sp_executesql @SQL, N'@FindTypeID INT', @FindTypeID 

END 
+0

我欣賞這裏的意見和建議。我正在努力克服缺乏SP和功能知識/經驗。由於數據用於本地數據處理以創建將在稍後日期使用的數據表,幸運的是,SQL注入的問題不會出現,因爲最終可見數據的用戶將不能直接訪問sql ,只需通過網絡訪問。關於上面的程序,我收到一個錯誤:'消息208,級別16,狀態6,過程ReturnFindsWithNotes,行33' ''無效的對象名'ReturnFindsWithNotes'.' –

+0

對不起,錯誤是我的錯,我沒有刪除以前的過程。我將通過這個工作並嘗試理解這些原則,謝謝。 –

+0

非常感謝@Spock,我已經添加了上面的工作過程。 –

相關問題