我有一个方法,它可以很好地独立运行,我想把它变成一个函数或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
答案 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