1

状況:

私はしばしば(データベースに関するコメントはありません、それは歴史です:))値が区切られた列を持っています。

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)

実行後、次のようになりました。

mode=tree は int 型に変換できません

え?最初の値のみを取得しIdます (結果を再確認しました) が、2 番目の値も変換しようとします。そのため、SQL Server は実行時に異なる方法で処理しているようです。

質問:

では、実行計画がこの動作をどのように処理するかを制御することは一般的に可能ですか?

サイドノート:

私は今これをやって解決しました:

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

文字列に & が含まれているかどうかを確認し、含まれている場合は によって見つかった長さの LEFT 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
4

1 に答える 1

1

分割関数が不特定の順序でデータを返しているようです。この問題を解決するには、その関数を変更して、毎回期待される順序で結果を返すようにします。

関数の実装方法によっては、ORDER BY ステートメントを追加することでこの動作を修正できる場合があります。SQL Server は、既定でセットが特定の順序で返されることを保証しません。

于 2012-11-10T17:30:01.110 に答える