をまさにSQLサーバーをトリガするかは分からない自然な鍵サロゲートキー
-
30-09-2019 - |
質問
裏話
仕事場を予定しているdeprecating天然のキーカラムの主ます。プロジェクトには100を超えるリンクテーブル、カラム;400+収納手続きを参照するこのカラムを直接;膨大な配列の共通のテーブルの間にこれらの用途にもご参考ます。
ビッグバンにより、ゼロからのスタート方法は画像になります。私たちが発展していくためにはdeprecateこのコラムプ、認証の変更の...する私たちは長い目標を目標にこの取り組みます。
の問題にしているのは、多くのスタッフがこれらのアプリケーションを共同保存の手続きです。ま完全に転換すべてのアプリケーションでは、のテーブル/保存の手続き適用されることもありますの折れまでに変換されます。これらの破壊プD、E、F。しかし、私た戦略の実施のためのコードをクラスと保管手続きの問い合わの移行状態のデータベースです。
この 基本 例として:
Users
---------------------------
Code varchar(32) natural key
Access
---------------------------
UserCode varchar(32) foreign key
AccessLevel int
いを目指して、今だけの過渡状態のようになります:
Users
---------------------------
Code varchar(32)
Id int surrogate key
Access
---------------------------
UserCode varchar(32)
UserID int foreign key
AccessLevel int
のマーケティングが"デザインの中で、移行期の連移動する用途や収納手続きることはできまアクセスいて、当てはまるものすべてのデータと新しいものでを押し、正しいカラム--一度への移行が完了してすべての保存手順を用いることで、これまでの落下に列あります。
たいと思った利用のSQLサーバーのトリガーを自動的に遮断新の挿入/更新のいくには、次のようなものがそれぞれの影響のテーブル:
CREATE TRIGGER tr_Access_Sync
ON Access
INSTEAD OF INSERT(, UPDATE)
AS
BEGIN
DIM @code as Varchar(32)
DIM @id as int
SET @code = (SELECT inserted.code FROM inserted)
SET @id = (SELECT inserted.code FROM inserted)
-- This is a migrated application; find the appropriate legacy key
IF @code IS NULL AND @id IS NOT NULL
SELECT Code FROM Users WHERE Users.id = @id
-- This is a legacy application; find the appropriate surrogate key
IF @id IS NULL AND @code IS NOT NULL
SELECT Code FROM Users WHERE Users.id = @id
-- Impossible code:
UPDATE inserted SET inserted.code=@code, inserted.id=@id
END
質問
の2つの大きな問題んこれまでには:
- これができない"の後に挿入"がNULL制約の挿入に失敗します。
- の"不可能なコード"ってどんぐの代理元のクエリー;場合は、元のクエリは、x,y,zのカラムであるということもあり、ぐx、理想いは同じトリガーになれます。そして、追加/削除別の列で、そういったトリガーには機能している。
誰にでもしていたコード例ではこの可能だということであるもの代替溶液をこれらのカラムを適切に溢れる場合でも一つだけの価値が渡されたSQL?
解決 3
問題について寝た後、これはSQL構文内で思いつくことができる最も一般的な/再利用可能なソリューションのようです。インサート内の「他の」列をまったく参照していなくても、両方の列にヌルの抑制ではない場合でも、正常に動作します。
CREATE TRIGGER tr_Access_Sync
ON Access
INSTEAD OF INSERT
AS
BEGIN
/*-- Create a temporary table to modify because "inserted" is read-only */
/*-- "temp" is actually "#temp" but it throws off stackoverflow's syntax highlighting */
SELECT * INTO temp FROM inserted
/*-- If for whatever reason the secondary table has it's own identity column */
/*-- we need to get rid of it from our #temp table to do an Insert later with identities on */
ALTER TABLE temp DROP COLUMN oneToManyIdentity
UPDATE temp
SET
UserCode = ISNULL(UserCode, (SELECT UserCode FROM Users U WHERE U.UserID = temp.UserID)),
UserID = ISNULL(UserID, (SELECT UserID FROM Users U WHERE U.UserCode = temp.UserCode))
INSERT INTO Access SELECT * FROM temp
END
他のヒント
トリッキーなビジネス...
さて、まず第一に:このトリガーはそうします いいえ 多くの状況で働く:
SET @code = (SELECT inserted.code FROM inserted)
SET @id = (SELECT inserted.code FROM inserted)
トリガーは、 Inserted
擬似テーブル - ここで選ぶつもりですか?トリガーを、10行を取得しても機能するようにトリガーを書く必要があります。 Inserted
テーブル。 SQLステートメントが10行を挿入すると、トリガーは いいえ 10回発射されます - 各行に1つ - しかしのみ 一度 バッチ全体について - それを考慮する必要があります!
2番目のポイント:私はIDを作ろうとします IDENTITY
フィールド - その後、彼らは常に値を取得します - 「レガシー」アプリでも。これらの「古い」アプリは、代わりにレガシーキーを提供する必要があります。そのため、そこでは大丈夫です。私が見ている唯一の問題は、それらを既に変換されたアプリからの挿入物であることをどのように処理するかわからない - それらは「古いスタイルの」レガシーキーを提供しますか?そうでない場合 - どのくらい早くそのようなキーを持つ必要がありますか?
私が考えているのは、テーブルの上を走り、すべての行をnull regacyキーで取得し、それに何らかの意味のある価値を提供する「クリーンアップジョブ」です。これを通常のストアドプロシージャにし、1日ごとに4時間30分ごとに実行します - あなたのニーズに合ったものは何でも。そうすれば、トリガーや彼らが持っているすべての制限に対処する必要はありません。
ができるのではない可能で、スキーマの変更'bigbang'がビューを作成の上では、これらのテーブルが非表示に変わるのか?
と思いを感じるかもしれませんがだけの故障"が後日:"私たちが発展していくためにはdeprecateこのカラム用時でも私の歩み素朴ともいうことになる今となっています。
確実にしていかなければならないと混乱できる各種アプリケーションというわけではな?