我们的产品使用两个不同的数据库[DB1],[DB2]将应用程序数据插入到表中。我被要求实现高可用性清除,而不需要开发团队更新代码中的连接字符串以指向单个数据库,这是最佳做法。我尝试了以下方法:
在[DB1]和[DB2]上创建一个指向主表的视图 创建了一个完全相同的辅助表 在[DB1]和[DB2]上创建存储过程以更改其各自的视图(Why can't SQL Server alter a view in a stored procedure?) 在[DB2]上创建一个作业,利用存储过程来改变视图指向的位置,这样在从主表中清除数据时,插入仍将继续进入辅助表。
以上在[DB2]上很有用,并且改变了视图,改变了数据的插入位置。但是,当作业(在[DB2]上运行)运行更新[DB1]上的视图的步骤时,将抛出以下内容:
子查询返回的值超过1。这是不允许的 子查询跟随=!=< < => > =或当 子查询用作表达式。 [SQLSTATE 21000](错误512) 声明已经终止。 [SQLSTATE 01000](错误3621)。该 步骤失败。,00:00:00,16,3621 ,,,, 0
我尝试了两种不同的方法 -
EXEC sp_executesql N'ALTER VIEW [dbo].[ApplicationEvent]
AS [some sql]'
和
DECLARE @sql varchar(max);
SET @sql = 'ALTER VIEW [dbo].[ApplicationEvent]
AS [some sql]'
exec(@sql);
都返回相同的错误。
需要同时指出视图,并且只有在主表上完成清除过程后才会指出。这是从同一个作业运行这两个步骤的原因。
是否存在仅针对链接服务器执行调用发生的错误?
提前感谢您的任何帮助!
其他想法: 我已经尝试禁用表上的所有触发器,看看这是否是我在这里看到的另一个线程的问题。 如果从他们的家庭数据库运行,两者都创建了SP的工作正常。链接的调用会抛出错误。
编辑:虽然我仍然不知道为什么会抛出这个错误...我现在找到了一个解决方法。
在[DB2]上运行尽可能多的作业之后,我让作业调用[DB1]上的另一个作业,该作业完成了错误的DB上的任务。
EXEC Server2.msdb.dbo.sp_start_job @job_name = N'Job2';
来回做几次让我得到了我想要的结果。如果可能的话,我仍然希望在一个工作中做到这一点,因为这似乎有点hackish。
存储过程以更改视图:
/****** Object: StoredProcedure [dbo].[AlterApplicaitonMessageViewSecondary] Script Date: 11/18/2014 4:01:00 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[AlterApplicaitonMessageViewSecondary]
AS
DECLARE @sql11 varchar(max);
Set @sql11 = 'ALTER VIEW [dbo].[ApplicationMessage2]
AS
--Select from local member table.
SELECT [Id]
,[EventId]
,[Timestamp]
,[Message]
,[Severity]
,[MerchantId]
,[ProviderId]
,[VisitId]
,[UserId]
,[Server]
,[Process]
,[ReferenceId]
FROM [DB1].[ApplicationEvent].[dbo].[ApplicationMessageSecondary]
with (nolock)';
exec(@sql11);