2

私は2つのテーブルを持っています。

DECLARE @definitions TABLE
( fDefId varchar(8)   ,
  dType  varchar(MAX) ,
  fName  varchar(MAX)
)

INSERT @definitions values('8c7eab0e','string','custpartno')
INSERT @definitions values('8c7eab02','int'   ,'itemno'    )

DECLARE @fields TABLE
( rowId varchar(8)   ,
  fkFId varchar(8)   ,
  adj   varchar(MAX)
)

INSERT @fields values('83EDE211','8c7eab0e','89319971151801')
INSERT @fields values('83EDE211','8c7eab02','1'             )

@fields値が ではなく、テーブルint内の関連レコードの値が であるレコードを検索しようとしています。@definitionsdType'int'

この結果のリスト (ある場合) を取得しようとすると、次のステートメントを試しました。

SELECT f.rowId ,
       f.fkFId ,
       f.adj   ,
       d.fName
  FROM @fields      f
  JOIN @definitions d ON  f.fkFId = d.fDefId
                      AND d.dType = 'int'
  WHERE ISNUMERIC( adj        ) <> 1
     OR CAST(      adj AS INT ) <> adj

SELECT *
FROM ( SELECT f.rowId ,
              f.fkFId ,
              f.adj   ,
              d.fName
       FROM @fields      f
       JOIN @definitions d ON  f.fkFId = d.fDefId
                           AND d.dType='int'
     ) a
WHERE ISNUMERIC( adj        ) <> 1
   OR CAST(      adj AS INT ) <> adj

両方でこのエラーが発生しました:

The conversion of the varchar value '89319971151801' overflowed an int column.

ただし、最初に値を次のようにテーブル変数に格納すると、次のようになります。

DECLARE @temp TABLE
( rowId    varchar(8),
  fDefId   varchar(8),
  adjusted varchar(MAX)
)

INSERT @temp
SELECT f.rowId ,
       f.fkFId ,
       f.adj
FROM @fields      f
JOIN @definitions d ON  f.fkFId = d.fDefId
                    AND d.dType = 'int'

SELECT * FROM @temp
WHERE ISNUMERIC( adjusted        ) <> 1
   OR CAST(      adjusted AS INT ) <> adjusted

期待どおりの結果が得られます (この例ではレコードはありません)。

句を削除すると、WHERE次の結果が得られます。

ここに画像の説明を入力

大きなフィールドを含む行が存在しないのに、? を追加した後にエラーが発生するのはなぜWHEREですか?

BIGINTの代わりにas をキャストすることで問題を回避することもできますが、 and句が最初からではない値を削除するINTので、なぜそれが問題になるのでしょうか?JOINWHEREINT

4

1 に答える 1

1

SQL 標準には、式の評価の特定の順序や式の評価の短絡を義務付ける要件がないことをご存知ですか? クエリ オプティマイザーは、セマンティックな意味 (意図ではない) が維持されている限り、クエリ全体を自由に再配置できます。

datetype = 'int'クエリ プロセッサでの操作の順序が強制されるため、2 回目の刺し傷、事前フィルター処理とフィルター処理された結果の読み込みが機能します。

式のため、単一クエリの試行は失敗します

CAST( adj AS INT ) <> adj

どれの

  • かかるvarchar
  • に変換しますint
  • それをintに戻しvarchar、最後に...
  • varchar(の正規化/正規化された文字列表現を含むint) を元の値と比較しvarcharます。

失敗します。クエリ プロセッサは、列に含まれているかどうかに関係なく、すべての候補行に対してその式を評価する必要があるため、失敗します。datatypeint

fromオプティマイザーは、派生テーブルを使用しないようにクエリをリファクタリングできることを十分に認識できるため、句に派生テーブルを使用した 2 回目の単一クエリの試行は失敗します。

もちろん、本当の問題は、非正規化されたデータベース設計があり、列の意味 (およびデータ型) を過負荷にadjして、単一のテーブルを複数のものにしようとしているということです。

于 2013-07-15T20:47:33.637 に答える