web-dev-qa-db-ja.com

has_unchecked_Assembly_data = 1でマークされた永続的な計算されたCLR発信データのテーブルですが、DBCC CHECKTABLEはこの同じフラグの設定を解除しません

列を持つOrderLinesテーブルがあります。

Quantity int not null
QtyCancelled int not null
QtyBackorder int not null
QtyPicking int not null
QtyPacking int not null
QtyShiped int not null

計算および永続化された列FulfillmentStatusIdは次のようになります。

dbo.clr_GetFulfillmentStatusByLineQuantities(Quantity, QtyCancelled, QtyBackorder, QtyPicking, QtyPacking, QtyShiped)

「clr_GetFulfillmentStatusByLineQuantities」は、もちろん、次のようにマークされた関連メソッド(C#)でデータベース内のアセンブリにスカラー関数を介してマップされます。

[SqlFunction(DataAccess = None, IsDeterministic = true, IsPrecise = true, SystemDataAccess = None)]

この質問 を参照して、このテーブルに対してDBCC CHECKTABLEを実行しました複数回、それでもhas_unchecked_Assembly_data = 1のままです。これは、列が最初にテーブルに追加されたときに当てはまりましたが、SQL 2016への移行前にDBCC CHECKTABLEコマンドが成功したと思います。


テーブルはhas_unchecked_Assembly_data = 1で長期間使用されていますが、テーブルの機能に影響はないようです。私amは、ALTERアセンブリがWITH UNCHECKED DATAを使用していないときに例外をスローし、次にanother私がdidを使用すると例外が発生するが、とにかく「MVIDに従って」アセンブリを更新しているように見える。

とりとめなくても申し訳ありませんが、あまり質問しすぎず、ほとんどの場合潜んでいます。

ただし、事前に感謝します!


アップデート(20180917T17:34-05:00):最初の指示を提案してくれたSeanに感謝します。 DBCC CHECKTABLE( 'OrderLines')WITH EXTENDED_LOGICAL_CHECKSの結果は、次のような2行でした。

Msg 2537, Level 16, State 106, Line 1
Table error: object ID 1486732449, index ID 1, partition ID 72057594403946496, alloc unit ID 72057594422755328 (type In-row data), page (1:1430554), row 5. The record check (valid computed column) failed. The values are 38 and 0.

そこで、テーブルの主キー(上記のインデックスID 1)に対してREBUILDを実行しましたが、成功しました。ただし、DBCC CHECKTABLE( 'OrderLines')WITH EXTENDED_LOGICAL_CHECKSを再実行すると、同様のエラーが再び返され、今回は異なるパーティションIDとアロケーションユニットID(期待してください)。

極端な解決策は、いわば「挿入からサイトを軌道に乗せる」というID挿入を使用してテーブルを削除、再作成、および再設定することですが、明らかな理由から、これはextreme

「テーブルのクラスター化インデックスに一貫性のない計算列データがあるようです」に対する正しい解決策は何ですか?

6
JW-OP

ここにOP、自分の(そして最初の)質問に答える!

Sean Gallardyの助けにより、_EXTENDED_LOGICAL_CHECKS_を使用すると、永続化された計算列のデータとの不整合が指摘されました。最初に主キー(クラスター化インデックス)を再作成してみましたが、実際には何も修正されませんでした(極端で奇妙な解決策)。

私もDBCC CHECKTABLE ('{table}', REPAIR_ALLOW_DATA_LOSS)を使用してみましたが、同じエラーが再び返されました。何も修理されなかったと思います。

私の最初の解決策は、永続的な計算列を削除して再作成することでした。これは機能しました。

しかし、これもやや「極端」であると考えた場合(テーブルに10M以上の行があり、この列に対するインデックスもあるため、これを行うには永久に時間がかかると考える)、より直接的な解決策に興味がありました。

_DBCC CHECKTABLE_withによって報告された行は2つしかなかったため、ページと行の参照は_DBCC PAGE_を調べました。このコマンドを正確に使用すると、実際の行データ/行IDが得られ、計算列を駆動するCLRメソッドを実行したときに、実際に不整合がありました。

基本的な実際の一貫性のないテーブルデータ:

_OrderLineId  QtyOrd  QtyCancl  QtyBack  QtyPick  QtyPack  QtyShip  FulfillId
    1234567       4        12        0        0        0        0          0
    4567890       4        12        0        0        0        0          0
_

この場合のFulfillIdは1(キャンセル済みを表す)である必要がありますが、これらの2つのテーブル行は両方の行で0(開いている/満たされていない)を示しています。

SELECTステートメントを使用して、CLR関数を介して実際の行データを実行しました。

_select
  ol.OrderLineId,
  ol.QtyOrd, ol.QtyCancl, ol.QtyBack, ol.QtyPick, ol.QtyPack, ol.QtyShip,
  ol.FulfillId [CurrentFulfillId],
  CLR(ol.QtyOrd, ol.QtyCancl, ol.QtyBack, ol.QtyPick, ol.QtyPack, ol.QtyShip) [ComputedFulfillId],
from
  OrderLines [ol]
where
  ol.OrderLineId in (1234567, 4567890)
_

これは基本的にまったく同じ情報を返し、ComputedFulfillIdも0(オープン)に解決されます。したがって、.NETコンソールアプリケーションでCLRコードを直接再テストし、SQL呼び出しでshouldが渡されていることを明示的に示すと、結果は期待値1(キャンセル)。

SELECTステートメントを変更して、疑わしい行の値の代わりに明示的な定数値を使用するCLRメソッドの呼び出しを含めました。

_SELECT ..., CLR(4, 12, 0, 0, 0, 0) [ForcedFulfillId] FROM OrderLines [ol] ...
_

また、ForcedFulfillId列には正しい値1が含まれていました。

DBCC PAGEを使用して正確な行IDを検索し、問題の行を更新すると、計算された列データが再計算されます。最後の_DBCC CHECKTABLE_はエラーを返さず、すべてが再び良好でした。

したがって、計算された列全体を削除して再作成するのではなく、DBCC CHECKTABLE({table}) WITH EXTENDED_LOGICAL_CHECKSからの情報とともに_DBCC PAGE_を使用すると、_ALTER Assembly_エラーを引き起こす元の「has_unchecked_Assembly_data = 1」の問題を修正できました。

[〜#〜] whew [〜#〜]

長い説明で申し訳ありません。次の貧しい魂のために私の旅行を確実に文書化したかったのです。

7
JW-OP