web-dev-qa-db-ja.com

複数の結合テーブルのビューを更新する

MSDNは多くのことを述べていないので、次のクエリを実行するとどうなりますか?

update claims set status='Awaiting Auth.'
where status = 'Approved' 

リンクテーブルClaimStatusNamedimClaimStatus列を使用して、外部キーを介して参照されるメインテーブルを更新できますか?

ビュー自体が複数のテーブルをクエリします。メインテーブルはtabDataです。これも上記のクエリで更新します。 fiClaimStatustabDataを、参照されているテーブルApprovedの__meansdimClaimStatusからAwaiting Auth.へのFKから変更します。このように機能しますか?

TabDataの行ごとに1つのビュー行のみが可能です。

これがビューです:

CREATE VIEW [dbo].[Claims] 
AS 
  SELECT mu.MarketUnitName AS MarketUnit, 
         c.CountryName     AS Country, 
         gsp.GSPName       AS GSP, 
         gsp.WCMSKeyNumber AS GspNumber, 
         sl.SLName         AS SL, 
         sl.WCMSKeyNumber  AS SlNumber, 
         m.ModelName       AS Model, 
         m.SalesName       AS [Model-Salesname], 
         s.ClaimStatusName AS [Status], 
         d.Work_Order      AS [Work Order], 
         d.SSN_Number      AS IMEI, 
         .... more columns ....
         idData,         -- PK of main table tabData
         fiSL, 
         fiModel, 
         fiClaimStatus  -- FK to dimClaimStatus
  FROM   tabData AS d 
         INNER JOIN locSL AS sl 
                 ON d.fiSL = sl.idSL 
         INNER JOIN locGSP AS gsp 
                 ON sl.fiGSP = gsp.idGSP 
         INNER JOIN locCountry AS c 
                 ON gsp.fiCountry = c.idCountry 
         INNER JOIN locMarketUnit AS mu 
                 ON c.fiMarketUnit = mu.idMarketUnit 
         INNER JOIN modModel AS m 
                 ON d.fiModel = m.idModel 
         INNER JOIN dimClaimStatus AS s 
                 ON d.fiClaimStatus = s.idClaimStatus 
         INNER JOIN tdefProductType 
                 ON d.fiProductType = tdefProductType.idProductType 
         LEFT OUTER JOIN tdefServiceLevel 
                      ON d.fimaxServiceLevel = tdefServiceLevel.idServiceLevel 
         LEFT OUTER JOIN tdefActionCode AS ac 
                      ON d.fimaxActionCode = ac.idActionCode 

更新

テーブルには2000万件の顧客レコードが含まれているため、実行する前にまず何が起こるかを知りたいと思いました。コメントと回答の後、私は今それを実行しました。即時の結果は:

(1 row(s) affected)

これは驚くべきことです。このステータスには数千のレコードがあり、現在更新されているようです。

アップデート2

実際には期待どおりに動作せず、疑わしい(1 row(s) affected)は正しかった。参照されたテーブルのみが更新されました。したがって、ステータスApprovedAwaiting Auth.に変更されました。

結論:

これは、ビューを使用して更新を行わないようにする最良の方法のようです。これは私の場合に機能します:

UPDATE tabData 
SET fiClaimStatus = (SELECT idClaimStatus
                     FROM dimClaimStatus
                     WHERE ClaimStatusName = 'Awaiting auth.')
WHERE fiClaimStatus=(SELECT idClaimStatus
                     FROM dimClaimStatus
                     WHERE ClaimStatusName = 'Approved')
6
Tim Schmelter

一般的なビューの更新可能性

CREATE VIEW (Transact-SQL) documentation の重要な部分は次のとおりです。

通常、データベースエンジンは、ビュー定義から1つのベーステーブルへの変更を明確に追跡できる必要があります。

クエリプロセッサの制限により、ビューが技術的に更新可能であっても、実際には実際には更新できないことに注意してください。推論。それは、「...データベースエンジンが...できる必要がある」というフレーズの背後にある微妙な点です。

ビューが実際に更新可能であることを確認する最も簡単な方法は、更新クエリの実行前(「推定」)プランを要求することです。エラーが発生した場合は、ビューが論理的に更新可能でないか、クエリプロセッサが更新可能であると判断できません。

「見積もられた」計画の要求には、当然、クエリの実行は含まれません。表示されているプラ​​ンは、クエリオプティマイザが削除できたビュー定義の量も示しています(冗長であるため)。通常、これは適切に機能するため、更新ビューのプランは、影響を受ける単一のベーステーブルへの単純な更新のプランと非常によく似ています。

具体例

リンクテーブルdimClaimStatusClaimStatusName列を使用して、外部キーを介して参照されるメインテーブルを更新できますか? [...] tabDataのfiClaimStatusを変更したい。

投稿したクエリを使用しない:

update claims 
set status='Awaiting Auth.'
where status = 'Approved' 

これにより、ビューの公開された列名statusに関連付けられたベーステーブル列が変更されます。ビュー定義から、これはテーブルdimClaimStatusの列ClaimStatusNameのエイリアスです。

実行プランは、dimClaimStatusがビューを通じて更新されたテーブルであることを示しています。

Execution plan

fiClaimStatusを更新する場合は、updateステートメントで指定する必要がある列です。それがルックアップを含む場合、最初に望んだようにビューを直接使用できない可能性がありますが、次のようなものを書くことができます:

update claims 
set fiClaimStatus =
(
    select CS.idClaimStatus
    from dbo.dimClaimStatus AS CS
    where CS.ClaimStatusName = 'Awaiting auth.'
)
where status = 'Approved';`
8
Paul White 9

あなたのUPDATEがあなたのビューのFROM句でsを更新していると想像してください。次に、私が最近書いたこのブログを読んで、どのように影響を受けるかを確認してください。

http://blogs.lobsterpot.com.au/2016/01/12/join-effects-with-update/

更新可能なビューのルール を破っていないと仮定すると、問題はありません。また、私の投稿の内容にも注意してください。

3
Rob Farley

state内の列viewを更新します。ビュー内でs.ClaimStatusName AS [Status]を参照します。 viewのコードから、dimClaimStatusテーブル(dimClaimStatus AS s)を更新していることがわかります。

2つの列idClaimStatusClaimStatusNameがあることを確認すると、テーブルのID\Name構造があります。ビュー内にClaimStatusNameを表示します。

したがって、dimClaimStatusテーブル内の名前を更新します。これが(1 row(s) affected)の理由です。

ビューを更新すると、ビュー内の複数の行内に新しい文字列が表示されます。

3
Bogdan Bogdanov