创建一个函数以从SQL Server 2008中的表返回结果

时间:2015-11-06 15:52:41

标签: sql sql-server sql-server-2008

我有一个方法,它可以很好地独立运行,我想把它变成一个函数或SP。我搜索了很多在线问题和答案,但没有人给我足够的信息来找出问题所在。

表本身不需要是变量,因为它总是相同的,但是find类型(@FindTypeID),quantity(@qtyfld)和weight(@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
  列名或提供的值数与表定义不匹配。

我会假设以下内容来检索数据。

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

1 个答案:

答案 0 :(得分:1)

您无法使用UDF。 您需要动态SQL来解决问题。

UDF有一些限制。 其中之一是您无法在UDF中使用EXEC功能。 您必须满足存储过程才能执行动态SQL。

我必须提及的一些事情......或面对一个downvote; - )

1)使用动态SQL时注意SQL注入 2)在构建动态SQL时应该使用quotename函数 3)当您使用动态SQL

时,DBA不喜欢它

试一试......

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