文字列を分割する機能があります(分かりやすくするために最後に貼り付けています)。 この機能は単独で使用すると期待どおりに機能します。 例:"WHERE ... IN"節に含まれるudfの奇妙なエラー
SELECT value
FROM dbo.mg_fn_Split('2#1','#')
戻り
-- value --
-- 2 --
-- 1 --
-----------
しかし、この例のように "IN" 句、(にtableAの詳細後で)で使用した場合:
SELECT * FROM TableA WHERE TableA.id IN
(
SELECT value
FROM dbo.mg_fn_Split('2#1','#')
)
私が手エラー:「無効な長さパラメータがLEFTまたはSUBSTRING関数に渡されました。」
ここでは例として表Aを使用しています。異なるテーブルを使用すると(IDカラムがあると仮定して)、正しい結果を返すことがありますが、他のテーブルではエラーが発生します。
私はそれが実行の順序と関係があると仮定していますが、私はまだ何が関数を "破損"する可能性があるのか見当たりません。
私は「何が起きているのか」という説明を探しています。「これを代わりに使用する」ではありません。たとえば結果を得るためにジョインを使用できることはわかっています。
関数の定義:
-- Description: Returns a table containing the results of a string-split operation.
-- Params:
-- DelimitedList: The string to split
-- Delimiter: The delimiter char, defaults to ','
-- Columns:
-- Position - The char index of the item
-- Value - The actual item
-- =============================================
CREATE Function [dbo].[mg_fn_Split]
(
@DelimitedList nvarchar(max)
, @Delimiter nvarchar(2) = ','
)
RETURNS TABLE
AS
RETURN
(
With CorrectedList As
(
Select Case When Left(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End
+ @DelimitedList
+ Case When Right(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End
As List
, Len(@Delimiter) As DelimiterLen
)
, Numbers As
(
Select TOP(Coalesce(DataLength(@DelimitedList)/2,0)) Row_Number() Over (Order By c1.object_id) As Value
From sys.columns As c1
Cross Join sys.columns As c2
)
Select CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen As Position
, Substring (
CL.List
, CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen
, CharIndex(@Delimiter, CL.list, N.Value + 1)
- (CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen)
) As Value
From CorrectedList As CL
Cross Join Numbers As N
Where N.Value <= DataLength(CL.List)/2
And Substring(CL.List, N.Value, CL.DelimiterLen) = @Delimiter
)
EDIT:私はこれを発揮するフィドルを設定している: http://sqlfiddle.com/#!3/9f9ff/3
インラインUDFがクエリに展開されるため、おそらく一部の結合操作またはフィルタが期待していなかった別の順序で評価されています。 –
結合を使用しない理由は何ですか? IMHO可能であれば、SQLコマンドから文字列解析を離れることをお勧めします。 –
私はMartinのコメントに同意します。あなたのWHERE句があなたのSelect *からTableAにプッシュされていると思います。あなたの関数の中で以下のAnd Substring(CL.List、N.Value、CL.DelimiterLen)= @Delimiterをコメントアウトすると、-1と評価されるSubstring値の1つによって引き起こされる同じ問題が発生します。 –