プログラミング逆引き辞典

~ 多言語対応のプログラミングレシピ ~

対象レコードの上限数設定&コピーするストアドプロシージャ

-- テーブル作成
create table t_emp (
    id int,
    name nvarchar(100),
    class_id int,
    update_date datetime
    constraint pk_emp primary key (id)
)
insert into t_emp values (1, '両津勘吉', 1, sysdatetime())
insert into t_emp values (2, '中川圭一', 2, sysdatetime())
insert into t_emp values (3, '秋本麗子', 2, sysdatetime())
insert into t_emp values (4, '大原大次郎', 0, sysdatetime())
go

create table m_class (
    class_id int,
    class_name nvarchar(100),
    update_date datetime
    constraint pk_master primary key (class_id)
)
insert into m_class values (0, '巡査部長', sysdatetime())
insert into m_class values (1, '巡査長', sysdatetime())
insert into m_class values (2, '巡査', sysdatetime())
go

-- コピー先
create table t_copy (
    id int,
    name nvarchar(100),
    class_id int,
    update_date datetime
    constraint pk_copy primary key (id)
)
go

-- 役職ごとのレコード数
select
    t2.class_name, t1.rows_count
from (
    select
        t.class_id, count(*) as rows_count
    from 
        t_emp t
    join
        m_class m on t.class_id = m.class_id
    group by
        t.class_id
    ) t1
join
    m_class t2 on t1.class_id = t2.class_id
order by
    t2.update_date
go

-- 上限を超えない範囲でテンプテーブルにレコード挿入
create procedure sp_countRows
(
    @max_rows_count int
)
as
begin
    -- 速度アップ
    set nocount on;

    -- ============================================
    -- テーブル作成 ※後ほどテンプテーブルに変更
    -- ============================================
    drop table if exists tmp_table;
    create table tmp_table (
        class_id int,
        class_name nvarchar(100),
        rows_count int
    );

    -- ============================================
    -- 上限を超えない場合はテンプテーブルに格納
    -- ============================================
    -- カーソルに格納
    declare cur cursor for
        select
            t2.class_id,
            t2.class_name,
            t1.rows_count
        from (
            select
                t.class_id,
                count(*) as rows_count
            from 
                t_emp t
            join
                m_class m on t.class_id = m.class_id
            group by
                t.class_id
            ) t1
        join
            m_class t2 on t1.class_id = t2.class_id
        order by
            t2.update_date;

    -- カーソルオープン
    open cur;

    declare @class_id int;
    declare @class_name nvarchar(100);
    declare @rows_count int;

    -- 累計カウントを0で初期化
    declare @result_count int;
    set @result_count = 0;

    -- 1行目を取得
    fetch next from cur into
        @class_id,
        @class_name,
        @rows_count;

    while (@@fetch_status = 0)
    begin
        -- 累計カウントに行数を加算
        print @class_name + 'のレコード数を加算';

        set @result_count += @rows_count;
        print '累計カウント:' + convert(varchar, @result_count);

        -- カウント数がパラメーターで指定した数を超えた場合は処理を終了
        if (@result_count > @max_rows_count)
        begin
            print '累計カウントがパラメーターで指定したマックス値を超えるので処理を終了';
            break;
        end

        -- テンプテーブルに対象のレコードをインサート
        insert into tmp_table (class_id, class_name, rows_count) values (@class_id, @class_name, @rows_count);

        -- 次のレコードを抽出
        fetch next from cur into
            @class_id,
            @class_name,
            @rows_count;

    end

    -- カーソルクローズ、開放
    close cur;
    deallocate cur;

    -- ============================================
    -- 上限を超えないレコードをt_copyテーブルにinsert selectコマンドでコピー
    -- ============================================
    print 't_copyテーブルにコピー';
    truncate table t_copy;
    insert into t_copy (id, name, class_id, update_date)
        select 
            id,
            name, 
            class_id, 
            update_date
        from 
            t_emp emp
        where exists (
            select 
                1 
            from 
                tmp_table tmp 
            where 
                emp.class_id = tmp.class_id
            );

    print '終了';

end
go