0

このカーソルの変数 @NextURLId が更新されない理由がわかりません。ここにコードがあります

DECLARE @NextURLId INT = 1
DECLARE @varContact_Id INT

DECLARE GetURL_Cursor CURSOR FOR
    SELECT DISTINCT(contact_id)
    FROM obp.Contacts
OPEN GetURL_Cursor

FETCH NEXT FROM GetURL_Cursor INTO @varContact_id
WHILE @@FETCH_STATUS = 0
BEGIN
-- Available URLs have the used value as NULL. Used has value of 1.
SET @NextURLId = (SELECT MIN(id) FROM obp.URL WHERE used IS NULL)

UPDATE obp.Contacts SET URL = (
    SELECT url from obp.URL WHERE id = @NextURLId)
UPDATE obp.URL SET  
    used = 1,
    contact_id = @varContact_Id,
    date = GETDATE()
 WHERE id = @NextURLId

FETCH NEXT FROM GetURL_Cursor INTO @varContact_id
END;

CLOSE GetURL_Cursor
DEALLOCATE GetURL_Cursor

このコードは、テーブル (obp.URL) から一意の URL を取得し、その URL を Contacts テーブルに入力してから、URL が使用されたことを示すように URL を更新することになっています。URL テーブルが 'used = 1' で更新された後、コードの次の繰り返しでクエリを実行すると、新しい URLId が取得されるように思えます。

ただし、このコードを実行すると、毎回同じ URL を取得します。明らかな何かが欠けていることは間違いありませんが、それを指摘するには助けが必要です。

余談ですが、これに対するセットベースの解決策があれば、喜んでお聞きします。

ティア

4

1 に答える 1

0

これ

UPDATE obp.Contacts SET URL = (
    SELECT url from obp.URL WHERE id = @NextURLId)

すべての行を同じで更新します。次のような適切なWHERE句を追加します

WHERE contact_id=@varContact_id

この要件について: 連絡先を URL に関連付けたいと考えており、どの URL と何を関連付けるかという論理的なルールがないことは理解しています。一見すると、これを行うにはマッチ テーブルが正しい方法だと思います。関連付けられた 2 つのオブジェクト間に 1 対 1 の関係が強く信じられている場合でも、このような関連付けを別のテーブルに入れる方がよいと思います。obp.URL と obp.Contacts は次元テーブルです(私は想定/希望しています)。関連付けを 1 つの異なるテーブルに保持するには、変更が発生した場合に 1 つのアクションが必要です。モデルでは、変更をこれらの両方のテーブルに反映する必要があります。

このようなテーブルのアイデアは次のとおりです。

create table Contact_URL_match
   (ID int identity (1,1)
   ,URL_id int not null unique
   ,contact_id int not null unique
   ,created datetime)

一意の制約により、同じ URL または同じ Contact_id を 2 回挿入することはできません。挿入/更新のたびに、前のコンテンツの重複がチェックされ、見つかった場合はアクションが拒否されるため、一意性が保護されます。

最初の大規模な初期アクションで新しい一致を明示するには、これを試してください(テストしていません。単なるアイデアです)

INSERT INTO
  Contact_URL_match
    (URL_id
    ,contact_id
    ,created)
SELECT
  urls.id 
  ,contacts.contact_id      
  ,getdate()
FROM
  (SELECT 
    DISTINCT(contact_id)
    ,ROW_NUMBER() over (ORDER BY contact_id asc) rn
  FROM 
    obp.Contacts) contacts
INNER JOIN
  (SELECT 
    id 
    ,ROW_NUMBER() over (ORDER BY id) rn
  FROM 
    obp.URL) urls
ON
  contacts.rn=urls.rn

サブクエリ内では、ORDER BY 句に基づいて両方のソース テーブルに行番号が作成されます。次に、サブクエリの結果セットをその行番号で結合しますが、これは意図的なランダム性の行為です。あなたがそれを望んでいることを願っています。その結合の結果が一致テーブルに挿入されます。

後で単一の新しい関連付けをマニフェストしたい場合は、サブクエリに WHERE 句を追加して、どの URL をどの Contact と照合するかを指定できます。URL または連絡先を選択する前に、マッチ テーブルで NOT EXISTS が使用されていないことを確認してください。

EDIT : 構文エラーが消去されました

于 2013-10-06T04:52:34.210 に答える