add data files into a primary filegroup in MS SQL Server - database

When a database is created a file group with a data file is created by default. Is it possible to add more than data file into a primary file group.

To add an data-file to primary filegroup:
USE [master]
GO
ALTER DATABASE [your_database]
ADD FILE
(NAME = N'logical_name',
FILENAME = N'C:\my_data.mdf', -- <--Path to physical file
SIZE = 1GB,
FILEGROWTH = 100MB
)
TO FILEGROUP [PRIMARY]

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 can I change filegroup location?

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.

Backup and restore SQL Server database filegroup

I use sql server and have a huge database that partitioned by date in multiple file groups.
the database filegroups is PRIMARY, FG2010, FG2011, FG2012, FG2013, and FG2014, that FG2010, FG2011, FG2012 and FG2013 is readonly.
Now, the backup scenario is:
each Friday get a full backup at 2:00 AM
each day on week except Friday get a differential backup at 2:00 AM
I want to change this scenario to:
get a full backup of database(One Time)
get a full backup of PRIMARY and FG2014 each Friday at 2:00 AM
get a differential backup of PRIMARY and FG2014 each day except Friday at 2:00 AM
Questions 1: Can I have this scenario?
I have a recovery plan too. each day I copy backup file to another server automatically by job and then restore it, in order to have recovery test plan and also use restored database to developer and tester users.
I want to have following scenario for recovery plan:
restore full backup of database.
restore last full backup of PRIMARY and FG2014.
restore last differential backup of PRIMARY and FG2014.
Question 2: can I have this scenario to recovery plan?
Question 3: can I have better scenario to backup and restore?
Please answer my question with TSQL query.
Q1. Yes, you can. You would also need to be taking regular transaction log backups.
Q2. Yes, this would also work for a recovery strategy, again you need to be taking transaction log backups.
Q3. As you are using the backups to create a development database, I would stick with this. There are options such as log shipping but I would not implement them to keep a development database updated from production.
I have written some demo scripts which you can use to run through the scenario you suggested on your local instance.
The scripts will:-
Create a test database, with multiple filegroups which some are read only.
Create a development database from a backup of the test database.
Take filegroup backups of the test database and restore over the development database
Please have a look and run through the scripts. Let me know if you have any questions.
Before you use the scripts, just make sure that you have the following filepaths on your computer:-
C:\SQLServer\Data
C:\SQLServer\Logs
C:\SQLServer\Backups
The version of SQL Server I use is 2012 SP2 CU2 Developer Edition.
First create the test database:-
CREATE DATABASE [FGRestoreTEST]
ON PRIMARY
( NAME = N'FGRestoreTEST', FILENAME = N'C:\SQLServer\Data\FGRestoreTEST.mdf' , SIZE = 5120KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB ),
FILEGROUP [FG2010]
( NAME = N'FG2010', FILENAME = N'C:\SQLServer\Data\FG2010.ndf' , SIZE = 5120KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB ),
FILEGROUP [FG2011]
( NAME = N'FG2011', FILENAME = N'C:\SQLServer\Data\FG2011.ndf' , SIZE = 5120KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB ),
FILEGROUP [FG2012]
( NAME = N'FG2012', FILENAME = N'C:\SQLServer\Data\FG2012.ndf' , SIZE = 5120KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB ),
FILEGROUP [FG2013]
( NAME = N'FG2013', FILENAME = N'C:\SQLServer\Data\FG2013.ndf' , SIZE = 5120KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB ),
FILEGROUP [FG2014]
( NAME = N'FG2014', FILENAME = N'C:\SQLServer\Data\FG2014.ndf' , SIZE = 5120KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
LOG ON
( NAME = N'FGRestoreTEST_log', FILENAME = N'C:\SQLServer\Logs\FGRestoreTEST_log.ldf' , SIZE = 2048KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)
GO
Then create tables in each of the filegroups:-
USE [FGRestoreTEST];
GO
CREATE TABLE [PRIMARY_TABLE]
(ID INT,
NAME CHAR(4)) ON [PRIMARY];
CREATE TABLE [FG2010_TABLE]
(ID INT,
NAME CHAR(4)) ON [FG2010];
CREATE TABLE [FG2011_TABLE]
(ID INT,
NAME CHAR(4)) ON [FG2011];
CREATE TABLE [FG2012_TABLE]
(ID INT,
NAME CHAR(4)) ON [FG2012];
CREATE TABLE [FG2013_TABLE]
(ID INT,
NAME CHAR(4)) ON [FG2013];
CREATE TABLE [FG2014_TABLE]
(ID INT,
NAME CHAR(4)) ON [FG2014];
GO
Insert data (100 rows) into each of the tables:-
INSERT INTO [PRIMARY_TABLE]
SELECT 1, 'TEST'
GO 100
INSERT INTO [FG2010_TABLE]
SELECT 1, 'TEST'
GO 100
INSERT INTO [FG2011_TABLE]
SELECT 1, 'TEST'
GO 100
INSERT INTO [FG2012_TABLE]
SELECT 1, 'TEST'
GO 100
INSERT INTO [FG2013_TABLE]
SELECT 1, 'TEST'
GO 100
INSERT INTO [FG2014_TABLE]
SELECT 1, 'TEST'
GO 100
Then set certain filegroups to read only:-
ALTER DATABASE [FGRestoreTEST]
MODIFY FILEGROUP [FG2010] READ_ONLY;
ALTER DATABASE [FGRestoreTEST]
MODIFY FILEGROUP [FG2011] READ_ONLY;
ALTER DATABASE [FGRestoreTEST]
MODIFY FILEGROUP [FG2012] READ_ONLY;
ALTER DATABASE [FGRestoreTEST]
MODIFY FILEGROUP [FG2013] READ_ONLY;
GO
Take a full backup:-
USE [master];
GO
BACKUP DATABASE [FGRestoreTEST]
TO DISK = N'C:\SQLServer\Backups\FGRestoreTEST.BAK';
GO
Then create a development database from the full backup (this will be used to restore the filegroup backups that will be taken further next):-
RESTORE DATABASE [FGRestoreTEST_Dev]
FROM DISK = N'C:\SQLServer\Backups\FGRestoreTEST.BAK' WITH
MOVE 'FGRestoreTEST' TO 'C:\SQLServer\Data\FGRestoreTEST_Dev.mdf',
MOVE 'FG2010' TO 'C:\SQLServer\Data\FG2010_Dev.ndf',
MOVE 'FG2011' TO 'C:\SQLServer\Data\FG2011_Dev.ndf',
MOVE 'FG2012' TO 'C:\SQLServer\Data\FG2012_Dev.ndf',
MOVE 'FG2013' TO 'C:\SQLServer\Data\FG2013_Dev.ndf',
MOVE 'FG2014' TO 'C:\SQLServer\Data\FG2014_Dev.ndf',
MOVE 'FGRestoreTEST_log' TO 'C:\SQLServer\Logs\FGRestoreTEST_Dev_log.ldf',
RECOVERY,STATS=5;
GO
Take backups of each of the filegroups:-
--http://msdn.microsoft.com/en-us/library/ms189906.aspx
BACKUP DATABASE [FGRestoreTEST]
FILEGROUP = 'PRIMARY'
TO DISK = 'C:\SQLServer\Backups\FGRestoreTEST_PRIMARY.bak';
BACKUP DATABASE [FGRestoreTEST]
FILEGROUP = 'FG2010'
TO DISK = 'C:\SQLServer\Backups\FGRestoreTEST_FG2010.bak';
BACKUP DATABASE [FGRestoreTEST]
FILEGROUP = 'FG2011'
TO DISK = 'C:\SQLServer\Backups\FGRestoreTEST_FG2011.bak';
BACKUP DATABASE [FGRestoreTEST]
FILEGROUP = 'FG2012'
TO DISK = 'C:\SQLServer\Backups\FGRestoreTEST_FG2012.bak';
BACKUP DATABASE [FGRestoreTEST]
FILEGROUP = 'FG2013'
TO DISK = 'C:\SQLServer\Backups\FGRestoreTEST_G2013.bak';
BACKUP DATABASE [FGRestoreTEST]
FILEGROUP = 'FG2014'
TO DISK = 'C:\SQLServer\Backups\FGRestoreTEST_FG2014.bak';
GO
Now we will modify data in the Primary & FG2014 filegroups:-
USE [FGRestoreTEST];
GO
INSERT INTO [PRIMARY_TABLE]
SELECT 1, 'TEST'
GO 100
TRUNCATE TABLE [FG2014_TABLE];
GO
Take differential backups of the filegroups:-
BACKUP DATABASE [FGRestoreTest]
FILEGROUP = 'PRIMARY'
TO DISK = 'C:\SQLServer\Backups\FGRestoreTest_PRIMARYDIFF.bak'
WITH DIFFERENTIAL;
BACKUP DATABASE [FGRestoreTest]
FILEGROUP = 'FG2014'
TO DISK = 'C:\SQLServer\Backups\FGRestoreTest_FG2014DIFF.bak'
WITH DIFFERENTIAL;
GO
Again, modify the data:-
USE [FGRestoreTEST];
GO
INSERT INTO [PRIMARY_TABLE]
SELECT 1, 'TEST'
GO 100
INSERT INTO [FG2014_TABLE]
SELECT 1, 'NEW'
GO 300
Backup the transaction log (you will probably have more than one of these in a real life environment, but for demo purposes I'm just taking one):-
USE [master];
GO
BACKUP LOG [FGRestoreTEST]
TO DISK = 'C:\SQLServer\Backups\FGRestoreTest_LogBackup.trn';
GO
OK, now we can restore the development database. First we take a Tail Log backup, putting the database into recovery. Note:- we will not use this backup!
BACKUP LOG [FGRestoreTEST_Dev]
TO DISK = 'C:\SQLServer\Backups\FGRestoreTest_TailLogBackup.trn'
WITH NORECOVERY;
GO
Now we can restore the full backups of the read-write filegroups:-
--http://msdn.microsoft.com/en-us/library/aa337540.aspx
--Restore primary filegroup
RESTORE DATABASE [FGRestoreTEST_Dev]
FILEGROUP = 'PRIMARY'
FROM DISK = 'C:\SQLServer\Backups\FGRestoreTEST_PRIMARY.bak'
WITH NORECOVERY;
GO
--Restore FG2014 filegroup
RESTORE DATABASE [FGRestoreTEST_Dev]
FILEGROUP = 'FG2014'
FROM DISK = 'C:\SQLServer\Backups\FGRestoreTEST_FG2014.bak'
WITH NORECOVERY;
GO
Then the differential backups:-
--Restore PRIMARY differential backup
RESTORE DATABASE [FGRestoreTEST_Dev]
FILEGROUP = 'PRIMARY'
FROM DISK = 'C:\SQLServer\Backups\FGRestoreTest_PRIMARYDIFF.bak'
WITH NORECOVERY;
GO
--Restore FG2014 differential backup
RESTORE DATABASE [FGRestoreTEST_Dev]
FILEGROUP = 'FG2014'
FROM DISK = 'C:\SQLServer\Backups\FGRestoreTest_FG2014DIFF.bak'
WITH NORECOVERY;
GO
Then the transaction log backup:-
RESTORE LOG [FGRestoreTEST_Dev]
FROM DISK = 'C:\SQLServer\Backups\FGRestoreTest_LogBackup.trn'
WITH NORECOVERY;
GO
Finally, the database can be recovered:-
RESTORE DATABASE [FGRestoreTest_DEV] WITH RECOVERY;
GO
And as a final test, check the data:-
USE [FGRestoreTEST_Dev];
GO
SELECT COUNT(*) AS [PRIMARY_TABLE]
FROM [PRIMARY_TABLE];
SELECT COUNT(*) AS [FG2010_TABLE]
FROM [FG2010_TABLE];
SELECT COUNT(*) AS [FG2011_TABLE]
FROM [FG2011_TABLE];
SELECT COUNT(*) AS [FG2012_TABLE]
FROM [FG2012_TABLE];
SELECT COUNT(*) AS [FG2013_TABLE]
FROM [FG2013_TABLE];
SELECT COUNT(*) AS [FG2014_TABLE]
FROM [FG2014_TABLE];
SELECT TOP (1) *
FROM [FG2014_TABLE];
GO
So, from the data changes made, we would expect to see 300 records in the PRIMARY & FG2014 filegroups, 100 in the rest and the all the values in the name column in the FG2014 set as 'NEW'.
A1: Yes you can have this scenario however, the backup strategy does not provide an ongoing way to recover FG2010 through 2013 should there be a need to, as only a one time FULL database backup exists.
A2: Yes, with some tweaking. What you are wishing to implement is called a Piecemeal Restore and the bulk of the required instruction for the method required can be found in the Books Online Example: Piecemeal Restore of Only Some Filegroups.
The key difference is you will be restoring over a previously restored full database backup, rather than a live database that has experienced an issue with specific filegroups.
You should be easily able to create a test case/proof of concept for your needs swiftly by using the above reference. If you get stuck, add your attempt/code to question and the good community chaps here will provide guidance. With a little effort from you and some direction from the community, I'm sure you can answer your own question. Teach a man to fish and all that........

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 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