Как создать представление, в котором cross apply применяет ряд встроенных udf с табличным значением?

Вот структура кода, на которую я смотрю:

CREATE VIEW [dbo].[View1]

    AS SELECT t1.[ID]        ,
              udf1.[Column1] ,
              udf1.[Column2] ,
              udf1.[Column3]

        FROM [Table1] t1
            CROSS APPLY [dbo].[UDF1] ( [dbo].[UDF2] ( t1.[ID] ) ) udf1

GO

[dbo].[UDF1] и [dbo].[UDF2] являются встроенными функциями с табличным значением.

Я не помню точных деталей, но SSMS выдает ошибки, когда я пытался использовать JOIN, и SO сказал мне, что мне нужно использовать CROSS APPLY, чтобы исправить это - я думаю, что это был правильный выбор?

Во всяком случае, сейчас у меня есть основная проблема:

Cannot find either column "dbo" or the user-defined function or aggregate "dbo.UDF2", or the name is ambiguous.

... несмотря на то, что UDF2 явно существует: я вижу это в SSMS.

Я подозреваю, что настоящая проблема заключается в том, как UDF2 передается в качестве параметра в UDF1.
. UDF2 возвращает таблицу, и столбцы точно соответствуют возвращающему табличное значение параметру, определенному для UDF1.

Но я считать SQL Server не поддерживает этот синтаксис?
Нужно ли мне преобразовать мое представление в многострочную функцию с табличным значением, объявить табличную переменную для получения результатов UDF2, а затем передать эту табличную переменную в UDF1?

(P.S. Ошибки SQL Server - одни из наименее полезных, которые я когда-либо видел, на любом языке ...)

Ой, это будет ужасно.

Erik Philips 26.10.2018 04:28

@ErikPhilips Есть ли более эффективная альтернатива? Думаю, я думал, что встроенные функции в этом контексте работают довольно хорошо ... но я не совсем понимаю CROSS APPLY, так что ...

Giffyguy 26.10.2018 04:29

Не используйте UDF.

Erik Philips 26.10.2018 04:29

@ErikPhilips (Кроме того, я чувствую, что должен упомянуть, это работает с данными OLTP в памяти, а не с жестким диском. Так что производительность не будет такой плохой, как довольно, как кажется.)

Giffyguy 26.10.2018 04:40
0
4
23
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это, вероятно, будет иметь очень низкую производительность, но я думаю, вам нужно использовать отдельное CROSS APPLY для каждой функции табличного значения. Я не думаю, что можно использовать содержимое, возвращаемое UDF2, в UDF1, поскольку для UDF1 потребуется параметр типа таблицы, а UDF2 возвращает таблицу, но не тип таблицы.

Функции не могут возвращать типы таблиц, поэтому вам, вероятно, придется найти другое решение. Вы можете создать еще одну функцию, которая вставляет результаты UDF2 в тип таблицы, а затем вызывает UDF1.

Если бы вы могли это сделать, это выглядело бы примерно так:

CREATE VIEW [dbo].[View1]
    AS SELECT t1.[ID]        ,
              udf1.[Column1] ,
              udf1.[Column2] ,
              udf1.[Column3]
        FROM [Table1] t1
            CROSS APPLY [dbo].[UDF2] ( t1.[ID] ) udf2
            CROSS APPLY [dbo].[UDF1] ( udf2 ) udf1
GO

Чтобы создать «еще одну функцию-оболочку», это будет выглядеть так:

CREATE FUNCTION [dbo].[UDF3](
    @id INT -- data type for t1.ID
) RETURNS @t TABLE (
    -- ... Your columns here ...
) 
AS
BEGIN
    -- Your user defined Table Type
    DECLARE @udf2 UDF2_TABLE 
    INSERT @udf2 (... columns ...)
    SELECT udf2.* -- try to use exact column names instead of *
      FROM [Table1] t1
         CROSS APPLY [dbo].[UDF2]( t1.[ID] )

    -- I'm not really sure this is possible either
    INSERT @t (... columns ...)
    SELECT udf1.*
      FROM [dbo].[UDF1](@udf2) udf1

    RETURN;
END

Это то, о чем я думал. Прохладный. (Кроме того, я чувствую, что должен упомянуть, что это работает с данными OLTP в памяти, а не с жестким диском. Так что производительность не будет такой плохой, как довольно, как кажется.)

Giffyguy 26.10.2018 04:40

Другие вопросы по теме