Я создаю базу для модульного тестирования, содержащую базу данных.
Детали не важны, но эта предпосылка привела меня в некоторые необычные ситуации.
Сейчас я пытаюсьчтобы создать представление для некоторых конкретных данных модульного теста, и я пытаюсь:
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
Тестирование с 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] ) ) )