According to Stack Overflow’s 2023 Developer Survey, SQL is the 4th most commonly used programming language among all respondents, with 48.66% reporting its use. Among professional developers, 52% utilize SQL, making it the 3rd most commonly used language in that group.
This underscores the importance of practicing with sample databases for career development in tech.
While finding the perfect SQL practice database isn’t always easy, you definitely need one for:
- Grow your solution portfolio before applying to new jobs.
- Learn about new or specific technologies in a test environment.
- Provide a training environment to try different SQL queries and features.
- Test your backup and restore solutions before applying them to your production databases.
- Prototyping.
- Product demonstration.
- Etc.
That’s why we’ve created a list of databases for you, comparing their features and providing additional details on their uses and how to build them from scratch, including options to enable or disable specific components as needed.
If you want to work with any of these databases, you can either run the script provided by the creator or download a backup from our website and restore it to your instance.
Compare, Download & Start Practicing with a Sample SQL Database
For database professionals seeking robust SQL practice environments, this comprehensive comparison helps identify the most suitable downloadable database samples for specific use cases.
Each database has been evaluated based on version compatibility, size requirements, and complexity of schema design.
Release | Deprecation | Version | Creator | Size | |
---|---|---|---|---|---|
Northwinds | 2000 | 2000 | 2000 + | Microsoft | 80 MB |
Pubs | 2000 | 2000 | 2000 + | Microsoft | 16 MB |
AdventureWorks | 2017-10-26 | 2017 | 2008 + | Microsoft | 272 MB |
AdventureWorksDW | 2017-10-26 | 2017 | 2008 + | Microsoft | 208 MB |
Contoso | 2022-06-04 | — | 2019 + | Microsoft | 22 MB minimum |
WideWorldImporters | 2016 | — | 2016 + | Microsoft | 710 MB |
WideWorldImportersDW | 2016 | — | 2016 + | Microsoft | 487 MB |
Data.gov | — | — | 2019 + | U.S. Government | 208 MB |
Dba.stackexchange.com | — | — | 2019 + | StackExchange | 1287 MB |
Below you can find information about size, number of tables, biggest tables with record count, and a link to download a backup just to be restored:
Tables | Biggest tables and row count | Download | |
---|---|---|---|
Northwinds | 13 | Order Details 2155 Orders 830 Customers 91 | Northwinds.bak |
Pubs | 11 | Roysched 86 Employee 43 Titleauthor 25 | Pubs.bak |
AdventureWorks | 71 | SalesOrderDetail 121317 TransactionHistory 113443 TransactionHistoryArchive 89253 | AdventureWorks.bak |
AdventureWorksDW | 31 | FactProductInventory 776286 FactInternetSalesReason 64515 FactResellerSales 60855 | AdventureWorksDW.bak |
Contoso | 8 | OrderRows 208969 CurrencyExchange 202100 Orders 87053 | Contoso.100K.bak |
WideWorldImporters | 48 | ColdRoomTemperatures_Archive 3654736 StockItemTransactions 236667 OrderLines 231412 | WideWorldImporters-Full.bak |
WideWorldImportersDW | 29 | Movement 236667 Order 231412 Sale 228265 | WideWorldImportersDW-Full.bak |
Data.gov | 1 | Electric_Vehicle_Population_Data 150483 | data.gov.bak |
Dba.stackexchange.com | 8 | Votes 892171 PostHistory 814930 Badge 416662 | dba.stackexchange.com.bak |
Best 4 Sample SQL DBA Review
Here’s our breakdown of the four most useful sample databases for SQL practice and why we love them.
1. Northwinds and Pubs
These are small, general-purpose databases designed to help you quickly set up a demo or prototype in any technology. Running the scripts is the fastest way to create them, and you can do so in any version you choose.
However, they won’t meet your needs for testing with large volumes of data unless you already have a method to populate them.
2. AdventureWorks
If it´s your first time creating a database and you want to learn about standard features like 3NF normalization, user-defined data types, XML, schema segregation, bulk insert CSV files, triggers, and documenting the database, then AdventureWorks perfectly suits your needs.
This database is also used when learning about Reporting Services (SSRS). You can find tutorials and solutions at this link.
The database creation script is located here.
When I ran it manually, I had to specify the codepage ‘RAW’ when loading the Address table (see this link) and install the FullText feature before getting a successful execution. Running the script took only 8 seconds, and you can run it in any SQL Server version starting from 2008.
In the same location, the script to create the AdventureWorksDW database is provided, which you can use to learn about Integration Services (SSIS) and Analysis Services (SSAS); you can get the tutorials and solutions here. Running the script took only 4 seconds, and you can run it in any SQL Server version starting from 2008.
3. Contoso
This is another data warehouse database that you can use for learning and running Business Intelligence projects, such as Analysis Services processes, Power BI reports, and more.
Microsoft provides various backups (sizes: 10K, 100K, 1M, 10M), as well as compressed data files (sizes: 100M and 1G) that can be attached to an instance. Additionally, they offer a data generator program, which you can customize to create your own data distribution, along with its source code, allowing you to modify and extend it as needed.
If you download the backups or data files, you can restore or attach them in SQL Server 2019 or later. However, if you generate your own data using the executable, you can attach it to any version of SQL Server.
In my case, I restored the backup file using the code below:
USE [master]
RESTORE DATABASE [Contoso]
FROM DISK = N'C:\setup\Contoso.100K.bak'
WITH FILE = 1
,MOVE N'Contoso 100K' TO N'C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\DATA\Contoso.mdf'
,MOVE N'Contoso 100K_log' TO N'C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\DATA\Contoso_log.ldf'
,NOUNLOAD
,REPLACE
,STATS = 5
4. WideWorldImporters
This is the most recent and biggest dataset provided by Microsoft.
It not only includes OLTP (Online Transaction Processing) and DW databases (data warehouse), but also you’ll find on the download page the Integration Services projects, scripts to learn and use recent SQL Server features (always encrypted, in-memory, analytics, polybase, and row level security), and sample workloads in Windows Forms (multithreaded order insert and multithreaded in-memory vehicle location insert).
When you download the source code, you’ll also gain access to several additional resources: an IoT Smart Grid application, the ContosoDW database, guides on using Master Data Services, R Services, and Azure SQL DB elastic pools. On the samples page, you’ll find even more projects, including Power BI dashboards, Dynamic Data Masking, the OLTP project, the OLAP project, the Analysis Services Multidimensional project, and the Integration Services project for performing ETL between the OLTP and DW databases.”
In my case, I restored the OLTP backup file using the code below:
USE [master]
RESTORE DATABASE [WideWorldImporters]
FROM DISK = N'C:\setup\WideWorldImporters-Full.bak'
WITH FILE = 1
,MOVE N'WWI_Primary' TO N'C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\DATA\WideWorldImporters.mdf'
,MOVE N'WWI_UserData' TO N'C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\DATA\WideWorldImporters_UserData.ndf'
,MOVE N'WWI_Log' TO N'C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\DATA\WideWorldImporters.ldf'
,MOVE N'WWI_InMemory_Data_1' TO N'C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\DATA\WideWorldImporters_InMemory_Data_1'
,NOUNLOAD
,STATS = 5
And restored the DW backup file using the code below:
USE [master]
RESTORE DATABASE [WideWorldImportersDW]
FROM DISK = N'C:\setup\WideWorldImportersDW-Full.bak'
WITH FILE = 1
,MOVE N'WWI_Primary' TO N'C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\DATA\WideWorldImportersDW.mdf'
,MOVE N'WWI_UserData' TO N'C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\DATA\WideWorldImportersDW_UserData.ndf'
,MOVE N'WWI_Log' TO N'C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\DATA\WideWorldImportersDW.ldf'
,MOVE N'WWIDW_InMemory_Data_1' TO N'C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\DATA\WideWorldImportersDW_InMemory_Data_1'
,NOUNLOAD
,STATS = 5
These aren’t the only free datasets available, but they are the easiest to start with since they come as backup files ready to be restored into your SQL Server instance.
Repositories for SQL Testing Databases
While there are other repositories online with additional datasets and guides to build your own projects, loading them into SQL Server requires knowledge of Integration Services, bulk loading, or Polybase. Additionally, you’ll need to invest time in creating the project to load the data in the format you need.
Several of these repositories can be found at:
- 43 Free Datasets for Building an Irresistible Portfolio (2024) – Dataquest
- Publicly Available Big Data Sets – Hadoop Illuminated
- Top 100 Open Source Datasets for Data Science – Medium
- Navigating Free Datasets: Sourcing for Accuracy – Atlassian
- Big Data: 33 Brilliant And Free Data Sources Anyone Can Use – Forbes
For example, I downloaded from data.gov the EV Population Data which then I loaded into the database using SQL Server Import and Export Wizard as described here, but some columns required manually specifying bigger sizes and the result database contains only one table. The same can be done for other datasets provided there.
On census.gov, you can find more correlated data, with information collected yearly on the same topics. This makes it easier to build larger schemas by loading multiple related tables or expanding datasets by combining data from multiple years for the same table.
The sites Bureau of Transportation Statistics and National Highway Traffic Safety Administration provide you with means to build your own dataset by choosing the filters before downloading the data, thus reducing your time and efforts in building a dataset with only the information you want.
If you need multiple tables, then downloading the Stack Exchange Data Dump is a better option.
I downloaded the DBA database which contains 8 tables:
- Badges
- Comments
- PostHistory
- PostLinks
- Posts
- Tags
- Users
- Votes
Loading the Badges table is accomplished by running this script (modified from the code provided at this link):
CREATE TABLE Badge (
Id INT,
UserId INT,
Name VARCHAR(50),
Date DATETIME,
Class INT,
TagBased BIT);
DECLARE @records xml
SELECT @records = C FROM OPENROWSET (BULK 'C:\setup\dba.stackexchange.com\Badges.xml', SINGLE_BLOB) AS records(C)
DECLARE @hdoc int
EXEC sp_xml_preparedocument @hdoc OUTPUT, @records
INSERT INTO PostHistory
SELECT * FROM OPENXML (@hdoc, '/badges/row', 1)
WITH(
Id INT,
PostHistoryTypeId INT,
PostId INT,
RevisionGUID UNIQUEIDENTIFIER,
CreationDate DATETIME,
UserId INT,
Text VARCHAR(MAX),
ContentLicense VARCHAR(12))
EXEC sp_xml_removedocument @hdoc
The total elapsed time was 31 seconds to load 416662 rows into the Badges table, and the other tables are loaded in a similar way.
Note: The backup provided lacks primary and foreign keys, which you can create if needed.
Master SQL with Hands-On Query Exercises Using Sample Databases
Sharpen your SQL skills with real-world queries – execute, optimize, and master database operations today!
Beginner-Level SQL Queries (Using Northwind & Pubs)
Ideal for those new to SQL, these queries cover fundamental operations such as retrieving data, filtering results, and combining tables using JOIN
s.
Retrieve All Customers from Northwind:
SELECT CustomerID, CompanyName, ContactName, Country
FROM Customers;
Practice basic SELECT
statements while learning to specify columns explicitly.
List Orders Placed After January 1, 2025:
SELECT
OrderID,
CustomerID,
OrderDate,
RequiredDate
FROM Orders
WHERE OrderDate > '2025-01-01 00:00:00';
Get comfortable with filtering data using WHERE conditions and proper datetime formatting.
Find the Total Number of Orders per Customer:
SELECT
CustomerID,
COUNT(OrderID) AS TotalOrders,
SUM(Freight) AS TotalFreight
FROM Orders
GROUP BY CustomerID
ORDER BY TotalOrders DESC;
Learn how to use GROUP BY
for aggregation and multiple aggregate functions.
Join Customers and Orders to See Order Details:
SELECT
c.CustomerID,
c.CompanyName,
o.OrderID,
o.OrderDate,
od.Quantity,
p.ProductName
FROM Customers c
JOIN Orders o ON c.CustomerID = o.CustomerID
JOIN [Order Details] od ON o.OrderID = od.OrderID
JOIN Products p ON od.ProductID = p.ProductID
ORDER BY o.OrderDate DESC;
Understand relational database concepts and multiple JOIN
operations.
Intermediate-Level SQL Queries (Using AdventureWorks)
At this stage, you should start working with Stored Procedures, Triggers, and Indexing. AdventureWorks provides a complex schema for simulating real-world enterprise databases.
Create a Stored Procedure to Get Customer Order History:
CREATE PROCEDURE Sales.GetCustomerOrders @CustomerID INT
,@StartDate DATE = NULL
,@EndDate DATE = NULL
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
SELECT soh.SalesOrderID
,soh.OrderDate
,soh.TotalDue
,soh.STATUS
,sod.OrderQty
,p.Name AS ProductName
FROM Sales.SalesOrderHeader soh
JOIN Sales.SalesOrderDetail sod ON soh.SalesOrderID = sod.SalesOrderID
JOIN Production.Product p ON sod.ProductID = p.ProductID
WHERE soh.CustomerID = @CustomerID
AND (
@StartDate IS NULL
OR soh.OrderDate >= @StartDate
)
AND (
@EndDate IS NULL
OR soh.OrderDate <= @EndDate
)
ORDER BY soh.OrderDate DESC;
END TRY
BEGIN CATCH
THROW;
END CATCH
END;
Learn to create reusable SQL logic using stored procedures with error handling and optional parameters.
Create an Index on the SalesOrderDetail Table to Improve Performance:
CREATE NONCLUSTERED INDEX IX_SalesOrderDetail_ProductID ON Sales.SalesOrderDetail (
ProductID ASC
,OrderQty DESC
) INCLUDE (
UnitPrice
,UnitPriceDiscount
)
WITH (
PAD_INDEX = OFF
,STATISTICS_NORECOMPUTE = OFF
,SORT_IN_TEMPDB = OFF
,DROP_EXISTING = OFF
,ONLINE = ON
);
Boost query speed by implementing proper indexing strategies with included columns.
Implement a Trigger to Log Order Insertions:
CREATE TRIGGER Sales.trg_OrderInsert ON Sales.SalesOrderHeader
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
INSERT INTO Sales.OrderAuditLog (
OrderID
,CustomerID
,OrderDate
,TotalDue
,InsertedDate
,InsertedBy
)
SELECT i.SalesOrderID
,i.CustomerID
,i.OrderDate
,i.TotalDue
,GETDATE()
,SYSTEM_USER
FROM inserted i;
END TRY
BEGIN CATCH
THROW;
END CATCH
END;
Enhance database automation by using triggers with proper error handling and auditing.
Advanced-Level SQL Queries (Using WideWorldImporters)
For DBAs and experienced SQL professionals, this section focuses on CTEs, Window Functions, and Query Optimization. WideWorldImporters is designed for high-volume transactional workloads, making it ideal for complex SQL testing.
Use a Common Table Expression (CTE) to Get the Top 5 Products by Sales:
WITH ProductSales
AS (
SELECT si.StockItemID
,si.StockItemName
,SUM(ol.Quantity) AS TotalQuantitySold
,SUM(ol.Quantity * ol.UnitPrice) AS TotalRevenue
FROM Warehouse.StockItems si
JOIN Sales.OrderLines ol ON si.StockItemID = ol.StockItemID
JOIN Sales.Orders o ON ol.OrderID = o.OrderID
WHERE o.OrderDate >= DATEADD(MONTH, - 12, GETDATE())
GROUP BY si.StockItemID
,si.StockItemName
)
SELECT TOP 5 StockItemID
,StockItemName
,TotalQuantitySold
,TotalRevenue
,FORMAT(TotalRevenue, 'C') AS FormattedRevenue
FROM ProductSales
ORDER BY TotalRevenue DESC;
Improve query readability and organization with CTEs while handling complex calculations.
Use a Window Function to Rank Employees by Sales Performance:
SELECT p.PersonID
,p.FullName
,YEAR(o.OrderDate) AS SalesYear
,MONTH(o.OrderDate) AS SalesMonth
,SUM(o.TotalAmount) AS TotalSales
,COUNT(DISTINCT o.OrderID) AS NumberOfOrders
,RANK() OVER (
PARTITION BY YEAR(o.OrderDate)
,MONTH(o.OrderDate) ORDER BY SUM(o.TotalAmount) DESC
) AS MonthlyRank
,LAG(SUM(o.TotalAmount)) OVER (
PARTITION BY p.PersonID ORDER BY YEAR(o.OrderDate)
,MONTH(o.OrderDate)
) AS PreviousMonthSales
,FORMAT((
SUM(o.TotalAmount) - LAG(SUM(o.TotalAmount)) OVER (
PARTITION BY p.PersonID ORDER BY YEAR(o.OrderDate)
,MONTH(o.OrderDate)
)
) / NULLIF(LAG(SUM(o.TotalAmount)) OVER (
PARTITION BY p.PersonID ORDER BY YEAR(o.OrderDate)
,MONTH(o.OrderDate)
), 0) * 100, 'N2') AS MonthOverMonthGrowth
FROM Application.People p
JOIN Sales.Orders o ON p.PersonID = o.SalespersonPersonID
WHERE p.IsSalesperson = 1
GROUP BY p.PersonID
,p.FullName
,YEAR(o.OrderDate)
,MONTH(o.OrderDate)
ORDER BY SalesYear DESC
,SalesMonth DESC
,TotalSales DESC;
Master advanced analytical functions with window functions, aggregates, and formatted output.
Optimize a Query Using an Index Hint:
SELECT si.StockItemID
,si.StockItemName
,si.UnitPrice
,si.RecommendedRetailPrice
,sh.QuantityOnHand
FROM Warehouse.StockItems si WITH (INDEX (IX_Warehouse_StockItems_StockItemName))
JOIN Warehouse.StockItemHoldings sh ON si.StockItemID = sh.StockItemID
WHERE si.StockItemName LIKE 'USB%'
AND si.UnitPrice < si.RecommendedRetailPrice
AND sh.QuantityOnHand > 0;
Gain control over query execution plans by using index hints and understanding data distribution.
💡 Next Step: Choose a sample database, run these queries, and start optimizing your SQL skills today!Find these helpful? Great! Need a database with specific data or for a certain SQL version? Drop us a line, and we’ll build it for you.
Frequently Asked Questions
Which is the best database to practice SQL?
Where to practice SQL for free?
What are some examples of SQL databases to practice and improve skills?
Can I practice stored procedures and triggers on Northwind database?
How do I handle version compatibility issues when restoring these sample databases?
ALTER DATABASE [DatabaseName] SET COMPATIBILITY_LEVEL = 120
for SQL Server 2014 compatibility.
How can I practice database mirroring with these samples?
Can I test database maintenance plans on these databases?
How do I handle schema changes and version control practice with these databases?
Need help with anything SQL database related?
Red9 Senior DBA experts have 20+ years of experience, schedule a call and talk with the best in the field.