假设我想从两个表中获得学生摘要:学生,年级:
CREATE PROCEDURE prc_get_student_grade_summaries
@studentIds [Integer_udtt] READONLY
AS
BEGIN
SELECT Name,
func_GetGradeAForStudent()
FROM tbl_student AS tS
INNER JOIN
@studentIds AS tSI
ON tS.Id = tSI.studentId
整数udtt定义如下:
CREATE TYPE [Integer_udtt] AS TABLE (
[Id] INT NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC));
func_GetGradeAForStudent类似于学生选择COUNT(*),其中studentId = id AND grade = 1 - 1:A
我想要的结果是摘要列表:
StudentId Number of A
101 5
102 4
103 2
将studentId从@studentId传递给func_GetGradeAForStudent的正确方法是什么?
答案 0 :(得分:1)
您无法将表值参数传递给UDF:
表值参数的限制
表值参数有几个限制:
您不能将表值参数传递给用户定义的函数。
表值参数只能被索引以支持UNIQUE或PRIMARY KEY约束。 SQL Server不维护统计信息 表值参数。
表值参数在Transact-SQL代码中是只读的。您无法更新表值行中的列值 参数,您不能插入或删除行。修改数据 传递给存储过程或参数化语句 表值参数,必须将数据插入临时 表或表变量。
您不能使用ALTER TABLE语句来修改表值参数的设计。
由于这些只是学生ID的列表,一种可能性是将这些ID作为逗号分隔的id列表传递,并使用split函数从逗号分隔列表中重新创建表。在SO和其他地方有大量示例,您可以在其中找到拆分函数的示例实现。
甚至更好,在你的proc中做所有事情。如果一切都在select count(*)...
,我真的没有看到对该函数的需要你应该能够内联所有内容,也许可以使用子选择:
CREATE PROCEDURE prc_get_student_grade_summaries
@studentIds [Integer_udtt] READONLY
AS
BEGIN
SELECT Name,
(select COUNT(*) from student where studentId = tSI.studentId AND grade = 1 ) as NumberOfAs
FROM tbl_student AS tS
INNER JOIN
@studentIds AS tSI
ON tS.Id = tSI.studentId
<强>更新强>
示例拆分函数,它以逗号分隔的列表并返回一个表:
CREATE FUNCTION [dbo].[fnSplit](
@sInputList VARCHAR(8000) -- List of delimited items
, @sDelimiter VARCHAR(8000) = ',' -- delimiter that separates items
) RETURNS @List TABLE (item VARCHAR(8000))
BEGIN
DECLARE @sItem VARCHAR(8000)
WHILE CHARINDEX(@sDelimiter,@sInputList,0) <> 0
BEGIN
SELECT
@sItem=RTRIM(LTRIM(SUBSTRING(@sInputList,1,CHARINDEX(@sDelimiter,@sInputList,0)-1))),
@sInputList=RTRIM(LTRIM(SUBSTRING(@sInputList,CHARINDEX(@sDelimiter,@sInputList,0)+LEN(@sDelimiter),LEN(@sInputList))))
IF LEN(@sItem) > 0
INSERT INTO @List SELECT @sItem
END
IF LEN(@sInputList) > 0
INSERT INTO @List SELECT @sInputList -- Put the last item in
RETURN
END
你这样称呼:select * from fnSplit(@CommaSeparetedList,',');