SQL Server studio 函数变量范围错误

Posted

技术标签:

【中文标题】SQL Server studio 函数变量范围错误【英文标题】:SQL Server studio Function variable scope error 【发布时间】:2018-08-14 11:58:56 【问题描述】:

我试图使用一个函数作为练习,其中我有 2 个由 ; 分隔的字符串(例如:'1;22;333;444;;5555;666')和另一个格式相同的字符串。

我想检查在大数据集的情况下,两个字符串中是否有相同的元素

例子

@string1 : 'a','b','c' 
@string2 : 'a','g','c'

在这种情况下,我希望答案为假,因为 B 和 C 不在第二个字符串中。

示例 2

@string1 : 'a','b','c' 
@string2 : 'a','b','c'

在这种情况下,答案将是正确的。

到目前为止,我正在做这样的事情:

CREATE FUNCTION dbo.fnSplit(
    @sInputList VARCHAR(8000), -- List of delimited items
    @sDelimiter VARCHAR(8000) = ',' -- delimiter that separates items
    ) 
RETURNS @List TABLE (item VARCHAR(8000))
BEGIN
    DECLARE @sItem VARCHAR(8000)

    WHILE CHARINDEX(@sDelimiter, @sInputList, 0) <> 0
    BEGIN
        SELECT
            @sItem = RTRIM(LTRIM(SUBSTRING(@sInputList, 1, CHARINDEX(@sDelimiter, @sInputList, 0) - 1))),
            @sInputList = RTRIM(LTRIM(SUBSTRING(@sInputList, CHARINDEX(@sDelimiter, @sInputList, 0) + LEN(@sDelimiter), LEN(@sInputList))))

        IF LEN(@sItem) > 0
            INSERT INTO @List 
                SELECT @sItem
    END

    IF LEN(@sInputList) > 0
        INSERT INTO @List 
            SELECT @sInputList -- Put the last item in
    RETURN
END
GO

select * from dbo.fnSplit('1;22;333;444;;5555;666', ';')

导致

1
22
333
444
5555
666

然后我有另一个导致错误的函数:

CREATE FUNCTION dbo.fnSplitFinal(
    @sInputList VARCHAR(8000) -- List of delimited items (source string) 
  ,  @sInputList2 VARCHAR(8000) -- List of delimited items2(target string) 

  , @sDelimiter VARCHAR(8000) = ','  -- delimiter that separates items source 
  , @sDelimiter2 VARCHAR(8000) = ',' -- delimiter that separates items target
) RETURNS  Integer 

BEGIN
DECLARE @list1 TABLE (item VARCHAR(8000));
DECLARE @list2 TABLE (item VARCHAR(8000));
DECLARE @listFinal TABLE (item VARCHAR(8000), item2 Varchar(8000), Istrue varchar(50)) ;

--source 
Insert Into @list1 (Item) 
select * from master.dbo.fnSplit(@sInputList, ';')

--target
Insert Into @list2 (Item)  
select * from Master.dbo.fnSplit(@sInputList2,';')

--final 
insert Into @listFinal (Item, item2, istrue)
select a.item , b.item,
Case 
    when a.item = b.item then 'true'
    when a.item != b.item then 'false' 
    when a.item is not NULL and b.item is NULL then 'falseNULL'
else 'cc'
end as Istrue
from @list1 --> error here, out of scope?  
left Join @list2 
    on @list1.item = List2.item
Declare @result Integer 

select @result = (select count(*) from @listFinal where isTrue !="true" ) 

RETURN @result 
END
GO

这显示错误“必须声明一个标量变量@list1”

任何帮助都是有价值的,并且会带来新的学习!

【问题讨论】:

错误查询中的 a 和 b 别名是什么? 我强烈建议您将当前的拆分功能扔进垃圾桶。有许多选项比使用 while 循环更适合拆分字符串。这里有几个。 sqlperformance.com/2012/07/t-sql-queries/split-strings 【参考方案1】:

这对我有用:

ALTER FUNCTION dbo.fnSplitFinal(
    @sInputList VARCHAR(8000) -- List of delimited items (source string) 
  ,  @sInputList2 VARCHAR(8000) -- List of delimited items2(target string) 

  , @sDelimiter VARCHAR(8000) = ','  -- delimiter that separates items source 
  , @sDelimiter2 VARCHAR(8000) = ',' -- delimiter that separates items target
 ) RETURNS Integer 

BEGIN
DECLARE @list1 TABLE (item VARCHAR(8000));
DECLARE @list2 TABLE (item VARCHAR(8000));
DECLARE @result INT

--source 
Insert Into @list1 (Item) 
select * from dbo.fnSplit(@sInputList, @sDelimiter)

--target
Insert Into @list2 (Item)  
select * from dbo.fnSplit(@sInputList2,@sDelimiter2)

--final 
SELECT @result = COUNT(*)
FROM @list1
WHERE item NOT IN
      (
          SELECT item FROM @list2
      );

RETURN @result 
END
GO

我将您的@delimiter 参数放入函数中,为@result 变量添加了声明,并简化了最终查询。

【讨论】:

【参考方案2】:

感谢大家的支持。我终于想通了这一点。这是我对问题的解决方案。

ALTER FUNCTION dbo.fnSplitFinal(
    @sInputList VARCHAR(8000) -- List of delimited items (source string) 
  ,  @sInputList2 VARCHAR(8000) -- List of delimited items2(target string) 

  , @sDelimiter VARCHAR(8000) = ','  -- delimiter that separates items source 
  , @sDelimiter2 VARCHAR(8000) = ',' -- delimiter that separates items target
) RETURNS   @FinalResult TABLE (isTrue VARCHAR(8000), Missing varchar(2000))


BEGIN
DECLARE @list1 TABLE (item VARCHAR(8000));
DECLARE @list2 TABLE (item VARCHAR(8000));
DECLARE @listFinal TABLE (item VARCHAR(8000), item2 Varchar(8000), Istrue varchar(50)) ;

--source 
Insert Into @list1 (Item) 
select * from master.dbo.fnSplit(@sInputList, ';')

--target
Insert Into @list2 (Item)  
select * from Master.dbo.fnSplit(@sInputList2,';')

--final 
insert Into @listFinal (Item, item2, istrue)
select a.item , b.item,
Case 
    when ltrim(rtrim(a.item)) = ltrim(rtrim(b.item)) then 'true'  -- Matching Value found 
    when ltrim(rtrim(a.item)) !=ltrim(rtrim(b.item)) then 'false' -- There is a mismatch in the value // not able to join also. 
    when a.item is not NULL and b.item is NULL then a.item+' is missing in the target' 
    When b.item is NOT NULL and A.item is NULL then b.item+' in target, not in source' 
else 'CheckAgain'
end as Istrue
from @list1 a
left Join @list2 b 
    on a.item = b.item

DECLARE @error VARCHAR(8000) 
SELECT @error = COALESCE(@error + ', ', '') + istrue 
FROM @listFinal where istrue !='True'


Declare @result Integer 
select @result = (select count(*) from  @listFinal where Istrue != 'True') 

 IF @result > 0
  INSERT INTO @FinalResult(isTrue,Missing) SELECT 'false',@error --isTrue from @listFinal where Istrue!='true'

 IF @result = 0
  INSERT INTO @FinalResult(isTrue,Missing) SELECT 'True','NULL'

RETURN  
END
GO

保持 fnsplit 不变。

这是结果的截屏视频。

谢谢!

【讨论】:

以上是关于SQL Server studio 函数变量范围错误的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 及 Visual Studio的离线帮助文档

sql server中单引号拼接字符串(书写错误会出现错误"浮点值 XXXX 超出了计算机表示范围(8 个字节)。“XX”附近有语法错误。")

Python函数式编程,范围和变量。我哪里错了?

SQL Server2008函数大全(完整版)

SQL Server2008函数大全(完整版)

SQL Server2008函数大全(完整版)