ビュー内の句の前にステートメント処理を選択します
-
12-11-2019 - |
質問
私は、以下のようにチャーディックスの部分文字列を選択するステートメントを持っています:
SELECT SUBSTRING(StringField, 5, CHARINDEX('ABC', StringField) - 5)...
WHERE
CHARINDEX('ABC', StringField) > 5
.
SELECTクエリで上記のステートメントを実行すると、結果はちょうど元に戻ります。スキーマバインドインデックスビューで上記のステートメントを実行すると、このエラーが発生します。
Invalid length parameter passed to the LEFT or SUBSTRING function
.
問題を解決するために、チャネルXexの最大値を取得し、0と0のマイナス値の可能性を除去する関数を書きます。しかし、誰かがWhere句がSELECTステートメントをフィルタアウトしないのかを知っていますか?
解決
クエリ内のシーンの後ろの操作の順序は保証されていないためです。
実行計画をチェックすると、両方のチェックが並行していると思うかどうかを確認します。
SQLは、そのフィールドのすべての行をメモリにロードする必要があるため、同時に両方の基準の処理を処理しています。
WITH (MAXDOP(1))
をクエリヒントとして試すことも、問題が表示されるかどうかを確認するか、実行順序を強制するために副選択を行うことができます。
.
SELECT SUBSTRING(StringField, 5, CHARINDEX('ABC', StringField) - 5)...
FROM (
SELECT Stringfield
FROM Table
WHERE CHARINDEX('ABC', StringField) > 5
) as [X]
私がPATINDEX
を使用してフィールドが数値で、私のビュー内の列の1つがこれをint
に変換していたかどうかを確認していたときにも同様の問題がありました。フィルターはサージキャブルではありませんでした。
他のヒント
これは醜い回避策ですが、あなたはおそらくこのようなものをすることができます:
DECLARE @x TABLE(StringField VARCHAR(32));
INSERT @x SELECT 'ABC'
UNION ALL SELECT 'A'
UNION ALL SELECT 'AAAAAAAABC';
SELECT SUBSTRING(StringField, 5, CHARINDEX('ABC', StringField) - 5)
FROM @x
WHERE CHARINDEX('ABC', StringField) > 5;
SELECT SUBSTRING(StringField,
CASE WHEN CHARINDEX('ABC', StringField) > 5 THEN 5 ELSE 1 END,
CHARINDEX('ABC', StringField) -
CASE WHEN CHARINDEX('ABC', StringField) > 5 THEN 5 ELSE 0 END)
FROM @x
WHERE CHARINDEX('ABC', StringField) > 5;
.
収量:
---
AAA
.
しかし、私はあなたの見解で後者が許されるのを疑っています。それは醜いですが残念ながら#tempテーブルを最初に#tempテーブルにダンプしていない限り(またはMAXDOP
が問題を確実に削除するかどうかを確認してください)あなたが処理の順序を多くのものにするのではありません。
もう1つのアイデアは、計算された列をテーブルに入れてみることです(ただし、索引付きビューを作成しようとしている場合は確かではありません - まだ複雑な場合があります)。または、索引付きビューの代わりに、その式でフィルタリングされたインデックスを使用するには。インデックス付きビューが何を達成し、どのバージョンのSQL Serverを使用しているのかを知っているのを知っていれば、いくつかの「解決策」があります。