Question

I was having fun testing out the columnstore index feature of sql server 2012. Because you can't update/insert tables with such indices I read on some options: keep a separate table and use a new partition for every bulk insert or disable the index, perform updates/inserts and then rebuild the index.

For my test I chose the latter option and ended up with this stored procedure:

-- Disable the columnstore index.
ALTER INDEX [All_Columns_Columnstore_Index] ON [dbo].[Tick] DISABLE

-- Insert data into tick table from staging table.
insert into Tick
select [Date],
       SymbolID,
       Price
from TickTemporary

-- Delete data from staging table.
delete from TickTemporary

-- Enable (rebuild) the columnstore index.
ALTER INDEX [All_Columns_Columnstore_Index] ON [dbo].[Tick] REBUILD

If I execute these lines manually everything works fine. But if I run the procedure, I get the error that updates/inserts can't be performed on a table that has a columnstore index.

Why is this?

Update:

I followed the advice in the answer I previously accepted but I still get the same thing.

-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;

-- Disable the columnstore index.
EXEC DisableColumnStoreIndex

-- Insert data into tick table from staging table.
insert into Tick
select [Date],
       SymbolID,
       Price
from TickTemporary

-- Delete data from staging table.
delete from TickTemporary

-- Enable (rebuild) the columnstore index.
EXEC RebuildColumnStoreIndex

Even tried placing "begin tran" and "commit tran" around the sproc calls.

Using dynamic sql like:

declare @sql nvarchar(max)
set @sql =
    'insert into Tick
     select [Date],
            SymbolID,
            Price
     from TickTemporary'
exec(@sql)

works, but really, I want to get by without dynamic sql. Isn't it possible in this case?

Was it helpful?

Solution

The check is done at compile time, not at execution time. Separate the procedure into it's own, or use dynamic SQL.

But as a general comment this is not the right approach. You should insert into a different table with identical structure, build the columnstore index on this identical table, then use partition switch to replace the old table with the new table: switch out the old table with an empty one, switch in the new table, drop the old data switched out. Similar to the procedure described in How to Update a table with a Columnstore Index. Because of the use of partition switch the users of your table experience a much shorter downtime, as the old table is still online and available during the insert and during the build columnstore stages.

OTHER TIPS

Solution For This compile time execution is Option(recompile)

create  PROCEDURE TEST
AS
BEGIN

ALTER INDEX [All_Columns_Columnstore_Index] ON [dbo].[Tick] DISABLE

-- Insert data into tick table from staging table.

insert into Tick
select [Date],
       SymbolID,
       Price
from TickTemporary  **Option(recompile)**

-- Delete data from staging table.
delete from TickTemporary

-- Enable (rebuild) the columnstore index.
ALTER INDEX [All_Columns_Columnstore_Index] ON [dbo].[Tick] REBUILD

End
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top