Aracılığıyla paylaş


clr Tetikleyicileri

Çünkü SQL Serverile entegrasyon .NET Frameworkortak dil çalışma zamanı (clr) kullanabilirsiniz .NET Frameworkclr oluşturma dili tetikler. Bu bölüm Tetikleyicileri clr entegrasyonu ile uygulamaya özgü bilgileri kapsar. Bkz: Tetikleyiciler tam bir tartışma için dml Tetikleyicilerive ddl Tetikleyicileri.

Ne tetikler?

Tetikleyici bir dil olay çalıştırıldığında otomatik olarak çalıştırır saklı yordam özel bir türüdür. SQL ServerGenel tür iki: Tetikleyiciler içerir: veri düzenleme dili (dml) ve veri tanım dili (ddl) Tetikleyicileri. dml tetikleyici olabilir zaman kullanılan INSERT, UPDATE, ya DELETEdeyimleri belirtilen tablo veya görünümü veri değiştirmek. ddl Tetikleyiciler ateşlenmesine yanıt olarak öncelikle başlayan deyimleri ddl deyimleri çeşitli saklı yordamlar CREATE, ALTER, ve DROP. ddl Tetikleyicileri, Denetim ve veritabanı işlemleri düzenleyen gibi yönetimsel görevler için kullanılabilir.

clr Tetikleyicileri benzersiz yetenekleri

Tetikleyiciler yazılı Transact-SQLkullanarak firing görünüm veya tablo sütunları güncelleştirilen belirleme yeteneğine sahip UPDATE(column)ve COLUMNS_UPDATED()işlevleri.

Bir clr dilinde yazılmış Tetikleyiciler diğer clr tümleştirme nesnelerden birçok önemli farklar. clr Tetikleyicileri yapabilirsiniz:

  • Başvuru veri INSERTEDve DELETEDtabloları

  • Sonucunda hangi sütunların değiştirilmiş belirlemek bir UPDATEişlemi

  • ddl deyimleri yürütme tarafından etkilenen veritabanı nesneleri hakkında bilgilere erişmek.

Bu yetenekler doğuştan sorgu dili veya tarafından sağlanan SqlTriggerContextsınıf clr tümleştirme ve yönetilen kod arasında seçim avantajları hakkında bilgi ve Transact-SQL, bakın clr tümleştirme genel bakış.

SqlTriggerContext sınıf kullanma

SqlTriggerContextSınıf halka oluşturulamıyor ve sadece erişim sağlayarak elde edilebilir SqlContext.TriggerContextözelliği clr tetikleyici gövdesi içinde. SqlTriggerContextSınıf etkin elde edilebilir SqlContextçağırarak SqlContext.TriggerContextözelliği:

SqlTriggerContext myTriggerContext = SqlContext.TriggerContext;

SqlTriggerContextSınıfı sağlar bağlam bilgileri tetikleyici hakkında. Bu bağlamsal bilgiler hangi sütunların güncellenmiştir, ddl tetikleyici, xml ve, güncelleştirme işleminde tetikleyici ateşlenmesine, neden eylem türünü içerir EventDatatetikleme işlemi açıklayan yapısı. Daha fazla bilgi için, bkz. eventdata (Transact-sql).

Tetikleyici eylem belirleme

Sen aldıktan sonra bir SqlTriggerContext, tetikleyici ateşlenmesine neden olan eylem türünü belirlemek için kullanabilirsiniz. Bu bilgiler aracılığıyla TriggerActionözelliği SqlTriggerContextsınıf

dml Tetikleyiciler, TriggerActionözelliği aşağıdaki değerlerden biri olabilir:

  • TriggerAction.Update (0x1)

  • TriggerAction.Insert (0x2)

  • TriggerAction.Delete(0x3)

  • ddl Tetikleyiciler için mümkün TriggerAction değerler listesi epeyce uzundur. Lütfen "TriggerAction numaralandırma" konusuna bakın. İçinde.Daha fazla bilgi için net Framework sdk.

Eklenen ve silinen tabloları kullanarak

İki özel tablolar dml tetikleyici deyimleri kullanılır: takılı tablo ve silindi tablosu. SQL Serverotomatik olarak oluşturur ve bu tabloları yönetir. Bu geçici tablolar, belirli veri değişiklikleri sınama ve dml tetikleyici eylemler için koşullar kullanabilirsiniz; Ancak, tablolardaki verileri doğrudan değişiklik yapamazsınız.

clr Tetikleyicileri erişebilir takılı ve silindi tablolar clr işlem sağlayıcısı aracılığıyla. Bu alarak yapılır bir SqlCommandSqlContext nesne nesneden. Örneğin:

C#

SqlConnection connection = new SqlConnection ("context connection = true");
connection.Open();
SqlCommand command = connection.CreateCommand();
command.CommandText = "SELECT * from " + "inserted";

SqlConnection connection = new SqlConnection ("context connection = true");
connection.Open();
SqlCommand command = connection.CreateCommand();
command.CommandText = "SELECT * from " + "inserted";

Visual Basic

Dim connection As New SqlConnection("context connection=true")
Dim command As SqlCommand
connection.Open()
command = connection.CreateCommand()
command.CommandText = "SELECT * FROM " + "inserted"

Dim connection As New SqlConnection("context connection=true")
Dim command As SqlCommand
connection.Open()
command = connection.CreateCommand()
command.CommandText = "SELECT * FROM " + "inserted"

Güncellenme Zamanı sütunlar belirleme

Kullanarak güncelleştirme işlemi tarafından değiştirilen sütun sayısını belirlemek için ColumnCountözelliği SqlTriggerContextnesnesini. Sen-ebilmek kullanma IsUpdatedColumnsütun sütun güncelleştirilmiş olup olmadığını belirlemek için giriş parametresi, sıra yöntemini. A Truedeğeri, sütunun güncelleştirildiğini gösterir.

Örneğin, bu kod parçacığını (den bu konunun ilerleyen bölümlerinde create trigger) updated sütunları listeler:

C#

reader = command.ExecuteReader();
reader.Read();
for (int columnNumber = 0; columnNumber < triggContext.ColumnCount; columnNumber++)
{
   pipe.Send("Updated column "
      + reader.GetName(columnNumber) + "? "
   + triggContext.IsUpdatedColumn(columnNumber).ToString());
 }

 reader.Close();

reader = command.ExecuteReader();
reader.Read();
for (int columnNumber = 0; columnNumber < triggContext.ColumnCount; columnNumber++)
{
   pipe.Send("Updated column "
      + reader.GetName(columnNumber) + "? "
   + triggContext.IsUpdatedColumn(columnNumber).ToString());
 }

 reader.Close();

Visual Basic

reader = command.ExecuteReader()
reader.Read()
Dim columnNumber As Integer

For columnNumber=0 To triggContext.ColumnCount-1

   pipe.Send("Updated column " & reader.GetName(columnNumber) & _
   "? " & triggContext.IsUpdatedColumn(columnNumber).ToString() )
                 
Next

reader.Close()

reader = command.ExecuteReader()
reader.Read()
Dim columnNumber As Integer

For columnNumber=0 To triggContext.ColumnCount-1

   pipe.Send("Updated column " & reader.GetName(columnNumber) & _
   "? " & triggContext.IsUpdatedColumn(columnNumber).ToString() )
                 
Next

reader.Close()

clr ddl Tetikleyicileri EventData erişme

Bir olaya yanıt olarak saklı yordamlar gibi normal Tetikleyiciler ddl Tetikleyiciler yangın. Ancak dml Tetikleyiciler, onlar değil ateş-e yanıt-e doğru GÜNCELLEŞTİRMEK, INSERT veya delete deyimleri bir tablo veya Görünüm içinde. Bunun yerine, yanıt olarak öncelikle create, alter ve damla ile başlayan deyimleri ddl deyimleri çeşitli yangın. ddl Tetikleyicileri, Denetim ve veritabanı işlemleri ve şema değişiklikleri izlemenin gibi yönetimsel görevler için kullanılabilir.

ddl tetikleyici harekete olay hakkında bilgi mevcut EventDataözelliği SqlTriggerContextsınıf Bu özelliği içeren bir xmldeğer. Xml şeması hakkında bilgi içerir:

  • Olay saati.

  • Sistem işlem Kımlığı (SPID) sırasında tetikleyici yürütülen bağlantı.

  • Tetikleyici harekete olay türü.

Daha sonra olay türüne bağlı olarak, şema olayın oluştuğu, veritabanı karşı olayın oluştuğu, nesne gibi ek bilgileri içerir ve Transact-SQLkomut olay.

Aşağıdaki örnekte, aşağıdaki ddl tetikleyici döndürür ham EventDataözellik.

[!NOT]

Sonuçlar ve aracılığıyla mesaj gönderme SqlPipenesnesi yalnızca açıklayıcı amacıyla gösterilir ve üretim kodu programlama clr Tetikleyiciler için genellikle önerilmez. Döndürülen ek verileri beklenmeyen ve kurşun için uygulama hataları olabilir.

C#

using System;
using System.Data;
using System.Data.Sql;
using Microsoft.SqlServer.Server;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Xml;
using System.Text.RegularExpressions;

public class CLRTriggers
{
   public static void DropTableTrigger()
   {
       SqlTriggerContext triggContext = SqlContext.TriggerContext;           

       switch(triggContext.TriggerAction)
       {
           case TriggerAction.DropTable:
           SqlContext.Pipe.Send("Table dropped! Here's the EventData:");
           SqlContext.Pipe.Send(triggContext.EventData.Value);
           break;
                
           default:
           SqlContext.Pipe.Send("Something happened! Here's the EventData:");
           SqlContext.Pipe.Send(triggContext.EventData.Value);
           break;
       }
   }
}

using System;
using System.Data;
using System.Data.Sql;
using Microsoft.SqlServer.Server;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Xml;
using System.Text.RegularExpressions;

public class CLRTriggers
{
   public static void DropTableTrigger()
   {
       SqlTriggerContext triggContext = SqlContext.TriggerContext;           

       switch(triggContext.TriggerAction)
       {
           case TriggerAction.DropTable:
           SqlContext.Pipe.Send("Table dropped! Here's the EventData:");
           SqlContext.Pipe.Send(triggContext.EventData.Value);
           break;
                
           default:
           SqlContext.Pipe.Send("Something happened! Here's the EventData:");
           SqlContext.Pipe.Send(triggContext.EventData.Value);
           break;
       }
   }
}

Visual Basic

Imports System
Imports System.Data
Imports System.Data.Sql
Imports System.Data.SqlTypes
Imports Microsoft.SqlServer.Server
Imports System.Data.SqlClient

'The Partial modifier is only required on one class definition per project.
Partial Public Class CLRTriggers 
    
    Public Shared Sub DropTableTrigger()
        Dim triggContext As SqlTriggerContext
        triggContext = SqlContext.TriggerContext

        Select Case triggContext.TriggerAction
           Case TriggerAction.DropTable
              SqlContext.Pipe.Send("Table dropped! Here's the EventData:")
              SqlContext.Pipe.Send(triggContext.EventData.Value)

           Case Else
              SqlContext.Pipe.Send("Something else happened! Here's the EventData:")
              SqlContext.Pipe.Send(triggContext.EventData.Value)
        
        End Select
    End Sub
End Class   
Imports System
Imports System.Data
Imports System.Data.Sql
Imports System.Data.SqlTypes
Imports Microsoft.SqlServer.Server
Imports System.Data.SqlClient

'The Partial modifier is only required on one class definition per project.
Partial Public Class CLRTriggers 
    
    Public Shared Sub DropTableTrigger()
        Dim triggContext As SqlTriggerContext
        triggContext = SqlContext.TriggerContext

        Select Case triggContext.TriggerAction
           Case TriggerAction.DropTable
              SqlContext.Pipe.Send("Table dropped! Here's the EventData:")
              SqlContext.Pipe.Send(triggContext.EventData.Value)

           Case Else
              SqlContext.Pipe.Send("Something else happened! Here's the EventData:")
              SqlContext.Pipe.Send(triggContext.EventData.Value)
        
        End Select
    End Sub
End Class   

Aşağıdaki örnek çıkış EventDataözellik değeri tarafından ateş ddl tetikleyici sonra bir CREATE TABLEolayı:

<EVENT_INSTANCE><PostTime>2004-04-16T21:17:16.160</PostTime><SPID>58</SPID><EventType>CREATE_TABLE</EventType><ServerName>MACHINENAME</ServerName><LoginName>MYDOMAIN\myname</LoginName><UserName>MYDOMAIN\myname</UserName><DatabaseName>AdventureWorks</DatabaseName><SchemaName>dbo</SchemaName><ObjectName>UserName</ObjectName><ObjectType>TABLE</ObjectType><TSQLCommand><SetOptions ANSI_NULLS="ON" ANSI_NULL_DEFAULT="ON" ANSI_PADDING="ON" QUOTED_IDENTIFIER="ON" ENCRYPTED="FALSE" /><CommandText>create table dbo.UserName&#x0D;&#x0A;(&#x0D;&#x0A; UserName varchar(50),&#x0D;&#x0A; RealName varchar(50)&#x0D;&#x0A;)&#x0D;&#x0A;</CommandText></TSQLCommand></EVENT_INSTANCE>

Üzerinden erişilebilir bilgilere ek olarak SqlTriggerContextsınıfı sorgu hala gelebilir COLUMNS_UPDATEDve eklenen/silinmiş bir komut metni içinde yürütülen işlem.

Örnek clr tetikleyici

Bu örnekte, istedikleri herhangi bir kimlik seçin kullanıcı izin vermek senaryoyu düşünün, ama özellikle bir e-posta adresi kimliği girilen kullanıcı bilmek istiyorum Aşağıdaki tetikleyici bilgileri algılar ve bir denetim tabloya oturum.

[!NOT]

Sonuçlar ve aracılığıyla mesaj gönderme SqlPipenesnesi yalnızca açıklayıcı amacıyla gösterilir ve üretim kodu genellikle önerilmez. Döndürülen ek verileri beklenmeyen ve kurşun için uygulama hataları olabilir

using System;
using System.Data;
using System.Data.Sql;
using Microsoft.SqlServer.Server;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Xml;
using System.Text.RegularExpressions;

public class CLRTriggers
{
   [SqlTrigger(Name = @"EmailAudit", Target = "[dbo].[Users]", Event = "FOR INSERT, UPDATE, DELETE")]
   public static void EmailAudit()
   {
      string userName;
      string realName;
      SqlCommand command;
      SqlTriggerContext triggContext = SqlContext.TriggerContext;
      SqlPipe pipe = SqlContext.Pipe;
      SqlDataReader reader;

      switch (triggContext.TriggerAction)
      {
         case TriggerAction.Insert:
         // Retrieve the connection that the trigger is using
         using (SqlConnection connection
            = new SqlConnection(@"context connection=true"))
         {
            connection.Open();
            command = new SqlCommand(@"SELECT * FROM INSERTED;",
               connection);
            reader = command.ExecuteReader();
            reader.Read();
            userName = (string)reader[0];
            realName = (string)reader[1];
            reader.Close();

            if (IsValidEMailAddress(userName))
            {
               command = new SqlCommand(
                  @"INSERT [dbo].[UserNameAudit] VALUES ('"
                  + userName + @"', '" + realName + @"');",
                  connection);
               pipe.Send(command.CommandText);
               command.ExecuteNonQuery();
               pipe.Send("You inserted: " + userName);
            }
         }

         break;

         case TriggerAction.Update:
         // Retrieve the connection that the trigger is using
         using (SqlConnection connection
            = new SqlConnection(@"context connection=true"))
         {
            connection.Open();
            command = new SqlCommand(@"SELECT * FROM INSERTED;",
               connection);
            reader = command.ExecuteReader();
            reader.Read();

            userName = (string)reader[0];
            realName = (string)reader[1];

            pipe.Send(@"You updated: '" + userName + @"' - '"
               + realName + @"'");

            for (int columnNumber = 0; columnNumber < triggContext.ColumnCount; columnNumber++)
            {
               pipe.Send("Updated column "
                  + reader.GetName(columnNumber) + "? "
                  + triggContext.IsUpdatedColumn(columnNumber).ToString());
            }

            reader.Close();
         }

         break;

         case TriggerAction.Delete:
            using (SqlConnection connection
               = new SqlConnection(@"context connection=true"))
               {
                  connection.Open();
                  command = new SqlCommand(@"SELECT * FROM DELETED;",
                     connection);
                  reader = command.ExecuteReader();

                  if (reader.HasRows)
                  {
                     pipe.Send(@"You deleted the following rows:");
                     while (reader.Read())
                     {
                        pipe.Send(@"'" + reader.GetString(0)
                        + @"', '" + reader.GetString(1) + @"'");
                     }

                     reader.Close();

                     //alternately, to just send a tabular resultset back:
                     //pipe.ExecuteAndSend(command);
                  }
                  else
                  {
                     pipe.Send("No rows affected.");
                  }
               }

               break;
            }
        }

     public static bool IsValidEMailAddress(string email)
     {
         return Regex.IsMatch(email, @"^([\w-]+\.)*?[\w-]+@[\w-]+\.([\w-]+\.)*?[\w]+$");
     }
}
using System;
using System.Data;
using System.Data.Sql;
using Microsoft.SqlServer.Server;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Xml;
using System.Text.RegularExpressions;

public class CLRTriggers
{
   [SqlTrigger(Name = @"EmailAudit", Target = "[dbo].[Users]", Event = "FOR INSERT, UPDATE, DELETE")]
   public static void EmailAudit()
   {
      string userName;
      string realName;
      SqlCommand command;
      SqlTriggerContext triggContext = SqlContext.TriggerContext;
      SqlPipe pipe = SqlContext.Pipe;
      SqlDataReader reader;

      switch (triggContext.TriggerAction)
      {
         case TriggerAction.Insert:
         // Retrieve the connection that the trigger is using
         using (SqlConnection connection
            = new SqlConnection(@"context connection=true"))
         {
            connection.Open();
            command = new SqlCommand(@"SELECT * FROM INSERTED;",
               connection);
            reader = command.ExecuteReader();
            reader.Read();
            userName = (string)reader[0];
            realName = (string)reader[1];
            reader.Close();

            if (IsValidEMailAddress(userName))
            {
               command = new SqlCommand(
                  @"INSERT [dbo].[UserNameAudit] VALUES ('"
                  + userName + @"', '" + realName + @"');",
                  connection);
               pipe.Send(command.CommandText);
               command.ExecuteNonQuery();
               pipe.Send("You inserted: " + userName);
            }
         }

         break;

         case TriggerAction.Update:
         // Retrieve the connection that the trigger is using
         using (SqlConnection connection
            = new SqlConnection(@"context connection=true"))
         {
            connection.Open();
            command = new SqlCommand(@"SELECT * FROM INSERTED;",
               connection);
            reader = command.ExecuteReader();
            reader.Read();

            userName = (string)reader[0];
            realName = (string)reader[1];

            pipe.Send(@"You updated: '" + userName + @"' - '"
               + realName + @"'");

            for (int columnNumber = 0; columnNumber < triggContext.ColumnCount; columnNumber++)
            {
               pipe.Send("Updated column "
                  + reader.GetName(columnNumber) + "? "
                  + triggContext.IsUpdatedColumn(columnNumber).ToString());
            }

            reader.Close();
         }

         break;

         case TriggerAction.Delete:
            using (SqlConnection connection
               = new SqlConnection(@"context connection=true"))
               {
                  connection.Open();
                  command = new SqlCommand(@"SELECT * FROM DELETED;",
                     connection);
                  reader = command.ExecuteReader();

                  if (reader.HasRows)
                  {
                     pipe.Send(@"You deleted the following rows:");
                     while (reader.Read())
                     {
                        pipe.Send(@"'" + reader.GetString(0)
                        + @"', '" + reader.GetString(1) + @"'");
                     }

                     reader.Close();

                     //alternately, to just send a tabular resultset back:
                     //pipe.ExecuteAndSend(command);
                  }
                  else
                  {
                     pipe.Send("No rows affected.");
                  }
               }

               break;
            }
        }

     public static bool IsValidEMailAddress(string email)
     {
         return Regex.IsMatch(email, @"^([\w-]+\.)*?[\w-]+@[\w-]+\.([\w-]+\.)*?[\w]+$");
     }
}

Visual Basic

Imports System
Imports System.Data
Imports System.Data.Sql
Imports System.Data.SqlTypes
Imports Microsoft.SqlServer.Server
Imports System.Data.SqlClient
Imports System.Text.RegularExpressions

'The Partial modifier is only required on one class definition per project.
Partial Public Class CLRTriggers 
    
    <SqlTrigger(Name:="EmailAudit", Target:="[dbo].[Users]", Event:="FOR INSERT, UPDATE, DELETE")> _
    Public Shared Sub EmailAudit()
        Dim userName As String
        Dim realName As String
        Dim command As SqlCommand
        Dim triggContext As SqlTriggerContext
        Dim pipe As SqlPipe
        Dim reader As SqlDataReader  

        triggContext = SqlContext.TriggerContext    
        pipe = SqlContext.Pipe  

        Select Case triggContext.TriggerAction
           Case TriggerAction.Insert
              Using connection As New SqlConnection("context connection=true")
                 connection.Open()
                 command = new SqlCommand("SELECT * FROM INSERTED;", connection)
                            
                 reader = command.ExecuteReader()
                 reader.Read()

                 userName = CType(reader(0), String)
                 realName = CType(reader(1), String)

                 reader.Close()

                 If IsValidEmailAddress(userName) Then
                     command = New SqlCommand("INSERT [dbo].[UserNameAudit] VALUES ('" & _
                       userName & "', '" & realName & "');", connection)
                 
                    pipe.Send(command.CommandText)
                    command.ExecuteNonQuery()
                    pipe.Send("You inserted: " & userName)

                 End If
              End Using
              
           Case TriggerAction.Update
              Using connection As New SqlConnection("context connection=true")
                 connection.Open()
                 command = new SqlCommand("SELECT * FROM INSERTED;", connection)
                            
                 reader = command.ExecuteReader()
                 reader.Read()

                 userName = CType(reader(0), String)
                 realName = CType(reader(1), String)
                
                 pipe.Send("You updated: " & userName & " - " & realName)

                 Dim columnNumber As Integer

                 For columnNumber=0 To triggContext.ColumnCount-1

                    pipe.Send("Updated column " & reader.GetName(columnNumber) & _
                      "? " & triggContext.IsUpdatedColumn(columnNumber).ToString() )
                 
                 Next

                 reader.Close()
              End Using

           Case TriggerAction.Delete
              Using connection As New SqlConnection("context connection=true")
                 connection.Open()
                 command = new SqlCommand("SELECT * FROM DELETED;", connection)
                            
                 reader = command.ExecuteReader()
   
                 If reader.HasRows Then
                    pipe.Send("You deleted the following rows:")

                    While reader.Read()

                       pipe.Send( reader.GetString(0) & ", " & reader.GetString(1) )
                       
                    End While 
                    
                    reader.Close()

                    ' Alternately, just send a tabular resultset back:
                    ' pipe.ExecuteAndSend(command)

                 Else
                   pipe.Send("No rows affected.")
                 End If
              
              End Using 
        End Select
    End Sub

    Public Shared Function IsValidEMailAddress(emailAddress As String) As Boolean

       return Regex.IsMatch(emailAddress, "^([\w-]+\.)*?[\w-]+@[\w-]+\.([\w-]+\.)*?[\w]+$")
    End Function    
End Class

Imports System
Imports System.Data
Imports System.Data.Sql
Imports System.Data.SqlTypes
Imports Microsoft.SqlServer.Server
Imports System.Data.SqlClient
Imports System.Text.RegularExpressions

'The Partial modifier is only required on one class definition per project.
Partial Public Class CLRTriggers 
    
    <SqlTrigger(Name:="EmailAudit", Target:="[dbo].[Users]", Event:="FOR INSERT, UPDATE, DELETE")> _
    Public Shared Sub EmailAudit()
        Dim userName As String
        Dim realName As String
        Dim command As SqlCommand
        Dim triggContext As SqlTriggerContext
        Dim pipe As SqlPipe
        Dim reader As SqlDataReader  

        triggContext = SqlContext.TriggerContext    
        pipe = SqlContext.Pipe  

        Select Case triggContext.TriggerAction
           Case TriggerAction.Insert
              Using connection As New SqlConnection("context connection=true")
                 connection.Open()
                 command = new SqlCommand("SELECT * FROM INSERTED;", connection)
                            
                 reader = command.ExecuteReader()
                 reader.Read()

                 userName = CType(reader(0), String)
                 realName = CType(reader(1), String)

                 reader.Close()

                 If IsValidEmailAddress(userName) Then
                     command = New SqlCommand("INSERT [dbo].[UserNameAudit] VALUES ('" & _
                       userName & "', '" & realName & "');", connection)
                 
                    pipe.Send(command.CommandText)
                    command.ExecuteNonQuery()
                    pipe.Send("You inserted: " & userName)

                 End If
              End Using
              
           Case TriggerAction.Update
              Using connection As New SqlConnection("context connection=true")
                 connection.Open()
                 command = new SqlCommand("SELECT * FROM INSERTED;", connection)
                            
                 reader = command.ExecuteReader()
                 reader.Read()

                 userName = CType(reader(0), String)
                 realName = CType(reader(1), String)
                
                 pipe.Send("You updated: " & userName & " - " & realName)

                 Dim columnNumber As Integer

                 For columnNumber=0 To triggContext.ColumnCount-1

                    pipe.Send("Updated column " & reader.GetName(columnNumber) & _
                      "? " & triggContext.IsUpdatedColumn(columnNumber).ToString() )
                 
                 Next

                 reader.Close()
              End Using

           Case TriggerAction.Delete
              Using connection As New SqlConnection("context connection=true")
                 connection.Open()
                 command = new SqlCommand("SELECT * FROM DELETED;", connection)
                            
                 reader = command.ExecuteReader()
   
                 If reader.HasRows Then
                    pipe.Send("You deleted the following rows:")

                    While reader.Read()

                       pipe.Send( reader.GetString(0) & ", " & reader.GetString(1) )
                       
                    End While 
                    
                    reader.Close()

                    ' Alternately, just send a tabular resultset back:
                    ' pipe.ExecuteAndSend(command)

                 Else
                   pipe.Send("No rows affected.")
                 End If
              
              End Using 
        End Select
    End Sub

    Public Shared Function IsValidEMailAddress(emailAddress As String) As Boolean

       return Regex.IsMatch(emailAddress, "^([\w-]+\.)*?[\w-]+@[\w-]+\.([\w-]+\.)*?[\w]+$")
    End Function    
End Class

Assuming iki tablo ile aşağıdaki tanımları bulunur:

CREATE TABLE Users
(
    UserName nvarchar(200) NOT NULL,
    RealName nvarchar(200) NOT NULL
);
GO CREATE TABLE UserNameAudit
(
    UserName nvarchar(200) NOT NULL,
    RealName nvarchar(200) NOT NULL
)

CREATE TABLE Users
(
    UserName nvarchar(200) NOT NULL,
    RealName nvarchar(200) NOT NULL
);
GO CREATE TABLE UserNameAudit
(
    UserName nvarchar(200) NOT NULL,
    RealName nvarchar(200) NOT NULL
)

Transact-SQLDeyimi tetikleyici oluşturur SQL Servergibidir ve derleme varsayar create zaten mevcut kayıtlı SQL Serververitabanı.

CREATE TRIGGER EmailAudit
ON Users
FOR INSERT, UPDATE, DELETE
AS
EXTERNAL NAME SQLCLRTest.CLRTriggers.EmailAudit

CREATE TRIGGER EmailAudit
ON Users
FOR INSERT, UPDATE, DELETE
AS
EXTERNAL NAME SQLCLRTest.CLRTriggers.EmailAudit

Doğrulama ve geçersiz işlemleri iptal ediliyor

Doğrulamak ve geçersiz INSERT, update veya delete işlemleri iptal etmek için ya da sizin veritabanı şema değişiklikleri önlemek için Tetikleyicileri kullanma yaygındır. Bu doğrulama mantığını Tetikleyiciniz birleşmeyle ve eylem geçerlilik ölçütleri karşılamıyorsa geçerli işlem geri alınması sağlanabilir.

Bir tetikleyici içinde çağrıldığında Transaction.Rollbackyöntemini veya bir SqlCommand komut metni "hareketi geri alma" belirsiz hata iletisiyle bir istisna atar ve bir try/catch bloğu içinde alınmalıdır. Gördüğünüz hata iletisi aşağıdakine benzer:

Msg 6549, Level 16, State 1, Procedure trig_InsertValidator, Line 0
A .NET Framework error occurred during execution of user defined routine or aggregate 'trig_InsertValidator': 
System.Data.SqlClient.SqlException: Transaction is not allowed to roll back inside a user defined routine, trigger or aggregate because the transaction is not started in that CLR level. Change application logic to enforce strict transaction nesting… User transaction, if any, will be rolled back.

Msg 6549, Level 16, State 1, Procedure trig_InsertValidator, Line 0
A .NET Framework error occurred during execution of user defined routine or aggregate 'trig_InsertValidator': 
System.Data.SqlClient.SqlException: Transaction is not allowed to roll back inside a user defined routine, trigger or aggregate because the transaction is not started in that CLR level. Change application logic to enforce strict transaction nesting… User transaction, if any, will be rolled back.

Try/catch bloğu kod yürütülmesine devam etmek gerekli olan ve bu özel durum bekleniyor. Tetikleyici kod yürütme tamamlandığında, başka bir özel durum oluşturuldu

Msg 3991, Level 16, State 1, Procedure trig_InsertValidator, Line 1 
The context transaction which was active before entering user defined routine, trigger or aggregate "trig_InsertValidator" has been ended inside of it, which is not allowed. Change application logic to enforce strict transaction nesting.
The statement has been terminated.

Msg 3991, Level 16, State 1, Procedure trig_InsertValidator, Line 1 
The context transaction which was active before entering user defined routine, trigger or aggregate "trig_InsertValidator" has been ended inside of it, which is not allowed. Change application logic to enforce strict transaction nesting.
The statement has been terminated.

Bu durum da beklenen ve çevresinde bir try/catch bloğu Transact-SQLtetiği harekete eylemi gerçekleştiren deyimi gerekli yürütme devam edebilmesi. Rağmen atılan iki özel durumları, işlem geri alınır ve değişiklikleri tabloya bağımlı değildir. clr Tetikleyicileri arasında önemli bir fark ve Transact-SQLtetikleyici olduğunu Transact-SQLTetikleyiciler işlem geri alınır sonra daha fazla iş yapmaya devam.

Örnek

Aşağıdaki tetikleyici bir tabloda INSERT deyimleri basit doğrulama gerçekleştirir. Eklenmiş tamsayı değeri bire eşit ise, işlem geri alınır ve değer tablosuna eklenmez. Diğer tüm tamsayı değerleri tabloya eklenir. Not try/catch bloğu etrafında Transaction.Rollbackyöntemi. Transact-SQLKomut dosyası, bir sınama tablosu, derleme ve yönetilen saklı yordam oluşturur. Not Böylece tetikleyici yürütme tamamlandığında istisna yakalanan iki INSERT deyimleri, bir try/catch bloğu içinde sarılmış bulunmaktadır.

C#

using System;
using System.Data.SqlClient;
using Microsoft.SqlServer.Server;
using System.Transactions;

public partial class Triggers
{
    // Enter existing table or view for the target and uncomment the attribute line
    // [Microsoft.SqlServer.Server.SqlTrigger (Name="trig_InsertValidator", Target="Table1", Event="FOR INSERT")]
    public static void trig_InsertValidator()
    {
        using (SqlConnection connection = new SqlConnection(@"context connection=true"))
        {
            SqlCommand command;
            SqlDataReader reader;
            int value;

            // Open the connection.
            connection.Open();
            
            // Get the inserted value.
            command = new SqlCommand(@"SELECT * FROM INSERTED", connection);
            reader = command.ExecuteReader();
            reader.Read();
            value = (int)reader[0];
            reader.Close();
            
            // Rollback the transaction if a value of 1 was inserted.
            if (1 == value)
            {
                try
                {
                    // Get the current transaction and roll it back.
                    Transaction trans = Transaction.Current;
                    trans.Rollback();                    
                }
                catch (SqlException ex)
                {
                    // Catch the expected exception.                    
                }
            }
            else
            {
                // Perform other actions here.
            }

            // Close the connection.
            connection.Close();            
        }
    }
}

using System;
using System.Data.SqlClient;
using Microsoft.SqlServer.Server;
using System.Transactions;

public partial class Triggers
{
    // Enter existing table or view for the target and uncomment the attribute line
    // [Microsoft.SqlServer.Server.SqlTrigger (Name="trig_InsertValidator", Target="Table1", Event="FOR INSERT")]
    public static void trig_InsertValidator()
    {
        using (SqlConnection connection = new SqlConnection(@"context connection=true"))
        {
            SqlCommand command;
            SqlDataReader reader;
            int value;

            // Open the connection.
            connection.Open();
            
            // Get the inserted value.
            command = new SqlCommand(@"SELECT * FROM INSERTED", connection);
            reader = command.ExecuteReader();
            reader.Read();
            value = (int)reader[0];
            reader.Close();
            
            // Rollback the transaction if a value of 1 was inserted.
            if (1 == value)
            {
                try
                {
                    // Get the current transaction and roll it back.
                    Transaction trans = Transaction.Current;
                    trans.Rollback();                    
                }
                catch (SqlException ex)
                {
                    // Catch the expected exception.                    
                }
            }
            else
            {
                // Perform other actions here.
            }

            // Close the connection.
            connection.Close();            
        }
    }
}

Visual Basic

Imports System
Imports System.Data.SqlClient
Imports System.Data.SqlTypes
Imports Microsoft.SqlServer.Server
Imports System.Transactions

Partial Public Class Triggers
' Enter existing table or view for the target and uncomment the attribute line
' <Microsoft.SqlServer.Server.SqlTrigger(Name:="trig_InsertValidator", Target:="Table1", Event:="FOR INSERT")> _
Public Shared Sub  trig_InsertValidator ()
    Using connection As New SqlConnection("context connection=true")

        Dim command As SqlCommand
        Dim reader As SqlDataReader
        Dim value As Integer

        ' Open the connection.
        connection.Open()

        ' Get the inserted value.
        command = New SqlCommand("SELECT * FROM INSERTED", connection)
        reader = command.ExecuteReader()
        reader.Read()
        value = CType(reader(0), Integer)
        reader.Close()

        ' Rollback the transaction if a value of 1 was inserted.
        If value = 1 Then

            Try
                ' Get the current transaction and roll it back.
                Dim trans As Transaction
                trans = Transaction.Current
                trans.Rollback()

            Catch ex As SqlException

                ' Catch the exception.                    
            End Try
        Else

            ' Perform other actions here.
        End If

        ' Close the connection.
        connection.Close()
    End Using
End Sub
End Class

Imports System
Imports System.Data.SqlClient
Imports System.Data.SqlTypes
Imports Microsoft.SqlServer.Server
Imports System.Transactions

Partial Public Class Triggers
' Enter existing table or view for the target and uncomment the attribute line
' <Microsoft.SqlServer.Server.SqlTrigger(Name:="trig_InsertValidator", Target:="Table1", Event:="FOR INSERT")> _
Public Shared Sub  trig_InsertValidator ()
    Using connection As New SqlConnection("context connection=true")

        Dim command As SqlCommand
        Dim reader As SqlDataReader
        Dim value As Integer

        ' Open the connection.
        connection.Open()

        ' Get the inserted value.
        command = New SqlCommand("SELECT * FROM INSERTED", connection)
        reader = command.ExecuteReader()
        reader.Read()
        value = CType(reader(0), Integer)
        reader.Close()

        ' Rollback the transaction if a value of 1 was inserted.
        If value = 1 Then

            Try
                ' Get the current transaction and roll it back.
                Dim trans As Transaction
                trans = Transaction.Current
                trans.Rollback()

            Catch ex As SqlException

                ' Catch the exception.                    
            End Try
        Else

            ' Perform other actions here.
        End If

        ' Close the connection.
        connection.Close()
    End Using
End Sub
End Class

Transact-SQL

-- Create the test table, assembly, and trigger.
create table Table1(c1 int);
go

CREATE ASSEMBLY ValidationTriggers from 'E:\programming\ ValidationTriggers.dll';
go

CREATE TRIGGER trig_InsertValidator
ON Table1
FOR INSERT
AS EXTERNAL NAME ValidationTriggers.Triggers.trig_InsertValidator;
go

-- Use a Try/Catch block to catch the expected exception
BEGIN TRY
   insert into Table1 values(42)
   insert into Table1 values(1)
END TRY
BEGIN CATCH
  SELECT ERROR_NUMBER() AS ErrorNum, ERROR_MESSAGE() AS ErrorMessage
END CATCH;

-- Clean up.
DROP TRIGGER trig_InsertValidator;
DROP ASSEMBLY ValidationTriggers;
drop table Table1;

-- Create the test table, assembly, and trigger.
create table Table1(c1 int);
go

CREATE ASSEMBLY ValidationTriggers from 'E:\programming\ ValidationTriggers.dll';
go

CREATE TRIGGER trig_InsertValidator
ON Table1
FOR INSERT
AS EXTERNAL NAME ValidationTriggers.Triggers.trig_InsertValidator;
go

-- Use a Try/Catch block to catch the expected exception
BEGIN TRY
   insert into Table1 values(42)
   insert into Table1 values(1)
END TRY
BEGIN CATCH
  SELECT ERROR_NUMBER() AS ErrorNum, ERROR_MESSAGE() AS ErrorMessage
END CATCH;

-- Clean up.
DROP TRIGGER trig_InsertValidator;
DROP ASSEMBLY ValidationTriggers;
drop table Table1;

Ayrıca bkz.

Başvuru

CREATE TRIGGER (Transact-SQL)

eventdata (Transact-sql)

Diğer Kaynaklar

DML Triggers

DDL Triggers

Rollbacks and Commits in Stored Procedures and Triggers

Using TRY...CATCH in Transact-SQL

Ortak dil çalışma zamanı (clr) tümleştirme veritabanı nesneleri oluşturma