1

我有一个奇怪的问题,只是偶尔发生。我已经运行了 10000 次,在不同的时间出现 2 个错误、12 个错误和没有错误。

这是我的测试脚本,它尝试了 10000 次并输出错误的脚本

declare @i int
set @i = 10000

declare @v varchar(200)

while @i > 0
begin
    SELECT top 1 @v = val
    FROM f_split_string('a,b,c,d,e,f',',')
   if @v != 'a'
       print @v
   set @i = @i - 1
end

这是f_split_string功能:

CREATE FUNCTION [dbo].[f_split_string] (@s nvarchar(max), @delim nvarchar(10))
-- returns a table from a delimited string
-- Parameters:
--    @s                The delimited string
--    @delim            The delimiter characters
-- Example:
--    SELECT val FROM f_split_string('a b c',' ')
RETURNS @t TABLE (id int, val nvarchar(max))
AS
BEGIN
      DECLARE @c int, @v nvarchar(max)
      SET @c = 1
      SET @v = dbo.f_element(@s, @delim, @c)
      WHILE @v IS NOT NULL
      BEGIN
            INSERT INTO @t (id,val) VALUES (@c,@v)
            SET @c = @c + 1
            SET @v = dbo.f_element(@s, @delim, @c)
      END

      RETURN
END

这是f_element功能:

CREATE FUNCTION [dbo].[f_element](@Input varchar(max), @Delimiter varchar(10), @ElementNumber int)
-- returns an element from a delimited string
-- Example:
--   SELECT dbo.f_element('abc|def|ghij', '|', 2)
--     will return the 2nd element - def
RETURNS varchar(max)
AS
BEGIN
      DECLARE @Pointer INT, @Count INT, @Last INT, @retVal varchar(max)
      SET @Pointer = 1
      SET @Count = 1
      SET @Last = 1

      WHILE (@Count < @ElementNumber)
      BEGIN
            SET @Pointer = CHARINDEX(@Delimiter,@Input,@Pointer)
            IF @Pointer = 0
                  BREAK

            SET @Pointer = @Pointer + DATALENGTH(@Delimiter)
            SET @Count = @Count + 1
      END

      IF @Pointer = 0 OR @ElementNumber < 1
            SET @retVal = null;
      ELSE IF SUBSTRING(@Input,@Pointer,DATALENGTH(@Delimiter)) = @Delimiter
            SET @retVal = '';
      ELSE
      BEGIN
            SET @Last = @Pointer

            SET @Pointer = CHARINDEX(@Delimiter,@Input,@Last+1)

            IF @Pointer = 0
                  SET @retVal = SUBSTRING(@Input, @Last, 9999)
            ELSE
                  SET @retVal = SUBSTRING(@Input, @Last, @Pointer - @Last)
      END

      RETURN @retVal
END

这正在 SQL Server 2008(不是 R2)上进行测试

首先,其他人是否会在我的测试脚本中出现错误,其次,为什么会发生这种情况?

我已经运行 f_element 函数 200000 次没有问题,所以怀疑 f_split_string 函数,但它可能是从 f_split_string 调用时的 f_element 函数

我在单用户 SQL Server 2008 R2 上运行它没有问题,2008 有多个用户

有谁能够帮我

错误是分隔字符串的错误部分。它应该是a,但有时它是其他部分。就好像这些行以错误的顺序插入到临时表中一样。我将 id 列添加到临时表中,以便对输出进行排序,但没有任何区别。

4

2 回答 2

2

如果您不使用明确的 ORDER BY 语句,SQL 将无法保证您的排序。

即使是像您这样简单的示例(您希望内部结构应该像您希望的那样工作)也表明情况并非如此。

解决方案:如果订单很重要,请添加 ORDER BY。我知道你没有什么要排序的,所以也许修改你的 split 函数,让它吐出两列:值和索引;然后您可以对索引进行排序。

于 2013-09-02T15:58:20.130 回答
0

除了我之前的答案,也许我可以指出另一个选择。

如果在您的数据库中使用 CLR 过程是您的一个选项,那么这是 CLR 代码比 T-SQL 更高效的工作。此外,由于 CLR 函数被 SQL Server 视为不透明的枚举器,因此您可能依赖于SELECT * FROM dbo.clr_func()与枚举器的顺序相同clr_func,尽管我猜您不应该尝试碰运气并使查询比那。

因为我看不出这样一个简单的 SELECT 的意义,所以你可能不得不转向 ORDER BY 来处理更严肃的事情。

如果您对此选项感兴趣,可以查看本文的使用 CLR部分:http: //www.codeproject.com/Articles/17802/Use-Table-Valued-Functions-as-Arrays-in- SQL 服务器

于 2013-09-02T16:08:39.460 回答