【问题标题】:I'm getting "error Msg 512, Level 16, State 1, Line 1 Subquery returned more than 1 value"我收到“错误消息 512,级别 16,状态 1,第 1 行子查询返回超过 1 个值”
【发布时间】:2014-01-28 20:29:45
【问题描述】:
在尝试确定特定集群上高可用性数据库的状态时,我收到了标题的错误消息。
消息 512,第 16 级,状态 1,第 1 行
子查询返回超过 1 个值。当子查询跟随 =、!=、、>= 或子查询用作表达式时,这是不允许的
这是我的代码的一部分。我需要能够利用两个 select 语句的结果,然后在两者都满足时分配 @HadrRole。
IF ((SELECT ars.role
FROM sys.dm_hadr_availability_replica_states ars
INNER JOIN sys.databases dbs
ON ars.replica_id = dbs.replica_id
WHERE dbs.name = @DatabaseName) = 2 AND (SELECT secondary_role_allow_connections_desc
FROM sys.availability_replicas) ='ALL')
SET @HadrRole = 3
【问题讨论】:
标签:
sql-server
tsql
cluster-computing
high-availability
【解决方案1】:
尝试使用EXISTS子查询:
IF EXISTS
(
SELECT *
FROM sys.dm_hadr_availability_replica_states ars
INNER JOIN sys.databases dbs
ON ars.replica_id = dbs.replica_id
WHERE dbs.name = @DatabaseName AND ars.role = 2
) AND
EXISTS
(
SELECT *
FROM sys.availability_replicas
WHERE secondary_role_allow_connections_desc = 'ALL'
)
SET @HadrRole = 3
注意:您可以这样使用SET 语句:
SET @HadrRole =
CASE
WHEN EXISTS
(
SELECT *
FROM sys.dm_hadr_availability_replica_states ars
INNER JOIN sys.databases dbs
ON ars.replica_id = dbs.replica_id
WHERE dbs.name = @DatabaseName AND ars.role = 2
)
AND EXISTS
(
SELECT *
FROM sys.availability_replicas
WHERE secondary_role_allow_connections_desc = 'ALL'
)
THEN 3
ELSE @HadrRole
END
【解决方案2】:
我用它来确定集群中每台服务器上的高可用性数据库是主数据库、辅助数据库还是只读辅助数据库。我将使用它来修改我的 SQL 代理作业,以便它们在集群中的正确服务器上运行(根据作业只读辅助或主服务器。感谢您的回复!我希望这对其他人有所帮助。
USE [msdb]
GO
/****** Object: UserDefinedFunction [dbo].[RG_fn_HA_isPrimaryReplica_isSecondayReadable] Script Date: 1/27/2014 4:31:39 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF object_id(N'RG_fn_HA_isPrimaryReplica_isSecondayReadable', 'FN') IS NOT NULL
DROP FUNCTION RG_fn_HA_isPrimaryReplica_isSecondayReadable
GO
CREATE FUNCTION [dbo].[RG_fn_HA_isPrimaryReplica_isSecondayReadable] (@DatabaseName SYSNAME)
RETURNS TINYINT
WITH EXECUTE AS CALLER
AS
/********************************************************************
File Name: RG_fn_HA_isPrimaryReplica_isSecondayReadable.sql
Applies to: SQL Server 2012
Purpose: To return either 0, 1, or 2 based on whether this
@DatabaseName is a primary or secondary replica.
Parameters: @DatabaseName - The name of the database to check.
Returns: 0 = Resolving
1 = Primary
2 = Secondary
3 = Readable Secondary
Author: Matthew Joyce
Version: 1.0.0 - 01/28/2014
********************************************************************/
BEGIN
DECLARE @HadrRole TINYINT
-- Return role status from sys.dm_hadr_availability_replica_states
IF (SELECT ars.role
FROM sys.dm_hadr_availability_replica_states ars
INNER JOIN sys.databases dbs
ON ars.replica_id = dbs.replica_id
WHERE dbs.name = @DatabaseName) = 1
SET @HadrRole = 1
ELSE
-- @DatabaseName exists but does not belong to an AG so return 1
-- IF @HadrRole IS NULL
--SET @HadrRole = 1
--ELSE
--Return 2 if secondary but not readable
IF (SELECT ars.role
FROM sys.dm_hadr_availability_replica_states ars
INNER JOIN sys.databases dbs
ON ars.replica_id = dbs.replica_id
WHERE dbs.name = @DatabaseName) = 2 AND (SELECT secondary_role_allow_connections_desc
FROM sys.availability_replicas
where replica_server_name =(select @@ServerName)) <>'ALL'
SET @HadrRole = 2
ELSE
IF (SELECT ars.role
FROM sys.dm_hadr_availability_replica_states ars
INNER JOIN sys.databases dbs
ON ars.replica_id = dbs.replica_id
WHERE dbs.name = @DatabaseName) = 2 AND (SELECT secondary_role_allow_connections_desc
FROM sys.availability_replicas
where replica_server_name =(select @@ServerName)) ='ALL'
SET @HadrRole = 3
RETURN @HadrRole;
END;
GO