1

SQL Server に次の更新ステートメントを用意します。

UPDATE MY_TABLE
SET COLUMN1 = FN_GETFIRSTVALUE(T.VALUE1),
    COLUMN2 = FN_GETSECONDVALUE(T.VALUE1, T.COLUMN1)
FROM MY_TABLE AS T
INNER JOIN ...

から返さFN_GETSECONDVALUEれる入力パラメータを受け入れますFN_GETFIRSTVALUEテーブル関数を使用することを考えました...しかし、これで2つの列を更新する方法がわかりません。これを行う別の/より良い方法はありますか? 関数を2回呼び出したり、選択/更新に分割したりしたくありません。

4

1 に答える 1

3

あなたの例への最小の変更は次のようになります...

UPDATE
  MY_TABLE
SET
  COLUMN1 = FN_GETFIRSTVALUE(T.VALUE1),
  COLUMN2 = FN_GETSECONDVALUE(T.VALUE1, FN_GETFIRSTVALUE(T.VALUE1))
FROM
  MY_TABLE AS T
INNER JOIN
  ...

SQL サーバーは結果の再利用に優れているため、最初の関数が必ずしも 2 回実行されるとは限りません。ただし、関数の呼び出しを 2 回記述するだけでも、まだ少し面倒です。

APPLY代わりに、 ...を使用して自分で再利用を書くことができます

UPDATE
  MY_TABLE
SET
  COLUMN1 = first_result.val,
  COLUMN2 = second_result.val
FROM
  MY_TABLE AS T
OUTER APPLY
  (SELECT dbo.FN_GETFIRSTVALUE(T.VALUE1) AS val)          AS first_result
OUTER APPLY
  (SELECT dbo.FN_GETSEOCNDVALUE(first_result.val) AS val) AS second_result
INNER JOIN
  ...

さらに良いことに、関数をテーブル値関数として書き直すことができます。1 つのレコードで 1 つのフィールドしか返さない場合でも...

UPDATE
  MY_TABLE
SET
  COLUMN1 = first_result.val,
  COLUMN2 = second_result.val
FROM
  MY_TABLE AS T
OUTER APPLY
  dbo.FN_GETFIRSTVALUE(T.VALUE1)           AS first_result
OUTER APPLY
  dbo.FN_GETSEOCNDVALUE(first_result.val)  AS second_result
INNER JOIN
  ...

どちらの場合も、テーブル値関数がインライン関数(単一のクエリのみ)として定義されている場合は、マルチステートメント関数(内部変数、IF ステートメントなどを含む) として定義されている場合よりもはるかに優れたパフォーマンスを発揮します。

最後に、必要に応じて、両方の機能を 1 つにラップすることもできます...

UPDATE
  MY_TABLE
SET
  COLUMN1 = result.val1
  COLUMN2 = result.val2
FROM
  MY_TABLE AS T
OUTER APPLY
  dbo.FN_GETBOTHVALUES(T.VALUE1)           AS result
INNER JOIN
  ...

(この関数は、 と という名前の 2 つのフィールドを持つ 1 つのレコードを返しますval1val2)

したがって、全体として、ここには多数のオプションがあります。そして、それはただ使用しているだけAPPLYです。共通テーブル式には他のオプションがあります...

WITH
  step1 AS
(
  SELECT
    *,
    dbo.FUNCTION1(T.column1) AS result1
  FROM
    MY_TABLE AS T
  INNER JOIN
    ...
)
,
  step2 AS
(
  SELECT
    *,
    dbo.FUNCTION2(T.result1) AS result2
  FROM
    step1
)

UPDATE
  step2
SET
  column1 = result1,
  column2 = result2

非常に多くのオプション...

于 2012-08-16T13:14:37.660 に答える