5

Ho una funzione CLR SQL come questo:CLR con valori di tabella funzione con argomento di matrice

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; 
    } 

} 

vorrei usarlo in questo modo:

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) 
) 

Problema che ho è che arrayOfInt è incompatibile con sql_variant. È possibile scrivere la funzione con valori di tabella CLR che ha un argomento array (tabella)?

risposta

6

SQLCLR non supporta i parametri con valori di tabella (TVPs):

  • CREATE PROCEDURE

    [type_schema_name. ] Data_type
    ...
    Linee guida per le procedure CLR:

    • con valori di tabella o cursore i tipi di dati non possono essere utilizzati come parametri.
  • CREATE FUNCTION

    [type_schema_name. ] Parameter_data_type
    ... Per le funzioni CLR, tutti i tipi di dati, tra cui i tipi CLR definiti dall'utente, sono consentiti eccetto testo, ntext, immagine, tipi di tabella definiti dall'utente e timestamp tipi di dati.

Tuttavia, non sono disponibili diverse opzioni:

  1. Se la matrice è un semplice elenco di numeri e/o stringhe è sempre possibile inviare in un elenco delimitato di valori (via SqlString/NVARCHAR (MAX)) e utilizzare String.Split() per decomprimerlo.

  2. Se la matrice è più complessa (cioè più campi), è possibile racchiudere i dati in XML e inoltrarli come SqlXml.

  3. Oppure, se si dispone di un array complesso, è possibile creare un UDT CLR come qualsiasi struttura desiderata e trasferirlo nella Funzione. Ciò richiede un po 'più sforzo, però.

  4. Inoltre, tenere presente che i parametri con valori di tabella sono solo questo, tabelle (variabili di tabella) e non strutture di dati in memoria come matrici e raccolte.Il vantaggio principale e il caso d'uso dei TVP sono nel ridurre la complessità e aumentare le prestazioni quando si inviano dati a SQL Server da un'applicazione. Se si è già all'interno di SQL Server in modo tale che si sta creando una variabile di tabella e quindi si desidera passare a una stored procedure CLR (o magari a una funzione), tutto ciò che si deve fare è esaminare il problema in un modo leggermente diverso e può ottenere la stessa cosa di base:

    • utilizzare una tabella temporanea invece di una tabella delle variabili
    • Passare il nome della tabella temporanea per il CLR stored procedure
    • Utilizzare il collegamento in-process (cioè stringa di connessione = "Context Connection = true;") perché può accedere agli oggetti temporanei locali
    • È possibile utilizzare la tabella temporanea in qualsiasi SQL th esegui usando il nome della tabella che è stato passato in
    • Puoi ottenere i dati da quella tabella nel contesto .NET facendo un semplice SELECT * sul nome della tabella che è stato passato, e quindi leggi ogni riga tramite SqlCommand.ExecuteReader() e SqlDataReader.Read()
+2

questo è divertente: "è sempre possibile inviare in un elenco delimitato dei valori", perché mi sono trovato qui durante la ricerca di un modo per passare in una tabella di stringhe in modo da poter utilizzare il CLR per concatenarli in un'unica stringa delimitata :) – BigOmega

Problemi correlati