3

テーブルがあり、別のテーブルの値に基づいてそのvarcharフィールドの1つを更新したいと思います。

私は次の表を持っています:

ID  Constraint_Value 
----------------------------
1   (OldVal_1) (OldVal_2) 
2   (OldVal_2) (OldVal_1) 

...そして次の表のデータを使用して更新を行いたい:

oldValue  newValue
----------------------------
OldVal_1    NewVal_1
OldVal_2    NewVal_2

アップデート後、私は次のことを目指しています。

ID    Constraint_Value 
----------------------------
1     (NewVal_1) (NewVal_2) 
2     (NewVal_2) (NewVal_1) 

次のSQLは、私の問題を示しています(SQL Management Studioでセットアップなしで実行できます):

IF OBJECT_ID('tempdb..#tmpConstraint') IS NOT NULL DROP TABLE #tmpConstraint
GO 
CREATE TABLE tempdb..#tmpConstraint ( constraint_id INT PRIMARY KEY, constraint_value varchar(256) )
GO

IF OBJECT_ID('tempdb..#tmpUpdates') IS NOT NULL DROP TABLE #tmpUpdates
GO 
CREATE TABLE tempdb..#tmpUpdates ( oldValue varchar(256), newValue varchar(256))
GO

insert into #tmpConstraint
values (1, '(OldVal_1) (OldVal_2)')

insert into #tmpConstraint
values (2, '(OldVal_2) (OldVal_1)')

insert into #tmpUpdates
values ('OldVal_1', 'NewVal_1')

insert into #tmpUpdates
values ('OldVal_2', 'NewVal_2')

select * from #tmpConstraint

update c
set constraint_value = REPLACE(constraint_value, u.oldValue, u.newValue)
from #tmpConstraint c
cross join #tmpUpdates u

select * from #tmpConstraint

これにより、次の結果が得られます。

(Before) 
1   (OldVal_1) (OldVal_2) 
2   (OldVal_2) (OldVal_1) 

(After) 
1   (NewVal_1) (OldVal_2) 
2   (OldVal_2) (NewVal_1) 

ご覧のとおり、OldVal_1更新されました。OldVal_2同じままです。

ルックアップテーブルのすべてのデータでフィールドを更新するにはどうすればよいですか?

4

1 に答える 1

1

UPDATE、各ソース行に1回だけ影響します。したがって、私が知っている最も簡単な回避策はカーソルです。

DECLARE @o VARCHAR(256), @n VARCHAR(256);

DECLARE c CURSOR LOCAL STATIC READ_ONLY FORWARD_ONLY 
FOR SELECT oldValue, newValue FROM #tmpUpdates;

OPEN c;

FETCH c INTO @o, @n;

WHILE @@FETCH_STATUS = 0
BEGIN
    UPDATE #tmpConstraint 
      -- note full match only:
      SET constraint_value = REPLACE(constraint_value, '(' + @o + ')', '(' + @n + ')')
      -- and note we only touch rows where there is a full match:
      WHERE constraint_value LIKE '%(' + @o + ')%';

    FETCH c INTO @o, @n;
END

CLOSE c;
DEALLOCATE c;

SELECT constraint_id, constraint_value FROM #tmpConstraint;

結果:

constraint_id  constraint_value
-------------  ---------------------
1              (NewVal_1) (NewVal_2)
2              (NewVal_2) (NewVal_1)
于 2012-05-31T15:46:56.710 に答える