我正在使用SQL Server 2008 RC2。
我们经常要做类似的查询:
select * from Site s where s.name in (:names)
":names"
是1000个以逗号分隔的18字节名称的大StringBuilder
。这需要一段时间才能运行;在我的本地开发机器上一分钟。我知道有很多人建议使用Table Valued Parameters
(TVP),例如下面的示例:
create procedure [dbo].[sp_TestSites] @siteNames SiteNameTableType readonly
as
begin
select s.* from Site s
inner join @siteNames d on d.name = s.name
end
但是,由于Microsoft JDBC Driver仍然不支持TVP(据我所知),实现这一目标的最佳方法是什么?将一个逗号分隔值的长字符串发送到存储过程,然后在过程中拆分字符串并插入临时表?例如:
create type dbo.SiteNameTableType as table(
name varchar(18) not null unique
)
create procedure sp_TestSites(
@longStringOfNames varchar(max))
as
begin
declare @siteNames SiteNameTableType
insert into @siteNames
select * from dbo.split(@longStringOfNames) -- assume I have a Split function
select s.* from Site s
inner join @siteNames d on d.name = s.name
end
答案 0 :(得分:1)
正如我在评论中提到的,您可以将数据准备为XML字符串并将其传递给存储过程。在SP内部,您可以查询该XML并根据需要加入结果集。
答案 1 :(得分:1)
您还可以将CSV字符串传递给SP,使用SP中的FUNCTION将CSV字符串转换为TVP,然后使用它?
实施例:
CREATE FUNCTION [dbo].[GET_TABLE_FROM_CSVSTRING] ( @CSVString VARCHAR(MAX))
RETURNS @Result TABLE(ItemValue VARCHAR(MAX))
AS
BEGIN
DECLARE @x XML
SELECT @x = CAST('<A>'+ REPLACE(@CSVString,',','</A><A>')+ '</A>' AS XML)
INSERT INTO @Result
SELECT t.value('.', 'VARCHAR(MAX)') AS inVal
FROM @x.nodes('/A') AS x(t)
RETURN
END
GO
我不知道这是否是最快的字符串分割器,但我会稍微检查一下。 注意:为了在特定情况下获得更好的性能,请修改生成的TVP定义(和XML代码)以包含您期望的精确列域(以帮助查询优化器)。即如果您确定单个值的长度最多为50个字符,请不要使用VARCHAR(MAX)但要使用VARCHAR(50)。