How can I change filegroup location? - sql-server

I used filetable for storing files in my project. now I want to change the filegroup location and move it to another drive.
How can I do this?

There is two maners.
First dettach the database, move the files, and then reattach the db
Second create a new file in the filegroup, and use the command DBCC SHRINKFILE (...) with the EMPTY option, then drop the empty file
FIRST :
EXEC sp_detach_db 'MyDatabase';
--> move the file with a system command
CREATE DATABASE MyDatabase
ON FILE (FILENAME = '...',
FILENAME = '...',
...
)
FOR ATTACH;
SECOND
ALTER DATABASE MyDatabase
ADD FILE (NAME = '...',
FILENAME = '...',
SIZE = ... GB,
FILEGROWTH = 64 MB)
TO FILEGROUP ...; --> the same filegroupe
DBCC SHRINKFILE ( '...', EMPTYFILE);
ALTER DATABASE MyDatabase
REMOVE FILE '...';
First one needs to set the database offline, second does not, but will block all accesses to tables and indexes inside the moved file.

Related

SQL Server database error: Cannot assign a new page to the database because the group files does not have sufficient space

I have set up a database in SQL and I am running a program which downloads and populates the database. This was working for me when I first set up the database but it now does not work. The error I get is the following:
Could not allocate a new page for database 'FDSLoaderDB' because of
insufficient disk space in filegroup 'PRIMARY'. Create the necessary
space by dropping objects in the filegroup, adding additional files to
the filegroup, or setting autogrowth on for existing files in the
filegroup.
I have looked online on how to resolve this issue but non of the suggested solutions work. I have tried to update the file sizes in the figure below.
I did this by running the following code:
USE FDSLoaderDB
Go
SELECT growth*8 as filegrowth_KB FROM sys.database_files Where name = N'FDSLoaderDB_log'
Go
USE master
Go
ALTER DATABASE FDSLoaderDB MODIFY FILE (NAME = N'FDSLoaderDB_log', FILEGROWTH = 5GB, MAXSIZE = UNLIMITED) -- adjust size here
Go
USE FDSLoaderDB
Go
SELECT growth*8 as filegrowth_KB FROM sys.database_files Where name = N'FDSLoaderDB_log'
Go
USE FDSLoaderDB
Go
SELECT growth*8 as filegrowth_KB FROM sys.database_files Where name = N'FDSLoaderDB'
Go
USE master
Go
ALTER DATABASE FDSLoaderDB MODIFY FILE (NAME = N'FDSLoaderDB', FILEGROWTH = 5GB, MAXSIZE = UNLIMITED) -- adjust size here
Go
USE FDSLoaderDB
Go
SELECT growth*8 as filegrowth_KB FROM sys.database_files Where name = N'FDSLoaderDB'
Go
USE master;
Go
ALTER DATABASE tempdb
MODIFY FILE (NAME = N'tempdev', SIZE = 60GB, FILEGROWTH = 5GB, MAXSIZE = UNLIMITED)
USE master;
Go
ALTER DATABASE tempdb
MODIFY FILE (NAME = N'templog', SIZE = 20GB, FILEGROWTH = 5GB, MAXSIZE = UNLIMITED);
Go
I re-run the program to re-populate the data and I get the same errors.
The log file of the program populating the database is in the following link.
EDIT:
My congratulations.
Seems your database is bigger than 10GB and you use SQL Server express Edition which has limit 10 GB per database
https://learn.microsoft.com/en-us/sql/sql-server/editions-and-components-of-sql-server-2017?view=sql-server-ver15

How to simulate a situation when non-empty Transaction Log file will be added to the SQL Server Full Database backup file

I created a test database "StoredData" with a single table:
CREATE DATABASE StoredData
ON PRIMARY
( NAME = N'StoredData', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA\StoredData.mdf')
LOG ON
( NAME = N'StoredData_log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\DATA\StoredData_log.ldf')
GO
ALTER DATABASE [StoredData] SET RECOVERY FULL
GO
USE StoredData
GO
CREATE TABLE dbo.Users
(
Id INT NOT NULL,
Name NVARCHAR(50) NOT NULL
)
Then I inserted 3 records into that table:
INSERT INTO dbo.Users (Id, Name)
VALUES (1, 'John'),
(2, 'Giovanni'),
(3, 'Anna')
After that I run this query to have some active transactions:
DECLARE #i INT = 0;
WHILE #i < 1000
BEGIN
IF(#i%10 = 0) BEGIN TRAN
INSERT INTO dbo.Users
SELECT TOP 10 * FROM dbo.Users
WAITFOR DELAY '00:00:01';
IF(#i%10 = 9) COMMIT
SET #i = #i+1
END
During the last query execution I'm trying to do full database backup:
BACKUP DATABASE StoredData
TO DISK = N'C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\Backup\StoredData_FullRecovery_Uncompressed.bak'
WITH FORMAT, NO_COMPRESSION
Then I'm looking into the backup file content:
RESTORE FILELISTONLY
FROM DISK = 'C:\Program Files\Microsoft SQL Server\MSSQL14.MSSQLSERVER\MSSQL\Backup\StoredData_FullRecovery_Uncompressed.bak'
And getting zero log file inside backup:
LogicalName: StoredData_log
BackupSizeInBytes: 0
You are looking at the wrong column for size of your files inside the backup file. you should look at the SIZE column, instead of BackupSizeInBytes. BackupSizeInBytes will tell you the size of your backup file it self(uncompressed size).
lets take a look at this picture:
This piece of information tells us that if we want to restore the StoredData_FullRecovery_Uncompressed.bak file, we will end up with 2 files. StoredData which will need about 8 MB space and the other StoredData_log which will need again 8 MB space.
lets clarify with an example:
suppose that I have created a database like below:
CREATE DATABASE [TestBackUp]
ON PRIMARY
( NAME = N'TestBackUp', FILENAME = N'<path>\TestBackUp.mdf' , SIZE = 8192KB , FILEGROWTH = 65536KB )
LOG ON
( NAME = N'TestBackUp_log', FILENAME = N'<path>\TestBackUp_log.ldf' , SIZE = 81920KB , FILEGROWTH = 65536KB )
I have added a mdf file with 8MB initial size and a ldf file with 80MB initial size.
Then I perform a full backup from database:
BACKUP DATABASE TestBackUp
TO DISK = N'<path>\TestBackUp.bak'
WITH FORMAT, NO_COMPRESSION
now lets see this file size on disk:
It has about 2.67MB size on disk. Now lets run the RESTORE FILELISTONLY command:
RESTORE FILELISTONLY
FROM DISK = N'<path>\TestBackUp.bak'
and lets see the output:
As we can see, our backup file has 2555904 bytes size on disk(BackupSizeInBytes) and if we restore this backup file we will end up with two files, one will have 8MB size and the other will have 80MB size on disk after restoring the database(Size)
Now lets create a table and populate some data inside it, and analyze the whole process again:
USE TestBackUp
GO
CREATE TABLE t(col1 NCHAR(2000), col2 NCHAR(2000))
GO
INSERT INTO t VALUES('a', 'b')
GO 10000
lets see the RESTORE FILELISTONLY command's output again:
The output tells us that we have a backup file which has about 84MB size on disk. After restoring we will end up with two files, one mdf file with 142606336 bytes size on disk and one ldf file with 150994944 bytes size on disk. below you can see the files information and size on disk too. you can see that size of these files are same as the value of size column in RESTORE FILELISTONLY command.
Read more at: https://blog.sqlauthority.com/2020/02/23/how-to-forecast-the-size-of-restore-of-backup-in-sql-server-interview-question-of-the-week-265/

Couldn't locate .ndf files of new file groups added

When I run this statement in SQL Server:
USE [master]
GO
ALTER DATABASE <DBName> ADD FILEGROUP <[FGName]>
Where is the corresponding .ndf file created on disk?
When I run that query, it's successful and I am able to find the new file group being added to the sys.filegroups table.
But when I run
select * from sys.database_files
I am not able to find the files created for the new file group. I couldn't find it in the disk as well. What am I doing wrong?
Could somebody help with this..?
Try this:
In SQL Server you will have to explicitly add the .ndf files to the different filegroups. If you dont mention any filegroup then by default it will be added to primary filegroup.
So whenever you add a filegroup it is just a logical name and it does not have any physical location.
use yourDBname
select * from sys.database_files
ALTER DATABASE yourDBname ADD FILE (NAME = name1, FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\DB11.ndf', SIZE=100MB, MAXSIZE=500GB, FILEGROWTH=50);
ALTER DATABASE yourDBname ADD FILEGROUP BusyTables
select * from sys.database_files

how to restore a sql server backup containing filestream data assigning a new folder name for filestream data?

To create a new database and populate it from a backup I typically do:
CREATE DATABASE MyDatabase -- I create an empty database
-- I retrieve the filepath of mdf and ldf files
DECLARE #FileData varchar(1000)
DECLARE #FileLog varchar(1000)
set #FileData = (select filename from MyDatabase.dbo.sysfiles where fileid = 1)
set #FileLog = (select filename from MyDatabase.dbo.sysfiles where fileid = 2)
-- I Restore the database from backup by substituting the mdf and ldf files
RESTORE DATABASE MyDatabase
FROM DISK = 'c:\Test\Test.bak'
WITH REPLACE,
MOVE 'MyApp_Data' TO #FileData, -- I forced the name to be MyApp_Data for simplicity
MOVE 'MyApp_Log' TO #FileLog -- I forced the name to be MyApp_Log for simplicity
How to do the same for the filestream data too? May I force the folder creation for filestream data or should I create it manually?
May you also comment on my approach?
I think you can use the MOVE option with the filestream data as well. You can run the following command to view the file list in your backup file. This will help identify the filestream file.
RESTORE FILELISTONLY
FROM DISK = 'c:\Test\Test.bak'
As for your overall approach, I think you may be doing more than you need to do. You don't have to create a database before you restore a backup to it. The RESTORE command will take care of the create DB steps.
So, your RESTORE command would be the same as your using, except that you can exclude the REPLACE option. You can specify your destination file information in the MOVE option.

how to set a network path for filestream filegroup

How to configure a database so that filestream data is stored on a non local path?
To enable filestream at db level I do first:
ALTER DATABASE MyDatabase ADD
FILEGROUP FileStreamFileGroup CONTAINS FILESTREAM;
GO
Then:
ALTER DATABASE MyDatabase ADD FILE (
NAME = MyDatabaseFileStreamFile,
FILENAME = 'c:\Test')
TO FILEGROUP FileStreamFileGroup ;
GO
Now instead of
c:\Test
I want to set a network path, for example:
\\Fileserver\Test
but this doesn't work:
ALTER DATABASE MyDatabase ADD FILE (
NAME = MyDatabaseFileStreamFile,
FILENAME = '\\Fileserver\Test') -- THIS IS NOT ACCEPTED
TO FILEGROUP FileStreamFileGroup ;
GO
How to achieve the desired result?
This is not supported. Although filestream data may be accessed remotely by clients, it must be local with respect to the Sql Server instance hosting it.

Resources