我有一个应用程序,允许用户互相联系,将其视为约会网站。我在联系人部分周围添加了一些安全措施,用户可以通过设置特定的年龄/身高范围和性别来限制谁可以联系他/她。
例如,我点击UserId-2配置文件,然后这将调用数据库,传入ID或选择的配置文件并传入我的ID,然后调用我的函数传递这两个值。功能如下:
ALTER FUNCTION [dbo].[Can_User_Contact]
(
@UserId1 int = 2, -- UserId
@UserId2 int = 1 -- Requested by Id
)
RETURNS bit
AS
BEGIN
RETURN (
SELECT CASE WHEN up.Id IS NULL THEN 0 ELSE 1 END AS does_data_match
FROM [user].User_Settings us
LEFT OUTER JOIN [User].[User_Profile] up ON us.UserId = @UserId1
LEFT OUTER JOIN [User].[User_Details] d ON up.Id = d.UserId
AND up.id = @UserId2
AND d.Height between ISNULL(us.HeightFrom, d.height) and ISNULL(us.HeightTo, d.Height)
AND up.Age between ISNULL(us.AgeFrom, up.age) and ISNULL(us.AgeTo, up.Age)
AND up.Gender = ISNULL(us.Gender, up.Gender)
)
END
在这个函数中,我将UserId-2在设置表中保存的值与我自己的值进行比较,方法是加入用户配置文件表和用户详细信息表,这个问题就是每次执行它我得到的以下消息:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
我在设置表中有两条记录,如下所示:
我只对第二张唱片感兴趣。
有人可以对我可能做错的事情有所了解吗?
@ UserId1是个人资料ID, @ UserId2是请求查看它的用户。
请记住,@ UserId1的设置表中可能没有记录,此功能也是可选的。
答案 0 :(得分:1)
SELECT
查询返回多行。
由于您对单个值的使用感兴趣,所以:
ALTER FUNCTION [dbo].[Can_User_Contact]
(
@UserId1 int = 2, -- UserId
@UserId2 int = 1 -- Requested by Id
)
RETURNS bit
AS
BEGIN
RETURN
(
SELECT CASE WHEN EXISTS
(
SELECT 1 FROM [user].User_Settings us1
LEFT OUTER JOIN [User].[User_Profile] up ON up.id = @UserId2
LEFT OUTER JOIN [User].[User_Details] d ON up.Id = d.UserId
LEFT OUTER JOIN [user].[User_Settings] us2 ON us2.UserId=up.id
WHERE
d.Height between ISNULL(us1.HeightFrom, d.height) and ISNULL(us1.HeightTo, d.Height)
AND us2.Age between ISNULL(us1.AgeFrom, up.age) and ISNULL(us1.AgeTo, up.Age)
AND us1.Gender = ISNULL(us2.Gender, up.Gender)
AND up.Id IS NOT NULL
AND us1.UserId = @UserId1
) THEN 1 ELSE 0 END AS does_data_match
END
答案 1 :(得分:1)
假设您为每个用户设置了user_setting
,User_Profile
和User_Details
的条目,这应该可以。
根据您的结果,您的加入条件会出现问题。理想情况下,您的某些加入条件应该是WHERE
条款的一部分,例如up.id = @UserId2
。
<强>查询强>
SELECT TOP 1 CASE WHEN us.UserId IS NULL THEN 0 ELSE 1 END AS does_data_match
FROM [User].[User_Profile] up
INNER JOIN [User].[User_Details] d ON up.Id = d.UserId
LEFT OUTER JOIN [user].User_Settings us
ON us.UserId = @UserId1
AND d.Height between ISNULL(us.HeightFrom, d.height) and ISNULL(us.HeightTo, d.Height)
AND up.Age between ISNULL(us.AgeFrom, up.age) and ISNULL(us.AgeTo, up.Age)
AND up.Gender = ISNULL(us.Gender, up.Gender)
WHERE up.id = @UserId2
ORDER BY up.id ASC
注意:如果假设为真,那么理想情况下不需要TOP
。只是添加了它以增加安全性