SQL Server: UDF табличного значения с параметром табличного значения из внутреннего представления - PullRequest
0 голосов
/ 12 октября 2018

Я создаю базу для модульного тестирования, содержащую базу данных.
Детали не важны, но эта предпосылка привела меня в некоторые необычные ситуации.

Сейчас я пытаюсьчтобы создать представление для некоторых конкретных данных модульного теста, и я пытаюсь:
CREATE VIEW [foo] AS SELECT * FROM TableValueUDF ( TableValueParam )
(Примечание: перемещение логики UDF в само представление приведет к огромному количеству дублирования кода в десятках).объектов базы данных, если не сотен - именно поэтому я избегаю этого.)

Очевидная проблема здесь в том, что вы не можете передать переменную в представление.
Но данные модульного тестатехнически статично ... поэтому я вернулся к:
CREATE VIEW [foo] AS SELECT * FROM TableValueUDF ( ( SELECT * FROM ( VALUES ... ) ) )
... где конечный пользователь-разработчик может вручную определить желаемые модульные тесты для каждого вида теста.

ИКонечно, SQL-сервер очень недоволен этим. (сообщения об ошибках указаны в приведенном ниже коде.)
Но я никогда не сталкивался с этим сценарием раньше, и я не знаю, как изменить этот запрос, чтобы выполнить то, что я пытаюсь сделать.
(Является ли это ситуацией, когда CROSS APPLY было бы полезно? Я не очень понимаю кросс-применимость.)

Мой настоящий код намного больше и сложнее, чем этот, поэтому я тестировал спростой пример сценария, помогающий локализовать проблему в repro.

Естественно, сообщения об ошибках не имеют никакого смысла. (указано внутри кода, в котором они появляются)
И поиск этих сообщений об ошибках приводит к совершенно другим ситуациям, бесполезным здесь.

Пример определений UDT и UDF:

/* Table-value UDT */
CREATE TYPE [dbo].[IntNameList]
AS TABLE
(
    [Value]    INT             NOT NULL ,
    [NameText] NVARCHAR ( 48 ) NOT NULL
)

GO

/* Table-value UDF with table-value parameter */
CREATE FUNCTION [dbo].[ProcessData]
(
    @tableValueParam [IntNameList] READONLY
)
RETURNS TABLE AS RETURN
(
    SELECT
        [Value]    ,
        [NameText] ,

        /* Simple example calculation: Is [Value] odd or even? */
        CAST ( IIF ( [Value] % 2 <> 0 , 1 , 0 ) AS BIT )
     AS [ValueOdd]

    FROM @tableValueParam
)

GO

Тестирование с объявленной переменной, чтобы убедиться, что UDF работает должным образом:

DECLARE @param [IntNameList]

INSERT INTO @param VALUES

    ( /* Value    */ 110 ,
      /* NameText */ N'Steve'
    ) ,

    ( /* Value    */ 111 ,
      /* NameText */ N'Mason'
    ) ,

    ( /* Value    */ 112 ,
      /* NameText */ N'Kimberly'
    )

/* Works as expected */
SELECT * FROM [dbo].[ProcessData] ( @param )

GO

enter image description here

Тестирование с CREATE VIEW, что является фактическим сценариемЯ пытаюсь достичь:

/*  Errors:

    1) "Only one expression can be specified in the select list
            when the subquery is not introduced with EXISTS."

    2) "Operand type clash: int is incompatible with IntNameList"
*/

CREATE VIEW [dbo].[ProcessExampleData] AS

SELECT * FROM [dbo].[ProcessData] ( ( SELECT * FROM ( VALUES

        ( /* Value    */ 110 ,
          /* NameText */ N'Steve'
        ) ,

        ( /* Value    */ 111 ,
          /* NameText */ N'Mason'
        ) ,

        ( /* Value    */ 112 ,
          /* NameText */ N'Kimberly'
        )

    ) AS [ExampleData] ( [Value]    ,
                         [NameText] ) ) )
...