Как передать UDTT отдельно к другой функции в SQL - PullRequest
0 голосов
/ 07 декабря 2011

Предположим, я хочу получить резюме ученика из двух таблиц: ученик, класс:

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 - что-то вроде select COUNT(*) от студента, где studentId = id и оценка = 1 - 1: A

Я хочу получить список резюме:

StudentId  Number of A
101   5
102   4
103   2

Как правильно пройти видентификатор студента от @studentIds к func_GetGradeAForStudent?

1 Ответ

1 голос
/ 07 декабря 2011

Нельзя передавать параметры табличных значений в пользовательские функции:

MSDN:

Ограничения табличных параметров

Существует несколько ограничений для табличных параметров:

Нельзя передать табличные параметры пользовательским функциям.

Табличные параметры могут быть проиндексированы только для поддержки ограничений UNIQUE или PRIMARY KEY.,SQL Server не ведет статистику по табличным параметрам.

Табличные параметры доступны только для чтения в коде Transact-SQL.Вы не можете обновить значения столбцов в строках табличного параметра, а также не можете вставлять или удалять строки.Чтобы изменить данные, передаваемые в хранимую процедуру или параметризованный оператор в параметре с табличным значением, необходимо вставить данные во временную таблицу или в табличную переменную.

Нельзя использовать операторы ALTER TABLE, чтобы изменитьпроектирование табличных параметров.

Поскольку это всего лишь список идентификаторов учеников, одной из возможностей будет передать эти идентификаторы в виде списка идентификаторов, разделенных запятыми, и использовать функцию разделения для воссозданиятаблица из списка, разделенного запятыми.Здесь, в SO и других местах, есть множество примеров, где вы можете найти примеры реализации функции split.

Или, что еще лучше, делайте все внутри вашего 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,',');

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...