【问题标题】:Calculated Parameter in WHEREWHERE 中的计算参数
【发布时间】:2015-11-17 00:07:54
【问题描述】:

我正在尝试在我的查询的where 语句的IN 列表中使用回车分隔的参数列表。

我可以使用replace 函数将列表转换为正确格式的逗号分隔字符串,但是当我将其放入IN 列表时,它什么也不返回。

下面的查询按预期返回逗号分隔的列表。

declare @VarCodes varchar(max)
set @VarCodes = '123-1
123-10
123-100
61
66
67
75'
(select  ''''+replace(replace(REPLACE(@VarCodes,char(13),''''+', '+''''),char(32),''),char(10),'')+'''')

'123-1','123-10','123-100','61','66','67','75'

如果我将此文本直接粘贴到下面的查询中,它会按预期返回数据。

select vad_variant_code from  variant_detail where vad_variant_code in ('123-1','123-10','123-100','61','66','67','75')

如果我将参数放在in 中,它不会返回任何内容。

select vad_variant_code from  variant_detail where vad_variant_code in ((select  ''''+replace(replace(REPLACE(@VarCodes,char(13),''''+', '+''''),char(32),''),char(10),'')+''''))

我假设这是因为 IN 需要一个逗号分隔的字符串列表,而 replace 函数返回一个长字符串?

这可以实现吗?

【问题讨论】:

标签: sql-server tsql


【解决方案1】:

试试这个...

declare @VarCodes varchar(max), @Xml XML;
set @VarCodes = '123-1,123-10,123-100,61,66,67,75'

SET @Xml = N'<root><r>' + replace(@VarCodes, ',','</r><r>') + '</r></root>';


select vad_variant_code from  variant_detail 
where vad_variant_code in (
                           select r.value('.','varchar(max)') as item
                           from @Xml.nodes('//root/r') as records(r)
                          )

【讨论】:

  • 谢谢。速度在这里并不是真正的问题,因为最多有 20 个变量。我稍微修改了您的选择,因为我的列表不是字符分隔的,而是回车。没问题,我只是更改了 XML 选择中的替换。 SET @Xml = N'' + replace(replace(@VarCodes,char(10),''), char(13),'') + '';
【解决方案2】:

我将此代码作为 TVF 最初基于 Jeff Moden 的代码:

CREATE FUNCTION [dbo].[cSplitter] (@Parameter VARCHAR(MAX))
RETURNS @splitResult TABLE (number INT, [value] VARCHAR(100))
AS
BEGIN
SET @Parameter = ','+@Parameter +',';

WITH cteTally AS
    (
        SELECT TOP (LEN(@Parameter))
            ROW_NUMBER() OVER (ORDER BY t1.Object_ID) AS N
            FROM Master.sys.All_Columns t1
            CROSS JOIN Master.sys.All_Columns t2
    )
INSERT @splitResult
    SELECT ROW_NUMBER() OVER (ORDER BY N) AS Number,
    SUBSTRING(@Parameter,N+1,CHARINDEX(',',@Parameter,N+1)-N-1) AS [Value]
    FROM cteTally
        WHERE N < LEN(@Parameter) AND SUBSTRING(@Parameter,N,1) = ','
RETURN
END

在我的数据库中使用这个 TVF,我的“IN”查询可以接受一个逗号分隔的值列表,如下所示:

DECLARE @VarCodes VARCHAR(MAX);
SET @VarCodes = '123-1
123-10
123-100
61
66
67
75';

DECLARE @csv VARCHAR(MAX);
SET @csv = REPLACE(REPLACE(REPLACE(@VarCodes, CHAR(13), ','), CHAR(32), ''),
                   CHAR(10), '');

SELECT  vad_variant_code
FROM    variant_detail
WHERE   EXISTS ( SELECT *
                 FROM   [cSplitter](@csv) AS [cs]
                 WHERE  [cs].[value] = vad_variant_code );

【讨论】:

  • 这很酷,但对于一个相当简单的任务来说很痛苦:(,我用两行完成了整个事情,请参阅我的答案:)
  • 行数更少并不意味着它更好。您正在使用在这种情况下我不建议使用的 xml,而且您假设它是逗号分隔值,但事实并非如此(请参阅 OP)。实际上,我懒得添加更多内容,因为 SQL 服务器在字符串操作方面非常慢,我真的建议将该 TVF 创建为 CLR 函数(我在现实生活中这样做 - 存在巨大的性能差异,使用 xml情况更糟)。
  • 真正的代码行更少并不意味着它的性能也会更好,但是您建议的代码正在逐个字符地进行字符串操作,我认为任何事情都会比这更快:)
  • I would really suggest creating that TVF as a CLR function 如何创建 TVF 作为 CLR 函数?它根本没有任何意义????
  • 好吧,我的意思是无论如何我都不建议使用 XML(实际上在论坛中,我将该选项列为第 3 或第 4 选项并对其进行采样)。这是一条关于它的论坛消息,其中包含 CLR 代码和示例(故事部分是土耳其语,但无论如何您需要的是代码部分):social.msdn.microsoft.com/Forums/tr-TR/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-02
  • 1970-01-01
  • 1970-01-01
  • 2019-06-20
  • 1970-01-01
  • 1970-01-01
  • 2014-10-12
相关资源
最近更新 更多