2

テーブルに を定義するCHECK CONSTRAINTと、保存されている条件句が入力したものと異なる場合があります。
例:

Alter table T1 add constraint C1 CHECK (field1 in (1,2,3))

保存されているものを見る:

select cc.Definition from sys.check_constraints cc
inner join sys.objects o on o.object_id = cc.parent_object_id
where cc.type = 'C' and cc.name = 'T1';

そうですか:

([field1]=(3) OR [field1]=(2) OR [field1]=(1))

これらは同等ですが、同じテキストではありません。BETWEEN(句を使用する場合も同様の動作が発生します)。

これが起こらないことを望む理由はCHECK、制約を定義するために使用するテキストと格納されているテキストを比較することにより、すべての制約が正しいことをプログラムで確認しようとしsys.check_constraintsているためです。異なる場合は、制約を削除して再作成します。

ただし、これらの場合、それらは常に異なるため、プログラムは常に制約を再作成する必要があると考えます。

質問は:

  1. SQL Server がこの変換を行う既知の理由はありますか? 構文糖衣を少し取り除いて、句をより単純な形式で保存しているだけですか?
  2. この動作を回避する方法はありますか (SQL Server が変更するものと一致するように長い形式で制約句を記述する以外に) はありますか?
  3. チェック制約が「期限切れ」であり、再作成が必要かどうかを判断する別の方法はありますか?
4

1 に答える 1

2

SQL Server がこの変換を行う既知の理由はありますか? 構文糖衣を少し取り除いて、句をより単純な形式で保存しているだけですか?

Books Online やその他の場所に記載されている理由については知りません。ただし、SQL Server の内部的な目的のために正規化されていると思います。これにより、SQL Server が式を定義する際に (列名に を使用するなど) 少し寛容になる可能性がありますがDatabase、式を解析する必要があるエンジン (つまり、) に対して列名が常に適切にエスケープされることが保証されます[Database]

この動作を回避する方法はありますか (SQL Server が変更する内容に一致するように長い形式で制約句を記述する以外に) ?

おそらくそうではありません。しかし、制約がそれほど複雑でない場合、制約句を長い形式で書き直すのはそれほど悪い考えでしょうか?

チェック制約が「期限切れ」であり、再作成が必要かどうかを判断する別の方法はありますか?

これに直接答える前に、ここにはプログラミング哲学が少し関係していることを指摘しておきます。CHECK 制約のテキストに対して SQL Server が提供する API は、元の式と同等のものを取得することのみを保証します。確かに、SQL Server の正規化されたバージョンの式を常に再現できるようにするためにいくつかの凝った方法を構築することはできますが、Microsoft が将来正規化ルールを変更しないという保証はありません。実際、2 つの同等の式が常に同じように正規化されるという保証はおそらくありません。

したがって、最初にアーキテクチャを再検討し、文書化されていない API の動作に依存することなく同じ結果を達成できるかどうかを確認することをお勧めします。

そうは言っても、この質問(および回答)で概説されている方法はいくつかあります。

もう 1 つの方法は、もう少し強引ですが、おそらく受け入れられる方法ですが、式が「時代遅れ」であると常に想定し、確認するたびに制約をドロップ/再作成するだけです。これらの制約が頻繁に時代遅れになる (またはテーブルが非常に大きい) ことを予期していない限り、これは適切な解決策と思われます。新しい制約がすでに違反している場合は、単にトランザクションをロールバックしてエラーを報告するように、おそらくトランザクションで実行することもできます。

于 2013-03-16T02:14:15.507 に答える