列を持つ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。
「テーブルのクラスター化インデックスに一貫性のない計算列データがあるようです」に対する正しい解決策は何ですか?
ここに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 [〜#〜]
長い説明で申し訳ありません。次の貧しい魂のために私の旅行を確実に文書化したかったのです。