ぽにょろん

思いついたこととメモ

T-SQLでOUTPUT句を使う

OUTPUT句って結構便利だと思っているんですが、そうそう使わないこともあってなかなか覚えられないorz
そんなわけでサンプルを書いてみました。

まずは書き方

何はともあれ、MSDN参照しましょう。

OUTPUT 句 (Transact-SQL)

SQLServer2005から使えるようです。

insert into [table] 
output inserted.* 
values ( 'hoge' ) 

update [table] set [colName] = 'po' 
output deleted.*, inserted.* 
where [colName] = 'aiueo'

delete from [table] 
output deleted.* 
where [colName] = '123456789'

ついでにやりたいことの実験

複数のプロセスから重複なく指定件数だけ更新したい。
かつ更新したレコードが欲しい。

テスト用のテーブルを用意。

create table test(id Integer, kind Integer, memo nvarchar(max), assignedName nvarchar(max));
--delete test;

declare @idx int;
set @idx = 0;

while @idx < 10000
begin
  insert test values(@idx, @idx % 3, 'hoge', Null);
  set @idx = @idx + 1;
end;

サンプルコードを用意。
理解が怪しいところがあるので、大丈夫だろうか。(; ̄ー ̄A

//using Dapper;

static void Main(string[] args)
{
   var list = new SynchronizedCollection<Test>();
   ThreadPool.SetMinThreads(200, 200);
   Parallel.ForEach(
       Enumerable.Range(0, 300),
       new ParallelOptions { MaxDegreeOfParallelism = 200 },
       num =>
       {
           Console.WriteLine(string.Format("BEGIN:{0}", num));
           var data = GetData(0, num.ToString()).Result;
           foreach (var item in data)
           {
               list.Add(item);
               Console.WriteLine(string.Format("Num:{0}, Id:{1}", num, item.Id));
           }
           Console.WriteLine(string.Format("END:{0}", num));
        });
    Console.ReadLine();
}
public async static Task<IEnumerable<Test>> GetData(int kind, string name)
{
    var str = @"接続文字列";
    using (var con = new SqlConnection(str))
    {
        con.Open();
        using (var tran = con.BeginTransaction())
        {
            var result = await con.QueryAsync<Test>("Update Top (10) test set assignedName = @Name output inserted.id, inserted.Kind where (kind = @Kind) and (assignedName IS NULL)", new { Kind = kind, Name = name }, tran);
            tran.Commit();
            return result;
        }
    }
}
public class Test
{
    public int Id { get; set; }
    public int Kind { get; set; }
    public string Memo { get; set; }
    public string AssignedName { get; set; }
}

実行結果

今のところ大体思った通り動いてる。

f:id:kowill:20150811224721p:plain