我有一个场景,我必须根据用户选择应用过滤器,过滤器应匹配所有值。 例如:如果用户对酒店设施应用过滤器,则应过滤符合用户选择的所有设施的酒店。
Create PROCEDURE [dbo].[usp_GetHotelListing]
@HotelID INT = 1,
@Amenities varchar(50) = '1,3'
AS
BEGIN
select * from DTHotelAmenities where HotelID = @HotelID and <Searching For Condition>
END
{{1}}
答案 0 :(得分:1)
&#34; [...]它应该过滤匹配所有用户选择的设施的酒店。&#34;
第一个解决方案(我发送设施清单)我会使用TVP:
CREATE TYPE dbo.IntArray AS TABLE (
-- NULLs and duplicated are disallowed.
IntValue INT NOT NULL PRIMARY KEY
);
GO
create procedure [dbo].[usp_GetHotelListing]
@HotelID INT = 1,
@Amenities IntArray READONLY
AS
begin
select ha.HotelID
from DTHotelAmenities ha
where HotelID = @HotelID
and exists (select * from @Amenities a where ha.AmenitiesID = a.IntValue)
group by ha.HotelID
-- Use distinct if there is not UNIQUE index / constraint defined on (HotelID, AmenitiesID)
having count(/*distinct*/ ha.AmenitiesID) = (select count(*) from @Amenities)
end
第二个解决方案使用XML发送值列表:
create procedure [dbo].[usp_GetHotelListing]
@HotelID INT = 1,
@Amenities XML = N'<r><i value="1"><i value="3"></r>'
AS
begin
create table #Amenities (AmenitiesID INT)
insert #Amenities (AmenitiesID)
select b.XmlCol.value('(@AmenitiesID)[1]', 'INT')
from (select @Amenities) a(XmlCol)
cross apply a.XmlCol.nodes('r/i') b(XmlCol)
select ha.HotelID
from DTHotelAmenities ha
where HotelID = @HotelID
and exists (select * from #Amenities a where ha.AmenitiesID = a.IntValue)
group by ha.HotelID
-- 1) Use distinct if there is not UNIQUE index / constraint defined on (HotelID, AmenitiesID)
-- 2) Use "count(distinct IntValue)" if @Amenities param could contain duplicated values
having count(/*distinct*/ ha.AmenitiesID) = (select count(/*distinct*/ IntValue) from #Amenities)
end
答案 1 :(得分:0)
动态查询版本:
Create PROCEDURE [dbo].[usp_GetHotelListing]
@HotelID INT = 1,
@Amenities varchar(50) = '1,3'
AS
BEGIN
declare @sql nvarchar(max) =
'select * from DTHotelAmenities where HotelID = ' +
cast(@HotelID as nvarchar(max)) +
' and AmenitiesID in(' + @Amenities + ')'
exec(@sql)
END
一般要注意sql注入威胁的可能性。您可能需要查看sp_executesql
替代方案。
答案 2 :(得分:0)
也许就像....
Create PROCEDURE [dbo].[usp_GetHotelListing]
@HotelID INT = 1,
@Amenities varchar(50) = '1,3'
AS
BEGIN
SET NOCOUNT ON;
Declare @xml XML;
Declare @t table (ID INT);
SET @xml = '<root><x>' + REPLACE(@Amenities , ',' , '</x><x>') + '</x></root>'
INSERT INTO @t(ID)
Select r.value('.', 'VARCHAR(max)') value
FROM @xml.nodes('//root/x') as records(r)
select o.*
from DTHotelAmenities o
INNER JOIN @t t ON t.ID = o.AmenitiesID
where o.HotelID = @HotelID
END