我有一个奇怪的问题,偶尔只会发生。我已经运行了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列添加到临时表中,因此我可以对输出进行排序,但它没有任何区别。
答案 0 :(得分:2)
如果您没有放置显式的ORDER BY语句,则SQL不保证您的订购。
即便是一个像你一样简单的例子 - 你希望内部应该像你想要的那样运作 - 表明事实并非如此。
解决方案:如果订单很重要,请添加ORDER BY。我知道你没有什么可以排序,所以也许修改你的拆分功能,以便它吐出两列:值和索引;然后,您可以对索引进行排序。
答案 1 :(得分: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-Server