This post has been updated, scroll to the bottom.
When you move an SQL-table to a new filegroup via the clustered-index recreation procedure, only "elementary" datatypes are moved (like "int", "datetime", "varchar" etc). Text, image, varbinary(max) and similar columns (aka "BLOB-fields" aka "LOB_DATA") will stay at their current location. If you click the "storage" settings for the table under the "properties" context menu item, you'll see that the "text filegroup" is the same as before! More info
The "text filegroup" can't be changed without re-creating a table. And I bet you've seen this phrase a million times while googling for a solution, right? Ok, we need to re-create the table and copy all the data into this new table. But who wants to do this manually? Drop and re-create a table with all the indexes, foreign-keys, primary keys, identities... Ain't there an automated procedure for this?The above method still works, but on modern versions of SQL Server these days you can do this online (!) using just scripts. The trick is to use partitioning - a built-in mechanism that allows moving data between filegroups automatically.
Suppose you have a MyTable
table that has an "ID" column and a LOB field "Data". Here are the steps:
CREATE PARTITION FUNCTION pf_MyTable_temp ([int] ) AS RANGE RIGHT FOR VALUES (0);
CREATE PARTITION SCHEME ps_MyTable_temp AS PARTITION pf_MyTable_temp TO ([SECONDARY],[SECONDARY]);
CREATE UNIQUE CLUSTERED INDEX PK_MyTable ON MyTable([ID]) WITH (DROP_EXISTING = ON , ONLINE = ON) ON ps_MyTable_temp([ID] );
CREATE UNIQUE CLUSTERED INDEX PK_MyTable ON MyTable([ID]) WITH (DROP_EXISTING = ON , ONLINE = ON) ON [SECONDARY];
DROP PARTITION SCHEME ps_MyTable_temp; DROP PARTITION FUNCTION pf_MyTable_temp;
Here's a neat stored procedure that will do it all for you: https://pastebin.com/raw/ZK3wXAqB