当传递大的逗号分隔值时,使用自定义 TABLE TYPE 作为参数而不是 SQL“IN”子句是否更好

2023-12-14

我有一个存储过程,它接受逗号分隔的字符串作为输入。有时可能太大,大约超过 8000 个字符或更多。在这种情况下,查询性能有时会下降。我认为里面的字符长度有限制IN条款。为此,有时我会遇到错误。现在,我需要知道使用自定义表类型作为参数并使用是否更好Inner JOIN找到结果。如果是的话那又是为什么呢。这是我的 2 个存储过程(最少代码):

CREATE TYPE [dbo].[INTList] AS TABLE(
    [ID] [int] NULL
)

程序1

CREATE PROCEDURE [report].[GetSKU]   
  @list [INTList] READONLY,         
AS 

Select sk.SKUID,sk.Code SCode,sk.SName
FROM SKUs sk
INNER JOIN @list sst ON sst.ID=sk.SKUID

程序2

CREATE PROCEDURE [report].[GetSKU]   
  @params varchar(max),         
AS 
Select sk.SKUID,sk.Code SCode,sk.SName
FROM SKUs sk
WHere CHARINDEX(','+cast( sk.SKUID as varchar(MAX))+',', @params) > 0

现在,使用哪些程序更好。

Note:原始存储过程确实还有一些Joins.


由于这个问题确实在评论中引起了相当多的讨论,但没有得到任何可行的答案,我想添加要点以帮助将来的研究。

这个问题是关于:如何将(大)值列表传递到查询中?

在大多数情况下,人们需要这个WHERE SomeColumn IN(SomeValueList)- 过滤或JOIN反对这个与类似的东西FROM MyTable INNER JOIN SomeValueList ON....

非常重要的是 SQL-Server 的版本,就像 v2016 一样,我们有两个很棒的工具:native STRING_SPLIT() (位置不安全!) 和 JSON 支持。

此外,相当明显的是,我们必须考虑尺度和数值.

  • 我们是传入一些 ID 的简单列表还是包含数千个值的巨大列表?
  • 我们谈论的是简单整数还是 GUID?
  • 文本值又如何,我们必须考虑危险字符(例如[ { "在 JSON 或< &在 XML 中 - 还有更多...)?
  • CSV 列表怎么样,其中可能会出现分隔符within内容(引用/转义)?
  • 在某些情况下,我们甚至可能想一次传递几列......

有几种选择:

  • 表值参数(TVP,CREATE TYPE ...),
  • CSV 与字符串分割函数(自 v2016 起原生,各种自制,CLR...),
  • 和基于文本的容器:XML 或 JSON(自 v2016 起)

表值参数(TVP - 最佳选择)

表值参数 (TVP) 必须提前创建(这可能是一个缺点),但创建后将像任何其他表一样运行。您可以添加索引,可以在各种用例中使用它,而不必担心幕后的任何事情。
有时我们由于缺少使用权而无法使用它CREATE TYPE...

字符分隔值 (CSV)

对于 CSV,我们看到三种方法

  • 动态 Sql:创建一条语句,将 CSV 列表简单地填充到IN()并动态执行它。这can是一种非常有效的方法,但会遇到各种障碍(没有ad-hoc-使用、注入威胁、破坏不良价值观……)

  • 字符串拆分函数:周围有大量示例...所有这些示例都有一个共同点:分隔的字符串将作为项目列表返回。这里的常见问题:性能、缺少序数位置、分隔符的限制、重复或空值的处理、引用或转义值的处理、分隔符的处理within内容。亚伦·伯特兰做了一些伟大的研究关于字符串分割的各种方法。与 TVP 类似,一个缺点可能是,该函数必须提前存在于数据库中,或者需要允许我们执行CREATE FUNCTION if not.

  • ad-hoc-splitters:在 v2016 之前,最常用的方法是基于 XML 的,从那时起,我们已转向基于 JSON 的拆分器。两者都使用一些字符串方法将 CSV 字符串转换为 1) 分隔元素 (XML) 或 2) 转换为 JSON 数组。通过1) XQuery (.value() and .nodes()) 或 2) JSONOPENJSON() or JSON_VALUE().

基于文本的容器

我们可以将列表作为字符串传递,但以定义的格式传递:

  • Using ["a","b","c"]代替a,b,c允许立即使用OPENJSON().
  • Using <x>a</x><x>b</x><x>c</x>相反,允许 XML 查询。

这里最大的优势是:任何编程语言都提供对这些格式的支持。
日期和数字格式等常见问题已得到隐式解决。在大多数情况下,传递 JSON 或 XML 只需几行代码。
两种方法都允许类型和位置安全的查询。
我们可以解决我们的需求,而不需要依赖任何预先存在的东西。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当传递大的逗号分隔值时,使用自定义 TABLE TYPE 作为参数而不是 SQL“IN”子句是否更好 的相关文章

随机推荐