建立發送訂閱

適用於:SQL ServerAzure SQL Database

本主題說明如何使用 SQL Server Management Studio、Transact-SQL 或 Replication Management Objects (RMO),在 SQL Server 中建立發送訂閱。 如需為非 SQL Server 訂閱者建立發送訂閱的資訊,請參閱為非 SQL Server 訂閱者建立訂閱

注意

Azure SQL 受控執行個體可以是快照式與異動複寫的發行者、散發者與訂閱者。 Azure SQL Database 中的資料庫只能是快照式與異動複寫的發送訂閱者。 如需詳細資訊,請參閱使用 Azure SQL DatabaseAzure SQL 受控執行個體的異動複寫。

使用 SQL Server Management Studio

使用 [新增訂閱精靈] 在「發行者」或「訂閱者」端建立發送訂閱。 依照精靈中各頁面進行:

  • 指定發行者和發行集。

  • 選取要執行複寫代理程式的位置。 對於發送訂閱,根據發行集的類型在 [散發代理程式位置] 頁面或 [合併代理程式位置] 頁面上選取 [在散發者端執行所有代理程式 (發送訂閱)]

  • 指定訂閱者與訂閱資料庫。

  • 指定複寫代理程式要連接用的登入和密碼:

    • 針對快照集和交易式發行集的訂閱,請於 [散發代理程式安全性] 頁面指定認證。

    • 針對合併式發行集的訂閱,請於 [合併代理程式安全性] 頁面指定認證。

      如需各代理程式所需權限的資訊,請參閱複寫代理程式安全性模型

  • 指定同步處理排程,以及訂閱者要初始化的時間。

  • 指定合併式發行集的其他選項:訂閱類型以及參數化篩選的值。

  • 指定允許更新訂閱的交易式發行集其他選項。 其中一個選項是決定訂閱者是否應立即在發行者端認可變更,或將其寫入佇列。 另一個選項是設定用來從訂閱者連線至發行者的認證。

  • 選擇性地撰寫訂閱指令碼。

若要從發行者端建立發送訂閱

  1. 連線到 Microsoft SQL Server Management Studio 中的發行者,然後展開伺服器節點。

  2. 展開 [複寫] 資料夾,然後展開 [本機發行集] 資料夾。

  3. 以滑鼠右鍵按一下您要建立一或多個訂閱的發行集,然後選取 [新增訂閱]。

  4. 在新增訂閱精靈中完成頁面。

若要從訂閱者建立發送訂閱

  1. 連線到 SQL Server Management Studio 中的訂閱者,然後展開伺服器節點。

  2. 展開 [複寫] 資料夾。

  3. 以滑鼠右鍵按一下 [區域訂閱] 資料夾,然後選取 [新增訂閱]。

  4. 在 [新增訂閱精靈] 的 [發行集] 頁面上,從 [發行者] 下拉式清單中選取 <尋找 SQL Server 發行者><尋找 Oracle 發行者>

  5. 連接到 [連接到伺服器] 對話方塊中的發行者。

  6. 選取 [發行集] 頁面上的發行集。

  7. 在新增訂閱精靈中完成頁面。

使用 TRANSACT-SQL

您可以使用複寫預存程序,以程式設計的方式建立發送訂閱。 使用哪些預存程序要依訂閱所屬的發行集類型而定。

重要

可能的話,會在執行階段提示使用者輸入安全性認證。 如果您必須將認證儲存在指令碼檔案中,則必須維護這個檔案的安全性,使他人無法在未獲授權的情況下擅自存取。

若要建立快照式或交易式發行集的發送訂閱

  1. 在發行集資料庫的發行者上,確認發行集確實是藉由執行 sp_helppublication 來支援發送訂閱。

    • 如果 allow_push 的值為 1,則發送訂閱受到支援。

    • 如果 allow_push 的值為 0,請執行 sp_changepublication。 針對 @property 指定 allow_push,並針對 @value 指定 true

  2. 在發行集資料庫的發行者上,執行 sp_addsubscription。 指定 @publication@subscriber@destination_db。 將 @subscription_type 的值指定為 push。 如需如何更新訂閱的資訊,請參閱建立交易式發行集的可更新訂閱

  3. 在發行集資料庫的發行者上,執行 sp_addpushsubscription_agent。 指定下列項目:

    • @subscriber@subscriber_db@publication 參數。

    • 執行「散發者」上的「散發代理程式」時會針對 @job_login@job_password 使用 Microsoft Windows 認證。

      注意

      透過 Windows 整合式驗證進行的連線,一律使用由 @job_login@job_password 指定的 Windows 認證。 散發代理程式一律使用 Windows 整合式驗證建立與散發者的本機連線。 根據預設,代理程式會使用 Windows 整合式驗證連線至訂閱者。

    • (選用) @subscriber_security_mode0 值,以及 @subscriber_login@subscriber_password 的 Microsoft SQL Server 登入資訊。 如果您在連接到「訂閱者」時需要使用「SQL Server 驗證」,請指定這些參數。

    • 此訂閱之散發代理程式作業的排程。 如需詳細資訊,請參閱指定同步處理排程

重要

當您使用遠端散發者來建立發行者上的發送訂閱時,提供給所有參數的值 (包括 job_loginjob_password) 都會以純文字格式傳送給散發者。 您應該先加密發行者及其遠端散發者之間的連線,再執行這個預存程序。 如需詳細資訊,請參閱啟用資料庫引擎的加密連線 (SQL Server 組態管理員)

若要建立合併式發行集的發送訂閱

  1. 在發行集資料庫的發行者上,確認發行集確實是藉由執行 sp_helpmergepublication 來支援發送訂閱。

    • 如果 allow_push 的值為 1,則發行集支援發送訂閱。

    • 如果 allow_push 的值不為 1,請執行 sp_changemergepublication。 針對 @property 指定 allow_push,並針對 @value 指定 true

  2. 在發行集資料庫的發行者上,執行 sp_addmergesubscription。 指定下列參數:

    • @publication。 這是發行集的名稱。

    • @subscriber_type。 針對客訂閱,請指定 local。 針對主訂閱,請指定 global

    • @subscription_priority。 指定主訂閱的訂閱優先權 (從0.0099.99)。

    如需詳細資訊,請參閱進階合併式複寫衝突偵測與解決

  3. 在發行集資料庫的發行者上,執行 sp_addmergepushsubscription_agent。 指定下列項目:

    • @subscriber@subscriber_db@publication 參數。

    • Windows 認證,「散發者」上的「合併代理程式」執行時會針對 @job_login@job_password使用該認證。

      注意

      透過 Windows 整合式驗證進行的連線,一律使用由 @job_login@job_password 指定的 Windows 認證。 合併代理程式一律使用 Windows 整合式驗證來建立到散發者的本機連線。 根據預設,代理程式會使用 Windows 整合式驗證連線至訂閱者。

    • (選用) @subscriber_security_mode0 值,以及 @subscriber_login@subscriber_password 的 SQL Server 登入資訊。 如果您在連接到「訂閱者」時需要使用「SQL Server 驗證」,請指定這些參數。

    • (選用) @publisher_security_mode0 值,以及 @publisher_login@publisher_password 的 SQL Server 登入資訊。 如果您在連接到「發行者」時需要使用「SQL Server 驗證」,請指定這些值。

    • 此訂閱之「合併代理程式」作業的排程。 如需詳細資訊,請參閱指定同步處理排程

重要

當您使用遠端散發者來建立發行者上的發送訂閱時,提供給所有參數的值 (包括 job_loginjob_password) 都會以純文字格式傳送給散發者。 您應該先加密發行者及其遠端散發者之間的連線,再執行這個預存程序。 如需詳細資訊,請參閱啟用資料庫引擎的加密連線 (SQL Server 組態管理員)

範例 (Transact-SQL)

下列範例會建立交易式發行集的發送訂閱。 登入和密碼值是在執行階段透過 sqlcmd 指令碼變數所提供。

-- This script uses sqlcmd scripting variables. They are in the form
-- $(MyVariable). For information about how to use scripting variables  
-- on the command line and in SQL Server Management Studio, see the 
-- "Executing Replication Scripts" section in the topic
-- "Programming Replication Using System Stored Procedures".

DECLARE @publication AS sysname;
DECLARE @subscriber AS sysname;
DECLARE @subscriptionDB AS sysname;
SET @publication = N'AdvWorksProductTran';
SET @subscriber = $(SubServer);
SET @subscriptionDB = N'AdventureWorks2022Replica';

--Add a push subscription to a transactional publication.
USE [AdventureWorks2022]
EXEC sp_addsubscription 
  @publication = @publication, 
  @subscriber = @subscriber, 
  @destination_db = @subscriptionDB, 
  @subscription_type = N'push';

--Add an agent job to synchronize the push subscription.
EXEC sp_addpushsubscription_agent 
  @publication = @publication, 
  @subscriber = @subscriber, 
  @subscriber_db = @subscriptionDB, 
  @job_login = $(Login), 
  @job_password = $(Password);
GO

下列範例會建立合併式發行集的發送訂閱。 登入和密碼值是在執行階段透過 sqlcmd 指令碼變數所提供。

-- This script uses sqlcmd scripting variables. They are in the form
-- $(MyVariable). For information about how to use scripting variables  
-- on the command line and in SQL Server Management Studio, see the 
-- "Executing Replication Scripts" section in the topic
-- "Programming Replication Using System Stored Procedures".

DECLARE @publication AS sysname;
DECLARE @subscriber AS sysname;
DECLARE @subscriptionDB AS sysname;
DECLARE @hostname AS sysname;
SET @publication = N'AdvWorksSalesOrdersMerge';
SET @subscriber = $(SubServer);
SET @subscriptionDB = N'AdventureWorksReplica'; 
SET @hostname = N'adventure-works\david8'

-- Add a push subscription to a merge publication.
USE [AdventureWorks2022];
EXEC sp_addmergesubscription 
  @publication = @publication, 
  @subscriber = @subscriber, 
  @subscriber_db = @subscriptionDB, 
  @subscription_type = N'push',
  @hostname = @hostname;

--Add an agent job to synchronize the push subscription.
EXEC sp_addmergepushsubscription_agent 
  @publication = @publication, 
  @subscriber = @subscriber, 
  @subscriber_db = @subscriptionDB, 
  @job_login = $(Login), 
  @job_password = $(Password);
GO

使用 Replication Management Objects

您可以使用 Replication Management Objects (RMO) 以程式設計的方式建立發送訂閱。 用於建立發送訂閱的 RMO 類別,依該訂閱所屬的發行集類型而定。

重要

可能的話,會在執行階段提示使用者輸入安全性認證。 如果您必須儲存認證,請使用 Microsoft Windows .NET Framework 提供的密碼編譯服務

若要建立快照式或交易式發行集的發送訂閱

  1. 使用 ServerConnection 類別建立與發行者的連接。

  2. 使用步驟 1 中的發行者連接建立 TransPublication 類別的執行個體。 指定 NameDatabaseNameConnectionContext

  3. 呼叫 LoadProperties 方法。 如果這個方法傳回 false,則表示步驟 2 中指定的屬性不正確,或伺服器上沒有該發行集存在。

  4. 執行位元運算邏輯 AND (Visual C# 中的&和 Visual Basic 中的 And),位於 Attributes 屬性和 AllowPush 之間。 如果結果為 None,則將 Attributes 設為 | 屬性和 Or 之間位元運算邏輯 OR (Visual C# 中的 Attributes ,並將 AllowPush>。 然後呼叫 CommitPropertyChanges 以啟用發送訂閱。

  5. 如果訂閱資料庫不存在,可使用 Database 類別建立它。 如需詳細資訊,請參閱建立、改變和移除資料庫

  6. 建立 TransSubscription 類別的執行個體。

  7. 設定下列訂閱屬性:

  8. 呼叫 Create 方法。

重要

當您使用遠端散發者來建立發行者的發送訂閱時,提供給所有屬性的值 (包括 SynchronizationAgentProcessSecurity) 都會以純文字方式傳送給散發者。 您應該先加密「發行者」及其遠端「散發者」之間的連線,然後再呼叫 Create 方法。 如需詳細資訊,請參閱啟用資料庫引擎的加密連線 (SQL Server 組態管理員)

若要建立合併式發行集的發送訂閱

  1. 使用 ServerConnection 類別建立與發行者的連接。

  2. 使用步驟 1 中的發行者連接建立 MergePublication 類別的執行個體。 指定 NameDatabaseNameConnectionContext

  3. 呼叫 LoadProperties 方法。 如果這個方法傳回 false,則表示步驟 2 中指定的屬性不正確,或伺服器上沒有該發行集存在。

  4. 執行位元運算邏輯 AND (Visual C# 中的&和 Visual Basic 中的 And),位於 Attributes 屬性和 AllowPush 之間。 如果結果為 None,則將 Attributes 設為 | 屬性和 Or 之間位元運算邏輯 OR (Visual C# 中的 Attributes ,並將 AllowPush>。 然後呼叫 CommitPropertyChanges 以啟用發送訂閱。

  5. 如果訂閱資料庫不存在,可使用 Database 類別建立它。 如需詳細資訊,請參閱建立、改變和移除資料庫

  6. 建立 MergeSubscription 類別的執行個體。

  7. 設定下列訂閱屬性:

  8. 呼叫 Create 方法。

重要

當您使用遠端散發者來建立發行者的發送訂閱時,提供給所有屬性的值 (包括 SynchronizationAgentProcessSecurity) 都會以純文字方式傳送給散發者。 您應該先加密「發行者」及其遠端「散發者」之間的連線,然後再呼叫 Create 方法。 如需詳細資訊,請參閱啟用資料庫引擎的加密連線 (SQL Server 組態管理員)

範例 (RMO)

此範例會建立交易式發行集的新發送訂閱。 用於執行散發代理程式作業的 Windows 帳戶認證,是在執行階段傳遞的。

           // Define the Publisher, publication, and databases.
           string publicationName = "AdvWorksProductTran";
           string publisherName = publisherInstance;
           string subscriberName = subscriberInstance;
           string subscriptionDbName = "AdventureWorks2022Replica";
           string publicationDbName = "AdventureWorks2022";

           //Create a connection to the Publisher.
           ServerConnection conn = new ServerConnection(publisherName);

           // Create the objects that we need.
           TransPublication publication;
           TransSubscription subscription;

           try
           {
               // Connect to the Publisher.
               conn.Connect();

               // Ensure that the publication exists and that 
               // it supports push subscriptions.
               publication = new TransPublication();
               publication.Name = publicationName;
               publication.DatabaseName = publicationDbName;
               publication.ConnectionContext = conn;

               if (publication.IsExistingObject)
               {
                   if ((publication.Attributes & PublicationAttributes.AllowPush) == 0)
                   {
                       publication.Attributes |= PublicationAttributes.AllowPush;
                   }

                   // Define the push subscription.
                   subscription = new TransSubscription();
                   subscription.ConnectionContext = conn;
                   subscription.SubscriberName = subscriberName;
                   subscription.PublicationName = publicationName;
                   subscription.DatabaseName = publicationDbName;
                   subscription.SubscriptionDBName = subscriptionDbName;

                   // Specify the Windows login credentials for the Distribution Agent job.
                   subscription.SynchronizationAgentProcessSecurity.Login = winLogin;
                   subscription.SynchronizationAgentProcessSecurity.Password = winPassword;

                   // By default, subscriptions to transactional publications are synchronized 
                   // continuously, but in this case we only want to synchronize on demand.
                   subscription.AgentSchedule.FrequencyType = ScheduleFrequencyType.OnDemand;

                   // Create the push subscription.
                   subscription.Create();
               }
               else
               {
                   // Do something here if the publication does not exist.
                   throw new ApplicationException(String.Format(
                       "The publication '{0}' does not exist on {1}.",
                       publicationName, publisherName));
               }
           }
           catch (Exception ex)
           {
               // Implement the appropriate error handling here.
               throw new ApplicationException(String.Format(
                   "The subscription to {0} could not be created.", publicationName), ex);
           }
           finally
           {
               conn.Disconnect();
           }
' Define the Publisher, publication, and databases.
Dim publicationName As String = "AdvWorksProductTran"
Dim publisherName As String = publisherInstance
Dim subscriberName As String = subscriberInstance
Dim subscriptionDbName As String = "AdventureWorks2022Replica"
Dim publicationDbName As String = "AdventureWorks2022"

'Create a connection to the Publisher.
Dim conn As ServerConnection = New ServerConnection(publisherName)

' Create the objects that we need.
Dim publication As TransPublication
Dim subscription As TransSubscription

Try
    ' Connect to the Publisher.
    conn.Connect()

    ' Ensure that the publication exists and that 
    ' it supports push subscriptions.
    publication = New TransPublication()
    publication.Name = publicationName
    publication.DatabaseName = publicationDbName
    publication.ConnectionContext = conn

    If publication.IsExistingObject Then
        If (publication.Attributes And PublicationAttributes.AllowPush) = 0 Then
            publication.Attributes = publication.Attributes _
            Or PublicationAttributes.AllowPush
        End If

        ' Define the push subscription.
        subscription = New TransSubscription()
        subscription.ConnectionContext = conn
        subscription.SubscriberName = subscriberName
        subscription.PublicationName = publicationName
        subscription.DatabaseName = publicationDbName
        subscription.SubscriptionDBName = subscriptionDbName

        ' Specify the Windows login credentials for the Distribution Agent job.
        subscription.SynchronizationAgentProcessSecurity.Login = winLogin
        subscription.SynchronizationAgentProcessSecurity.Password = winPassword

        ' By default, subscriptions to transactional publications are synchronized 
        ' continuously, but in this case we only want to synchronize on demand.
        subscription.AgentSchedule.FrequencyType = ScheduleFrequencyType.OnDemand

        ' Create the push subscription.
        subscription.Create()
    Else
        ' Do something here if the publication does not exist.
        Throw New ApplicationException(String.Format( _
         "The publication '{0}' does not exist on {1}.", _
         publicationName, publisherName))
    End If

Catch ex As Exception
    ' Implement the appropriate error handling here.
    Throw New ApplicationException(String.Format( _
        "The subscription to {0} could not be created.", publicationName), ex)
Finally
    conn.Disconnect()
End Try

此範例會建立合併式發行集的新發送訂閱。 用於執行合併代理程式作業的 Windows 帳戶認證,是在執行階段傳遞的。

// Define the Publisher, publication, and databases.
string publicationName = "AdvWorksSalesOrdersMerge";
string publisherName = publisherInstance;
string subscriberName = subscriberInstance;
string subscriptionDbName = "AdventureWorks2022Replica";
string publicationDbName = "AdventureWorks2022";
string hostname = @"adventure-works\garrett1";

//Create a connection to the Publisher.
ServerConnection conn = new ServerConnection(publisherName);

// Create the objects that we need.
MergePublication publication;
MergeSubscription subscription;

try
{
    // Connect to the Publisher.
    conn.Connect();

    // Ensure that the publication exists and that 
    // it supports push subscriptions.
    publication = new MergePublication();
    publication.Name = publicationName;
    publication.DatabaseName = publicationDbName;
    publication.ConnectionContext = conn;

    if (publication.IsExistingObject)
    {
        if ((publication.Attributes & PublicationAttributes.AllowPush) == 0)
        {
            publication.Attributes |= PublicationAttributes.AllowPush;
        }

        // Define the push subscription.
        subscription = new MergeSubscription();
        subscription.ConnectionContext = conn;
        subscription.SubscriberName = subscriberName;
        subscription.PublicationName = publicationName;
        subscription.DatabaseName = publicationDbName;
        subscription.SubscriptionDBName = subscriptionDbName;
        subscription.HostName = hostname;

        // Set a schedule to synchronize the subscription every 2 hours
        // during weekdays from 6am to 10pm.
        subscription.AgentSchedule.FrequencyType = ScheduleFrequencyType.Weekly;
        subscription.AgentSchedule.FrequencyInterval = Convert.ToInt32(0x003E);
        subscription.AgentSchedule.FrequencyRecurrenceFactor = 1;
        subscription.AgentSchedule.FrequencySubDay = ScheduleFrequencySubDay.Hour;
        subscription.AgentSchedule.FrequencySubDayInterval = 2;
        subscription.AgentSchedule.ActiveStartDate = 20051108;
        subscription.AgentSchedule.ActiveEndDate = 20071231;
        subscription.AgentSchedule.ActiveStartTime = 060000;
        subscription.AgentSchedule.ActiveEndTime = 100000;

        // Specify the Windows login credentials for the Merge Agent job.
        subscription.SynchronizationAgentProcessSecurity.Login = winLogin;
        subscription.SynchronizationAgentProcessSecurity.Password = winPassword;

        // Create the push subscription.
        subscription.Create();
    }
    else
    {
        // Do something here if the publication does not exist.
        throw new ApplicationException(String.Format(
            "The publication '{0}' does not exist on {1}.",
            publicationName, publisherName));
    }
}
catch (Exception ex)
{
    // Implement the appropriate error handling here.
    throw new ApplicationException(String.Format(
        "The subscription to {0} could not be created.", publicationName), ex);
}
finally
{
    conn.Disconnect();
}
' Define the Publisher, publication, and databases.
Dim publicationName As String = "AdvWorksSalesOrdersMerge"
Dim publisherName As String = publisherInstance
Dim subscriberName As String = subscriberInstance
Dim subscriptionDbName As String = "AdventureWorks2022Replica"
Dim publicationDbName As String = "AdventureWorks2022"
Dim hostname As String = "adventure-works\garrett1"

'Create a connection to the Publisher.
Dim conn As ServerConnection = New ServerConnection(publisherName)

' Create the objects that we need.
Dim publication As MergePublication
Dim subscription As MergeSubscription

Try
    ' Connect to the Publisher.
    conn.Connect()

    ' Ensure that the publication exists and that 
    ' it supports push subscriptions.
    publication = New MergePublication()
    publication.Name = publicationName
    publication.DatabaseName = publicationDbName
    publication.ConnectionContext = conn

    If publication.IsExistingObject Then
        If (publication.Attributes And PublicationAttributes.AllowPush) = 0 Then
            publication.Attributes = publication.Attributes _
            Or PublicationAttributes.AllowPush
        End If

        ' Define the push subscription.
        subscription = New MergeSubscription()
        subscription.ConnectionContext = conn
        subscription.SubscriberName = subscriberName
        subscription.PublicationName = publicationName
        subscription.DatabaseName = publicationDbName
        subscription.SubscriptionDBName = subscriptionDbName
        subscription.HostName = hostname

        ' Set a schedule to synchronize the subscription every 2 hours
        ' during weekdays from 6am to 10pm.
        subscription.AgentSchedule.FrequencyType = ScheduleFrequencyType.Weekly
        subscription.AgentSchedule.FrequencyInterval = Convert.ToInt32("0x003E", 16)
        subscription.AgentSchedule.FrequencyRecurrenceFactor = 1
        subscription.AgentSchedule.FrequencySubDay = ScheduleFrequencySubDay.Hour
        subscription.AgentSchedule.FrequencySubDayInterval = 2
        subscription.AgentSchedule.ActiveStartDate = 20051108
        subscription.AgentSchedule.ActiveEndDate = 20071231
        subscription.AgentSchedule.ActiveStartTime = 60000
        subscription.AgentSchedule.ActiveEndTime = 100000

        ' Specify the Windows login credentials for the Merge Agent job.
        subscription.SynchronizationAgentProcessSecurity.Login = winLogin
        subscription.SynchronizationAgentProcessSecurity.Password = winPassword

        ' Create the push subscription.
        subscription.Create()
    Else

        ' Do something here if the publication does not exist.
        Throw New ApplicationException(String.Format( _
         "The publication '{0}' does not exist on {1}.", _
         publicationName, publisherName))
    End If
Catch ex As Exception
    ' Implement the appropriate error handling here.
    Throw New ApplicationException(String.Format( _
    "The subscription to {0} could not be created.", publicationName), ex)
Finally
    conn.Disconnect()
End Try

另請參閱

檢視及修改發送訂閱屬性
複寫安全性最佳做法
建立發行集
複寫管理物件概念
同步處理發送訂閱
訂閱發行集
以指令碼變數使用 sqlcmd