CLR Табличная функция с аргументом массива - PullRequest
9 голосов
/ 20 января 2011

У меня есть функция SQL CLR, подобная этой:

public partial class UserDefinedFunctions {
    [Microsoft.SqlServer.Server.SqlFunction(TableDefinition = "number int", FillRowMethodName = "FillRow")]
    public static IEnumerable MyClrFunction(object obj) {
        // read obj array input and then
        var result = new ArrayList();
        result.Add((SqlInt32)1);
        result.Add((SqlInt32)2);
        result.Add((SqlInt32)3);
        return result;
    }

    public static void FillRow(object obj, out SqlInt32 number) {
        number = (SqlInt32)obj;
    }

}

Я бы хотел использовать ее следующим образом:

DECLARE @x arrayOfInt

INSERT INTO @x VALUES (10)
INSERT INTO @x VALUES (20)
INSERT INTO @x VALUES (30)

SELECT * FROM dbo.MyClrFunction(@x)

arrayOfInt is:

CREATE TYPE [dbo].[arrayOfInt] AS TABLE(
[item] [int] NOT NULL,
PRIMARY KEY CLUSTERED 
    (
    [item] ASC
    ) WITH (IGNORE_DUP_KEY = OFF)
)

У меня проблема в том, что arrayOfInt несовместимо с sql_variant.Можно ли написать таблично-значную функцию CLR с аргументом массива (таблицы)?

1 Ответ

11 голосов
/ 22 января 2011

SQLCLR не поддерживает табличные параметры (TVP):

  • CREATE PROCEDURE

    [type_schema_name.] data_type
    ...
    Рекомендации по процедурам CLR:

    • Табличные или курсор типы данных использовать нельзяв качестве параметров.
  • CREATE FUNCTION

    [type_schema_name.] parameter_data_type
    ... Для функций CLR разрешены все типы данных, включая определяемые пользователем типы CLR, кроме text , ntext , image , определяемые пользователем типы таблиц и отметка времени типы данных.

Однако у вас есть несколько вариантов:

  1. Если массив представляет собой простой список чисел и / или строк, вы можетевсегда отправляйте список значений с разделителями (через SqlString / NVARCHAR (MAX)) и используйте String.Split () для его распаковки.

  2. Если массив более сложный (т. е. несколько полей), тогда вы можете обернуть данные в XML и передать их как SqlXml.

  3. Или, если у вас есть сложный массив, вы можете создать CLR UDT, который будет любой структурой, которая вам нравитсяи передать это в функцию.Однако это требует немного больше усилий.

  4. Кроме того, имейте в виду, что таблично-значимые параметры - это просто таблицы (переменные таблицы), а не структуры данных в памяти, такие какМассивы и Коллекции.Основное преимущество и сценарий использования TVP заключается в уменьшении сложности и повышении производительности при отправке данных на SQL Server из приложения.Если вы уже находитесь внутри SQL Server, так что вы создаете табличную переменную и затем хотите передать ее в хранимую процедуру CLR (или, может быть, функцию), тогда все, что вам нужно сделать, это взглянуть на проблему немного по-другому, и выможет выполнить то же самое:

    • Использовать временную таблицу вместо табличной переменной
    • Передать имя временной таблицы в хранимую процедуру CLR
    • Использовать in-процессное соединение (т. е. строка соединения = "Context Connection = true;"), поскольку оно может обращаться к локальным временным объектам
    • Вы можете использовать временную таблицу в любом выполняемом вами SQL-запросе, используя имя таблицы, переданное в
    • Вы можете получить данные из этой таблицы в контекст .NET, выполнив простое SELECT * переданное имя таблицы, а затем прочитав каждую строку с помощью SqlCommand.ExecuteReader() и SqlDataReader.Read()
...