2012-11-06 26 views
1

现状:我可以控制SQL Server处理其执行计划的方式吗?

我经常(在数据库中没有任何评论,这是历史:)),其中值被分离出列。

假设我们有一个列params其中包含例如1,2,3,4,5

如果我需要基于值的表格,我将它们与dbo.fn_Split()函数分离(可以在网上找到几个版本 - 但在此范围之外)。所以我得到我的虚拟表。

今天我遇到了一个情况,我有一个专栏,我有这个内容110&mode=tree

正如我所需要的只是ID我对自己说......像往常一样,分裂,只得到第一个值:

SELECT TOP 1 [value] FROM dbo._fnSplit('110&mode=tree','&') 

正如我所需要的值作为INT我添加了一个CAST()在其周围。

CAST((SELECT TOP 1 [value] FROM dbo._fnSplit('110&mode=tree','&')) AS int) 

现在执行后,我得到了:

模式=树不能被转换成int类型

胡赫?我得到的第一个值是Id(我仔细检查了结果),但它仍然尝试转换第二个值。因此,SQL Server似乎在执行过程中对它进行了不同的处理。

问:

那么,这通常可以控制执行计划如何处理这个问题?

旁注:

我解决它现在这样做:

[...] WHERE id = CAST((CASE WHEN k.param LIKE '%&%' THEN LEFT(k.swindowparam,PATINDEX('%&%',k.param)-1) ELSE k.swindowparam END) AS int)) 

检查字符串包含&如果是这样一个长度为向左PATINDEX发现。

编辑:

这里是分割功能:

CREATE FUNCTION dbo.fn_Split(@text nvarchar(4000), @delimiter char(1) = ',') 

RETURNS @Strings TABLE 
(
position int IDENTITY PRIMARY KEY, 
value nvarchar(4000) 
) 

AS 
BEGIN 

DECLARE @index int 
SET @index = -1 

SET @text = RTRIM(LTRIM(@text)) 

WHILE (LEN(@text) > 0) 
BEGIN 
SET @index = CHARINDEX(@delimiter , @text) 
IF (@index = 0) AND (LEN(@text) > 0) 
BEGIN 
INSERT INTO @Strings VALUES (@text) 
BREAK 
END 
IF (@index > 1) 
BEGIN 
INSERT INTO @Strings VALUES (LEFT(@text, @index - 1)) 
SET @text = RIGHT(@text, (LEN(@text) - @index)) 
END 
ELSE 
SET @text = RIGHT(@text, (LEN(@text) - @index)) 
END 
RETURN 
END 

回答

1

这听起来像你的分割功能是在指定顺序返回数据。为了解决这个问题,我会改变这个函数,使它每次都以预期的顺序返回结果。

根据函数的实现方式,您可以通过添加ORDER BY语句来纠正这种行为。 SQL Server不保证默认情况下将以任何特定顺序返回一个集合。

+0

我已经添加了ORDER BY,因为我的分割函数返回值和位置列。所以我按ASC排序,但错误仍然是一样的。这仍然让我感到困惑。 – YvesR

+0

您是否可以发布拆分功能? – Narthring

+0

我给这个问题增加了功能。 – YvesR