5

У меня есть функция SQL CLR, как этот:CLR Table-функция с аргументом массива

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 является:

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

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

ответ

6

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

  • CREATE PROCEDURE

    [type_schema_name. ] Тип_данное
    ...
    Руководства по процедурам CLR:

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

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

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

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

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

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

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

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

это смешно: «вы всегда можете отправить в ограниченном списке значений», потому что я оказался здесь, ища пути, чтобы пройти в таблице строк, так что я мог бы использовать CLR объединить их в одну разделительную строку :) – BigOmega