在 temp table 中搜索时的条件 AND 语句
Conditional AND statement when searching in temp table
我正在编写一个存储过程来通过管理面板搜索客户table。
我大部分时间都在使用它,当我传递 CustomerRoles(分隔的客户角色 ID)时,我得到了那些角色中的客户 returned.
但是,如果我不传递任何客户角色(所以是一个空字符串),我不会得到任何记录,但我希望它传递给 return 所有角色。
这是我关心的部分
AND (@CustomerRoles IS null OR EXISTS (
SELECT [Customer_Id], [CustomerRole_Id] FROM [Test].[dbo].[Customer_CustomerRole_Mapping] crm with (NOLOCK)
WHERE c.Id = crm.Customer_Id AND crm.[CustomerRole_Id] IN (SELECT CustomerRoleId FROM #FilteredCustomerRolesIds)))
我可以确认在未搜索 CustomerRoles 时将空值传递到存储过程。
我想我需要某种空值检查或合并表达式,但不确定如何去做。
这是我的完整存储过程
USE [Test]
GO
/****** Object: StoredProcedure [dbo].[CustomerLoadAllPaged] Script Date: 10/2/2020 8:20:52 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--new stored procedure
ALTER PROCEDURE [dbo].[CustomerLoadAllPaged]
(
@CustomerRoles nvarchar(MAX) = null,
@CustomerEmail nvarchar(MAX) = null,
@FirstName nvarchar(MAX) = null,
@LastName nvarchar(MAX) = null,
@PageIndex int = 0,
@PageSize int = 2147483644,
@TotalRecords int = null OUTPUT
)
AS
BEGIN
create table #TempCust (RowNum int identity(1,1), id int);
create index #IK_tempcust on #TempCust (RowNum);
SET @CustomerRoles = isnull(@CustomerRoles, '')
CREATE TABLE #FilteredCustomerRolesIds
(
CustomerRoleId int not null
)
INSERT INTO #FilteredCustomerRolesIds (CustomerRoleId)
SELECT CAST(data as int) FROM [nop_splitstring_to_table](@CustomerRoles, ',')
DECLARE @CustomerRoleIdCount int
SET @CustomerRoleIdCount = (SELECT COUNT(1) FROM #FilteredCustomerRolesIds)
-- Insert statements for procedure here
--select all
INSERT INTO #TempCust ([id])
SELECT c.[Id]
FROM [Test].[dbo].[Customer] c with (NOLOCK)
LEFT join [Test].[dbo].[Address] a with (NOLOCK) on a.Id = c.BillingAddress_Id and (
coalesce(@CustomerEmail,'') <> ''
or coalesce(@FirstName,'') <> ''
or coalesce(@LastName,'') <> ''
)
/*LEFT join [Test].[dbo].[Customer_CustomerRole_Mapping] crm with (NOLOCK) on c.Id = crm.Customer_Id and (
coalesce(@CustomerRoles,'') <> ''
)*/
WHERE (@CustomerEmail IS null OR c.[Email] LIKE CONCAT('%',@CustomerEmail,'%'))
AND (@FirstName IS null OR a.[FirstName] LIKE CONCAT('%',@FirstName,'%'))
AND (@LastName IS null OR a.[LastName] LIKE CONCAT('%',@LastName,'%'))
--AND (crm.[CustomerRole_Id] IN (SELECT CustomerRoleId FROM #FilteredCustomerRolesIds))
AND (@CustomerRoles IS null OR EXISTS (
SELECT [Customer_Id], [CustomerRole_Id] FROM [Test].[dbo].[Customer_CustomerRole_Mapping] crm with (NOLOCK)
WHERE c.Id = crm.Customer_Id AND crm.[CustomerRole_Id] IN (SELECT CustomerRoleId FROM #FilteredCustomerRolesIds)))
--ORDER BY c.[CreatedOnUtc] DESC;
--paging
DECLARE @PageLowerBound int
SET @PageLowerBound = @PageSize * @PageIndex
-- Return the paged records
select [Id] --note select * can produce unexpected results
,[CustomerGuid]
,[Username]
,[Email]
,[Password]
,[PasswordFormatId]
,[PasswordSalt]
,[AdminComment]
,[IsTaxExempt]
,[AffiliateId]
,[VendorId]
,[HasShoppingCartItems]
,[Active]
,[Deleted]
,[IsSystemAccount]
,[SystemName]
,[LastIpAddress]
,[CreatedOnUtc]
,[LastLoginDateUtc]
,[LastActivityDateUtc]
,[BillingAddress_Id]
,[ShippingAddress_Id]
from [Test].[dbo].[Customer] cust with (NOLOCK)
where cust.[Id] in (
select id
from #TempCust tc
--Where (tc.RowNum > @PageLowerBound) -- best to use offset like below, which is faster and recommended
)
ORDER BY cust.[CreatedOnUtc] DESC
OFFSET @PageLowerBound ROWS FETCH NEXT @PageSize ROWS ONLY;
--total records
select @TotalRecords = count(*) from #TempCust;
DROP TABLE #TempCust
DROP TABLE #FilteredCustomerRolesIds
END
因为您通过以下行确保 @CustomerRoles
永远不会 null
:
SET @CustomerRoles = ISNULL(@CustomerRoles, '');
您需要与空字符串进行比较而不是 null
例如
AND (
-- @CustomerRoles IS NULL -- Change to empty string check since it is never null
@CustomerRoles = ''
OR EXISTS (
SELECT [Customer_Id], [CustomerRole_Id]
FROM [Test].[dbo].[Customer_CustomerRole_Mapping] crm WITH (NOLOCK)
WHERE c.Id = crm.Customer_Id AND crm.[CustomerRole_Id] IN (SELECT CustomerRoleId FROM #FilteredCustomerRolesIds)
)
)
顺便说一句,你不应该使用 nolock
提示,除非它绝对需要性能。
空字符串与 NULL
不同。如果传递的是空字符串,则需要与 ''
进行比较。或者,也许您想安全起见并考虑两种可能性:
AND (@CustomerRoles IS null OR
@CustomerRoles = '' OR
EXISTS ( . . . )
)
我正在编写一个存储过程来通过管理面板搜索客户table。 我大部分时间都在使用它,当我传递 CustomerRoles(分隔的客户角色 ID)时,我得到了那些角色中的客户 returned.
但是,如果我不传递任何客户角色(所以是一个空字符串),我不会得到任何记录,但我希望它传递给 return 所有角色。
这是我关心的部分
AND (@CustomerRoles IS null OR EXISTS (
SELECT [Customer_Id], [CustomerRole_Id] FROM [Test].[dbo].[Customer_CustomerRole_Mapping] crm with (NOLOCK)
WHERE c.Id = crm.Customer_Id AND crm.[CustomerRole_Id] IN (SELECT CustomerRoleId FROM #FilteredCustomerRolesIds)))
我可以确认在未搜索 CustomerRoles 时将空值传递到存储过程。
我想我需要某种空值检查或合并表达式,但不确定如何去做。
这是我的完整存储过程
USE [Test]
GO
/****** Object: StoredProcedure [dbo].[CustomerLoadAllPaged] Script Date: 10/2/2020 8:20:52 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--new stored procedure
ALTER PROCEDURE [dbo].[CustomerLoadAllPaged]
(
@CustomerRoles nvarchar(MAX) = null,
@CustomerEmail nvarchar(MAX) = null,
@FirstName nvarchar(MAX) = null,
@LastName nvarchar(MAX) = null,
@PageIndex int = 0,
@PageSize int = 2147483644,
@TotalRecords int = null OUTPUT
)
AS
BEGIN
create table #TempCust (RowNum int identity(1,1), id int);
create index #IK_tempcust on #TempCust (RowNum);
SET @CustomerRoles = isnull(@CustomerRoles, '')
CREATE TABLE #FilteredCustomerRolesIds
(
CustomerRoleId int not null
)
INSERT INTO #FilteredCustomerRolesIds (CustomerRoleId)
SELECT CAST(data as int) FROM [nop_splitstring_to_table](@CustomerRoles, ',')
DECLARE @CustomerRoleIdCount int
SET @CustomerRoleIdCount = (SELECT COUNT(1) FROM #FilteredCustomerRolesIds)
-- Insert statements for procedure here
--select all
INSERT INTO #TempCust ([id])
SELECT c.[Id]
FROM [Test].[dbo].[Customer] c with (NOLOCK)
LEFT join [Test].[dbo].[Address] a with (NOLOCK) on a.Id = c.BillingAddress_Id and (
coalesce(@CustomerEmail,'') <> ''
or coalesce(@FirstName,'') <> ''
or coalesce(@LastName,'') <> ''
)
/*LEFT join [Test].[dbo].[Customer_CustomerRole_Mapping] crm with (NOLOCK) on c.Id = crm.Customer_Id and (
coalesce(@CustomerRoles,'') <> ''
)*/
WHERE (@CustomerEmail IS null OR c.[Email] LIKE CONCAT('%',@CustomerEmail,'%'))
AND (@FirstName IS null OR a.[FirstName] LIKE CONCAT('%',@FirstName,'%'))
AND (@LastName IS null OR a.[LastName] LIKE CONCAT('%',@LastName,'%'))
--AND (crm.[CustomerRole_Id] IN (SELECT CustomerRoleId FROM #FilteredCustomerRolesIds))
AND (@CustomerRoles IS null OR EXISTS (
SELECT [Customer_Id], [CustomerRole_Id] FROM [Test].[dbo].[Customer_CustomerRole_Mapping] crm with (NOLOCK)
WHERE c.Id = crm.Customer_Id AND crm.[CustomerRole_Id] IN (SELECT CustomerRoleId FROM #FilteredCustomerRolesIds)))
--ORDER BY c.[CreatedOnUtc] DESC;
--paging
DECLARE @PageLowerBound int
SET @PageLowerBound = @PageSize * @PageIndex
-- Return the paged records
select [Id] --note select * can produce unexpected results
,[CustomerGuid]
,[Username]
,[Email]
,[Password]
,[PasswordFormatId]
,[PasswordSalt]
,[AdminComment]
,[IsTaxExempt]
,[AffiliateId]
,[VendorId]
,[HasShoppingCartItems]
,[Active]
,[Deleted]
,[IsSystemAccount]
,[SystemName]
,[LastIpAddress]
,[CreatedOnUtc]
,[LastLoginDateUtc]
,[LastActivityDateUtc]
,[BillingAddress_Id]
,[ShippingAddress_Id]
from [Test].[dbo].[Customer] cust with (NOLOCK)
where cust.[Id] in (
select id
from #TempCust tc
--Where (tc.RowNum > @PageLowerBound) -- best to use offset like below, which is faster and recommended
)
ORDER BY cust.[CreatedOnUtc] DESC
OFFSET @PageLowerBound ROWS FETCH NEXT @PageSize ROWS ONLY;
--total records
select @TotalRecords = count(*) from #TempCust;
DROP TABLE #TempCust
DROP TABLE #FilteredCustomerRolesIds
END
因为您通过以下行确保 @CustomerRoles
永远不会 null
:
SET @CustomerRoles = ISNULL(@CustomerRoles, '');
您需要与空字符串进行比较而不是 null
例如
AND (
-- @CustomerRoles IS NULL -- Change to empty string check since it is never null
@CustomerRoles = ''
OR EXISTS (
SELECT [Customer_Id], [CustomerRole_Id]
FROM [Test].[dbo].[Customer_CustomerRole_Mapping] crm WITH (NOLOCK)
WHERE c.Id = crm.Customer_Id AND crm.[CustomerRole_Id] IN (SELECT CustomerRoleId FROM #FilteredCustomerRolesIds)
)
)
顺便说一句,你不应该使用 nolock
提示,除非它绝对需要性能。
空字符串与 NULL
不同。如果传递的是空字符串,则需要与 ''
进行比较。或者,也许您想安全起见并考虑两种可能性:
AND (@CustomerRoles IS null OR
@CustomerRoles = '' OR
EXISTS ( . . . )
)