Aracılığıyla paylaş


CLR tablo biçiminde işlevler

Bir tablo deerli tablo döndüren kullanıcı tanımlı bir işlev işlevidir.

BaşlayarakSQL Server 2005,SQL Servertablo değerli işlevler sağlayarak, yönetilen bir dil. bir tablo değerli işlev tanımlamak işlevselliğini genişletirVeri bir tablo değerli işlev tarafından döndürülen birIEnumerableorIEnumeratornesne.

Not

Tablo değerli işlevler için zaman damgası sütunları veya Unicode olmayan dize veri türü sütunlarındaki dönüş tablo türündeki sütunlar ekleyemezsiniz (örneğin char, varchar, ve text).NOT NULL kısıtlaması desteklenmez.

Transact-SQL ve CLR tablo biçiminde işlevleri arasındaki farklar

Transact-SQL tablo değerli işlevler işlev ara bir tabloya arama sonuçlarını materialize.Bir ara kullandıkları bu yana tablo, bunlar kısıtlamaları ve benzersiz dizin üzerinde sonuçlar destekleyebilir.Büyük sonuçlar verilir, bu özellikleri son derece yararlı olabilir.

Buna karşılık, CLR tablo değerli işlev bir akış yerine temsil eder.sonuçlar kümesinin tamamını tek bir tabloda materialized hiç gereksinim vardır.The IEnumerable object returned by the managed function is directly called by the execution plan of the query that calls the table-valued function, and the results are consumed in an incremental manner.Bu akış modeli hemen ilk satırda doldurulması tüm tablo için beklemek yerine, kullanılabilir sonra sonuçlar tüketilebilir sağlar.Bir bütün olarak bellekte materialized olmadığı için çok sayıda satır döndürdü, varsa, ayrıca daha iyi bir alternatif olduğu.Örneğin, bir metin dosyası ayrıştırma ve her satırı bir satır olarak yönetilen bir tablo değerli işlev kullanılabilir.

Tablo biçiminde işlevler uygulama

Uygula tablo değerli işlev sınıf yöntemleri olarak birMicrosoft.NET framework derleme., Tablo değerli işlev kodu uygulamalıdırIEnumerablearabirim.The IEnumerable interface is defined in the .NET Framework.Temsil eden diziler ve topluluklar .NET Framework uygulamanız zaten yazdığıIEnumerablearabirim.Bu, bir dizi ya da bir sonucu dönüştürme tablo değerli işlevler yazmak için kolaylaştırır küme.

Tablo biçiminde parametreleri

Tablo deerli bir yordam veya işlev iletilir ve veriler birden çok satır sunucuya geçirmek için etkili bir yöntem sağlar, kullanıcı tanımlı tablo türlerini parametreleridir.Parametreleri tablo deerli parametre dizileri, benzer işlevsellik sağlar, ancak daha fazla esneklik ve daha yakın tümleştirmeTransact-SQL.Bunlar da olası en iyi performansı sağlar.Tablo deerli parametreleri yuvarlak başvuru sayısını sunucuya da yardımcı olur.Birden fazla isteği sunucuya göndermek yerine, gibi skaler parametreleri listesini verileri sunucuya bir tablo deerli parametre olarak gönderilebilir., Yönetilen bir saklı yordam iade edilmesi ya da işlev içinde çalışan için bir tablo deerli parametre olarak kullanıcı tanımlı tablo türü geçirilemezSQL Serverişlem.Tablo deerli parametreleri hakkında daha fazla bilgi için bkz:Tablo biçiminde Parametreler (Veritabanı Altyapısı).

Çıktı parametreleri ve tablo biçiminde işlevleri

Çıkış parametreleri kullanan tablo deerli işlevlerden bilgi döndürülebilir.Uygulama kodu tablo değerli işlev ilgili parametresinde bir başvuru parola parametresi bağımsız değişken olarak kullanmanız gerekir.Visual Basic, Visual C# aynı şekilde çıktı parametrelerini desteklemediğini unutmayın., Başvuruya göre parametre kısa olmalıdır ve uygulamanızı<Out()>özniteliğini aşağıdaki gibi bir çıkış parametresi göstermek için:

Imports System.Runtime.InteropServices
…
Public Shared Sub FillRow ( <Out()> ByRef value As SqlInt32)

Tanımlayan bir tablo değerli işlev Transact-SQL

Bir CLR tanımlamak için gerekli sözdizimi tablo değerli işlev olarak benzer birTransact-SQLtablo değerli işlev, birlikteEXTERNAL NAMEyan tümce.Örneğin:

CREATE FUNCTION GetEmpFirstLastNames()
RETURNS TABLE (FirstName NVARCHAR(4000), LastName NVARCHAR(4000))
EXTERNAL NAME MyDotNETAssembly.[MyNamespace.MyClassname]. GetEmpFirstLastNames;

Ayrıntılı sorgular gibi işlemek için ilişkili form içindeki verileri göstermek için kullanılan tablo değerli işlevler:

select * from function();
select * from tbl join function() f on tbl.col = f.col;
select * from table t cross apply function(t.column);

Tablo değerli işlevler tablo dönebilirsiniz:

  • skaler girdi bağımsız değişkenlerini oluşturulur.Örneğin, tablo değerli işlev numaralarını virgülle ayrılmış bir dizi alır ve bunları bir tabloya pivots.

  • Dış veri oluşturulur.Örneğin, bir tablo değerli işlev olay günlüğünü okur ve onu bir tablo olarak sunar.

NotBir tablo değerli işlev bir üzerinden veri erişimi yalnızca gerçekleştirebilirsiniz Transact-SQL, sorgu InitMethodyöntem ve değil FillRowyöntem.The InitMethod should be marked with the SqlFunction.DataAccess.Read attribute property if a Transact-SQL query is performed.

Bir örnek tablo değerli işlev

Aşağıdaki tablo değerli işlev, sistem olay günlüğü ' bilgi verir.işlev Okumak için olay günlüğünü adını içeren bir tek dize baðýmsýz deðiþken alýr.

Örnek kod

using System;
using System.Data.Sql;
using Microsoft.SqlServer.Server;
using System.Collections;
using System.Data.SqlTypes;
using System.Diagnostics;

public class TabularEventLog
{
    [SqlFunction(FillRowMethodName = "FillRow")]
    public static IEnumerable InitMethod(String logname)
    {
        return new EventLog(logname).Entries;    }

    public static void FillRow(Object obj, out SqlDateTime timeWritten, out SqlChars message, out SqlChars category, out long instanceId)
    {
        EventLogEntry eventLogEntry = (EventLogEntry)obj;
        timeWritten = new SqlDateTime(eventLogEntry.TimeWritten);
        message = new SqlChars(eventLogEntry.Message);
        category = new SqlChars(eventLogEntry.Category);
        instanceId = eventLogEntry.InstanceId;
    }
}
Imports System
Imports System.Data.Sql
Imports Microsoft.SqlServer.Server
Imports System.Collections
Imports System.Data.SqlTypes
Imports System.Diagnostics
Imports System.Runtime.InteropServices

Public Class TabularEventLog
    <SqlFunction(FillRowMethodName:="FillRow")> _
    Public Shared Function InitMethod(ByVal logname As String) As IEnumerable
        Return New EventLog(logname).Entries
    End Function

    Public Shared Sub FillRow(ByVal obj As Object, <Out()> ByRef timeWritten As SqlDateTime, <Out()> ByRef message As SqlChars, <Out()> ByRef category As SqlChars, <Out()> ByRef instanceId As Long)
        Dim eventLogEnTry As EventLogEntry = CType(obj, EventLogEntry)
        timeWritten = New SqlDateTime(eventLogEnTry.TimeWritten)
        message = New SqlChars(eventLogEnTry.Message)
        category = New SqlChars(eventLogEnTry.Category)
        instanceId = eventLogEnTry.InstanceId
    End Sub
End Class

Bildirmek ve örnek tablo biçiminde kullanmak işlev

Sonra örnek tablo değerli işlev derlenmiş, bunun bildirilenTransact-SQLaşağıdaki gibi:

use master
-- Replace SQL_Server_logon with your SQL Server user credentials.
GRANT EXTERNAL ACCESS ASSEMBLY TO [SQL_Server_logon] 
-- Modify the following line to specify a different database.
ALTER DATABASE master SET TRUSTWORTHY ON

-- Modify the next line to use the appropriate database.
CREATE ASSEMBLY tvfEventLog 
FROM 'D:\assemblies\tvfEventLog\tvfeventlog.dll' 
WITH PERMISSION_SET = EXTERNAL_ACCESS
GO
CREATE FUNCTION ReadEventLog(@logname nvarchar(100))
RETURNS TABLE 
(logTime datetime,Message nvarchar(4000),Category nvarchar(4000),InstanceId bigint)
AS 
EXTERNAL NAME tvfEventLog.TabularEventLog.InitMethod
GO

Not

BaşlayarakSQL Server 2005, on a"80 oluşturamazsınız" uyumluluk düzey SQL Serververitabanını, kullanıcı tanımlı türler, saklı yordamlar, İşlevler, toplamları veya tetikleyici yönetiliyor. Bu CLR entegrasyonu özelliklerinden yararlanmak için SQL Server, kullanmanız gereken saklı yordamı "100" veritabanı uyumluluk düzeyini ayarlamak için sp_dbcmptlevel .

Not

İle /clr derlenmiş Visual C++ yönetilen veritabanı nesneleri: saf Visual C++ Derleyici seçeneği desteklenmiyor çalıştırılmak üzereSQL Server 2005.Örneğin, tablo değerli işlevler gibi veritabanı nesnelerini içerir.

Örnek, sınama aşağıdakileri deneyinTransact-SQLkodu:

-- Select the top 100 events,
SELECT TOP 100 *
FROM dbo.ReadEventLog(N'Security') as T
go

-- Select the last 10 login events.
SELECT TOP 10 T.logTime, T.Message, T.InstanceId 
FROM dbo.ReadEventLog(N'Security') as T
WHERE T.Category = N'Logon/Logoff'
go

Örnek: Bir SQL Server Query sonuçlar döndürülüyor

Aşağıdaki örnek, sorgu tablo değerli işlev gösterir birSQL Serververitabanı.Bu örnek AdventureWorks açık veritabanından kullanırSQL Server 2008.Bkz:https://www.codeplex.com/sqlserversamples daha fazla bilgi yükleme AdventureWorks.

FindInvalidEmails.cs veya FindInvalidEmails.vb kaynak kodu dosyası adı.

using System;
using System.Collections;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;

using Microsoft.SqlServer.Server;

public partial class UserDefinedFunctions {
   private class EmailResult {
      public SqlInt32 CustomerId;
      public SqlString EmailAdress;

      public EmailResult(SqlInt32 customerId, SqlString emailAdress) {
         CustomerId = customerId;
         EmailAdress = emailAdress;
      }
   }

   public static bool ValidateEmail(SqlString emailAddress) {
      if (emailAddress.IsNull)
         return false;

      if (!emailAddress.Value.EndsWith("@adventure-works.com"))
         return false;

      // Validate the address. Put any more rules here.
      return true;
   }

   [SqlFunction(
       DataAccess = DataAccessKind.Read,
       FillRowMethodName = "FindInvalidEmails_FillRow")]
   public static IEnumerable FindInvalidEmails(SqlDateTime modifiedSince) {
      ArrayList resultCollection = new ArrayList();

      using (SqlConnection connection = new SqlConnection("context connection=true")) {
         connection.Open();

         using (SqlCommand selectEmails = new SqlCommand(
             "SELECT " +
             "[CustomerID], [EmailAddress] " +
             "FROM [AdventureWorksLT2008].[SalesLT].[Customer] " +
             "WHERE [ModifiedDate] >= @modifiedSince",
             connection)) {
            SqlParameter modifiedSinceParam = selectEmails.Parameters.Add(
                "@modifiedSince",
                SqlDbType.DateTime);
            modifiedSinceParam.Value = modifiedSince;

            using (SqlDataReader emailsReader = selectEmails.ExecuteReader()) {
               while (emailsReader.Read()) {
                  SqlString emailAddress = emailsReader.GetSqlString(1);
                  if (ValidateEmail(emailAddress)) {
                     resultCollection.Add(new EmailResult(
                         emailsReader.GetSqlInt32(0),
                         emailAddress));
                  }
               }
            }
         }
      }

      return resultCollection;
   }

   public static void FindInvalidEmails_FillRow(
       object emailResultObj,
       out SqlInt32 customerId,
       out SqlString emailAdress) {
      EmailResult emailResult = (EmailResult)emailResultObj;

      customerId = emailResult.CustomerId;
      emailAdress = emailResult.EmailAdress;
   }
};
Imports Microsoft.SqlServer.Server
Imports System
Imports System.Collections
Imports System.Data
Imports System.Data.SqlClient
Imports System.Data.SqlTypes
Imports System.Runtime.InteropServices

Public Class UserDefinedFunctions
   <SqlFunction(DataAccess:=DataAccessKind.Read, FillRowMethodName:="FindInvalidEmails_FillRow")> _
   Public Shared Function FindInvalidEmails(ByVal modifiedSince As SqlDateTime) As IEnumerable
      Dim resultCollection As New ArrayList
      Using connection As SqlConnection = New SqlConnection("context connection=true")
         connection.Open()
         Using selectEmails As SqlCommand = New SqlCommand("SELECT [CustomerID], [EmailAddress] FROM [AdventureWorksLT2008].[SalesLT].[Customer] WHERE [ModifiedDate] >= @modifiedSince", connection)
            selectEmails.Parameters.Add("@modifiedSince", SqlDbType.DateTime).Value = modifiedSince
            Using emailsReader As SqlDataReader = selectEmails.ExecuteReader
               Do While emailsReader.Read
                  Dim emailAddress As SqlString = emailsReader.GetSqlString(1)
                  If UserDefinedFunctions.ValidateEmail(emailAddress) Then
                     resultCollection.Add(New EmailResult(emailsReader.GetSqlInt32(0), emailAddress))
                  End If
               Loop
            End Using
            Return resultCollection
         End Using
      End Using
   End Function

   Public Shared Sub FindInvalidEmails_FillRow(ByVal emailResultObj As Object, <Out()> ByRef customerId As SqlInt32, <Out()> ByRef emailAdress As SqlString)
      Dim emailResult As EmailResult = DirectCast(emailResultObj, EmailResult)
      customerId = emailResult.CustomerId
      emailAdress = emailResult.EmailAdress
   End Sub

   Public Shared Function ValidateEmail(ByVal emailAddress As SqlString) As Boolean
      If emailAddress.IsNull Then
         Return False
      End If
      If Not emailAddress.Value.EndsWith("@adventure-works.com") Then
         Return False
      End If
      Return True
   End Function

   Private Class EmailResult
      Public Sub New(ByVal customerId As SqlInt32, ByVal emailAdress As SqlString)
         Me.CustomerId = customerId
         Me.EmailAdress = emailAdress
      End Sub

      Public CustomerId As SqlInt32
      Public EmailAdress As SqlString
   End Class
End Class

Bir DLL dosyası için kaynak kodu derleyin ve DLL C sürücünüzün kök dizinine kopyalayın.Daha sonra aşağıdaki yürütmekTransact-SQLsorgu.

use AdventureWorksLT2008
go

IF EXISTS (SELECT name FROM sysobjects WHERE name = 'FindInvalidEmails')
   DROP FUNCTION FindInvalidEmails
go

IF EXISTS (SELECT name FROM sys.assemblies WHERE name = 'MyClrCode')
   DROP ASSEMBLY MyClrCode
go

CREATE ASSEMBLY MyClrCode FROM 'C:\FindInvalidEmails.dll'
WITH PERMISSION_SET = SAFE -- EXTERNAL_ACCESS
GO

CREATE FUNCTION FindInvalidEmails(@ModifiedSince datetime) 
RETURNS TABLE (
   CustomerId int,
   EmailAddress nvarchar(4000)
)
AS EXTERNAL NAME MyClrCode.UserDefinedFunctions.[FindInvalidEmails]
go

SELECT * FROM FindInvalidEmails('2000-01-01')
go

Değişiklik Geçmişi

Güncelleştirilmiş içerik

Bir SQL sorgusuna gösteren bir örnek eklendi.

See Also

Other Resources