SQL Server 2016を使用して、このT-SQLステートメントの実行中にこの警告が表示される理由を理解しようとしています(テストを簡単にするためにテーブル変数を選択しました。これは、int
タイプの列を持つDBテーブルで発生します上手):
_declare @test as table(
col1 int
)
insert into @test (col1)
values(30500600)
select LEFT(test.col1, 2)
from @test as test
_
_30
_は期待どおりに返されますが、実行プランを調べると、次のようなSELECT
ステートメントの警告が表示されます。
式の型変換(CONVERT_IMPLICIT(varchar(12)、[test]。[col1]、0))は、クエリプランの選択で「CardinalityEstimate」に影響する可能性があります
テーブルからプルせずに上記を同じように実行した場合:
_select LEFT(30500600, 2)
_
期待どおり_30
_が返され、実行プランに警告はありません。
どちらのステートメントもint
タイプに対してLEFT()
を実行する必要があるため、一方が警告を返し、他方が警告を返さない理由がわかりません。何が起きてる?
編集:
_col1
_データ型宣言をvarchar
に変更してみましたが、エラーは解消されました。しかし、それでもint
をselect LEFT(30500600, 2)
関数に直接渡した場合にLEFT()
自体が警告を引き起こさない理由を説明していません。
元のクエリでcast
からvarchar
を試しましたが、同じ警告を返すLEFT(cast(test.col1 as varchar(12)), 2)
です。
可能性のある重複
リンクされた重複は、計算された列がそのユーザーの問題であったと述べています。私の例では計算された列がないので、それは問題ではありません。これは、CONCAT
関数でも同じであるLEFT
関数を使用した文字列型への暗黙的な変換に関する回答の2番目の部分につながります。上記の編集の2番目の段落では、CAST
を使用して明示的にvarchar
に変換したので、変換が行われるとは思いませんか?ここに何か欠けているのは明らかです。
このクエリに「型変換/カーディナリティの見積もり」の警告がない理由:
SELECT LEFT(30500600, 2);
...基数の見積もりがないためです。これは、決定的な関数に渡される定数式です。「行」が1つだけ返されることが保証されています。警告は潜在的なカーディナリティーの問題(タイプ変換の単純な存在ではなく)に関するものなので、説明はそれと同じくらい簡単だと思います。
そのステートメントの推定実行プランを取得する場合、それは単一の「クエリなしの選択」要素です。
<?xml version="1.0" encoding="utf-16"?>
<ShowPlanXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Version="1.518" Build="13.0.5081.1" xmlns="http://schemas.Microsoft.com/sqlserver/2004/07/showplan">
<BatchSequence>
<Batch>
<Statements>
<StmtSimple StatementCompId="1" StatementId="1" StatementText="select LEFT(30500600, 2)" StatementType="SELECT WITHOUT QUERY" RetrievedFromCache="false" />
</Statements>
</Batch>
</BatchSequence>
</ShowPlanXML>
価値があるのは、テーブル変数のバージョンでさえ、SQL Server2017で警告が表示されないことです(変換が可能な場合、それは実際には無意味な警告であるためです) tは、カーディナリティーの見積もりに影響を与える可能性があります(例のように)。
明確にするために、その警告はalways無意味ではありません。この例を見てみましょう:
SELECT message_id
INTO #SomeNumbers
from sys.messages;
SELECT *
FROM #SomeNumbers
WHERE LEFT(message_id, 2) = '50';
これにより、一時テーブルに280,192行が挿入されます。 SELECTクエリにはこの警告があり、警告は正当です。 SQL Serverでは、実際に一致する行が2,156のみ(テーブルの1%未満)であるのに、28,019.2の一致する行(テーブルの10%)があると推定しています。
この入力をLEFT
関数にキャストする例については、警告がCONVERT_IMPLICIT
からCONVERT
にわずかに変更されていることに注意してください。
式の型変換(CONVERT(varchar(12)、[test]。[col1]、0))は、クエリプランの選択で "CardinalityEstimate"に影響する可能性があります
つまり、暗黙の変換を明示的な変換に置き換えるだけであり、それでも警告が必要です。
これは実際に予想されることです。 this を見てください。
LEFT(character_expression、integer_expression)
Character_expression:
文字またはバイナリデータの式です。 character_expressionには、定数、変数、または列を指定できます。 character_expressionは、textまたはntextを除き、暗黙的にvarcharまたはnvarcharに変換できる任意のデータ型にすることができます。それ以外の場合は、CAST関数を使用して、character_expressionを明示的に変換します。
Col1をVARCHAR(100)に変更すると、警告は消えます。テスト目的でのみ試してください。