Help us understand the problem. What is going on with this article?

T-SQLでループ内のDECLAREによる宣言時、代入を行わないと初期化されない

事象

ループ、またはカーソル内で、毎回変数をnullで初期化したい時、DECLAREによる宣言のみだと初期化されない。

原因

  • ループ、カーソルで宣言済み変数名を宣言してエラーにならず、アドレスが更新されない。
  • 代入処理がなければ値は変更されない。 って仕様があるのだと思う。多分。ドキュメントが見つからなかった。

結論

  • DECLAREで初期化する場合、代入をする。
  • または、ループ内のDECLAREを避け、ループの外でDECLAREしてループ内はSETで初期化する。

調査

初期化できるパターン1

BEGIN
  DECLARE @count INT = 0
  WHILE @count < 2
    BEGIN
      SET @count = @count + 1
      DECLARE @id INT = null -- ここ

      PRINT '代入前: null?'
      PRINT CONVERT(NVARCHAR(10), @id)

      SET @id = 1;

      PRINT '代入後: 1?'
      PRINT CONVERT(NVARCHAR(10), @id)

    END
END
GO

-- 結果
[2020-03-03 11:06:41] [S0001] 代入前: null?
[2020-03-03 11:06:41] [S0001]
[2020-03-03 11:06:41] [S0001] 代入後: 1?
[2020-03-03 11:06:41] [S0001] 1
[2020-03-03 11:06:41] [S0001] 代入前: null?
[2020-03-03 11:06:41] [S0001]
[2020-03-03 11:06:41] [S0001] 代入後: 1?
[2020-03-03 11:06:41] [S0001] 1

初期化できるパターン2

BEGIN
  DECLARE @count INT = 0
  WHILE @count < 2
    BEGIN
      SET @count = @count + 1
      DECLARE @id INT = 2 -- ここ

      PRINT '代入前: 2?'
      PRINT CONVERT(NVARCHAR(10), @id)

      SET @id = 1;

      PRINT '代入後: 1?'
      PRINT CONVERT(NVARCHAR(10), @id)

    END
END
GO

-- 結果
[2020-03-03 11:10:45] [S0001] 代入前: 2?
[2020-03-03 11:10:45] [S0001] 2
[2020-03-03 11:10:45] [S0001] 代入後: 1?
[2020-03-03 11:10:45] [S0001] 1
[2020-03-03 11:10:45] [S0001] 代入前: 2?
[2020-03-03 11:10:45] [S0001] 2
[2020-03-03 11:10:45] [S0001] 代入後: 1?
[2020-03-03 11:10:45] [S0001] 1

初期化できないパターン

BEGIN
  DECLARE @count INT = 0
  WHILE @count < 2
    BEGIN
      SET @count = @count + 1
      DECLARE @id INT -- ここ

      PRINT '代入前: null?'
      PRINT CONVERT(NVARCHAR(10), @id)

      SET @id = 1;

      PRINT '代入後: 1?'
      PRINT CONVERT(NVARCHAR(10), @id)

    END
END
GO

-- 結果
[2020-03-03 11:09:56] [S0001] 代入前: null?
[2020-03-03 11:09:56] [S0001]
[2020-03-03 11:09:56] [S0001] 代入後: 1?
[2020-03-03 11:09:56] [S0001] 1
[2020-03-03 11:09:56] [S0001] 代入前: null?
[2020-03-03 11:09:56] [S0001] 1
[2020-03-03 11:09:56] [S0001] 代入後: 1?
[2020-03-03 11:09:56] [S0001] 1

参考

SQLSercer - DECLARE

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away