Learning FOCUS: Prices + quantities
May 28, 2025The Fourth Campaign
May 28, 2025Hey there! Ready to dive into the awesome world of SQL Server 2025? This latest release is packed with cool new features and enhancements that you won’t want to miss. Curious to know more? Check out the SQL Server on Linux release-notes for all the exciting details!
In this blog post, I will show you how quick and easy it is to get SQL Server 2025 up and running in a container on Windows Subsystem for Linux (WSL). We’ll create a test database, set up some tables, and even play around with a few REGEX functions using the latest SQL Server Management Studio!
Running SQL Server in containers on WSL is super flexible for development and testing. It’s perfect for developers who want to experiment with Linux-native features on a Windows machine without needing a separate Linux system. Let’s get started!
For detailed instructions on setting up WSL, check out the Install WSL guide. You can also deploy SQL Server as a systemd service by following the SQL Server Installation on WSL guide.
First things first, install WSL and a SQL Server 2025 compatible distro. For this demo, I went with Ubuntu 22.04. I’ve already got Docker Desktop installed on my machine to manage the containers. With this setup, you can install any supported SQL Server on the WSL-compatible distro for testing or demo purposes. It’s super handy for any development work too.
wsl -l -o
wsl –install Ubuntu-22.04
Heads up! The above step might need a system restart and will automatically download Ubuntu if it’s not already on your system.
Next, let’s deploy SQL Server 2025 on Ubuntu 22.04. I ran a simple docker run command, and ta-da! I can connect to it using SQL Server Management Studio, as shown in below:
docker run -e “ACCEPT_EULA=Y” -e “MSSQL_SA_PASSWORD=DontUseThisSmartPwd:)”
-e “MSSQL_PID=Developer” -e “MSSQL_AGENT_ENABLED=true”
-p 14333:1433 –name sqlcontainerwsl –hostname sqlcontainerwsl
-d mcr.microsoft.com/mssql/server:2025-latest
I tried out the new SQL Server Management Studio and had some fun testing few REGEX functions:
These tables contain sample data for testing the regular expression functions.*/
— 1. **employees Table: For REGEXP_LIKE Example**
— Create employees table with some records
DROP TABLE IF EXISTS employees
CREATE TABLE employees (
ID INT IDENTITY(101,1),
[Name] VARCHAR(150),
Email VARCHAR(320),
Phone_Number NVARCHAR(20)
);
INSERT INTO employees ([Name], Email, Phone_Number) VALUES
(‘John Doe’, ‘john@contoso.com’, ‘123-4567890’),
(‘Alice Smith’, ‘alice@fabrikam@com’, ‘234-567-81’),
(‘Bob Johnson’, ‘bob.fabrikam.net’,’345-678-9012′),
(‘Eve Jones’, ‘eve@contoso.com’, ‘456-789-0123’),
(‘Charlie Brown’, ‘charlie@contoso.co.in’, ‘567-890-1234’);
GO
— 2. **customer_reviews Table: For REGEXP_COUNT Example**
DROP TABLE IF EXISTS customer_reviews
CREATE TABLE customer_reviews (
review_id INT PRIMARY KEY,
review_text VARCHAR(1000)
);
INSERT INTO customer_reviews (review_id, review_text) VALUES
(1, ‘This product is excellent! I really like the build quality and design.’),
(2, ‘Good value for money, but the software could use improvements.’),
(3, ‘Poor battery life, bad camera performance, and poor build quality.’),
(4, ‘Excellent service from the support team, highly recommended!’),
(5, ‘The product is good, but delivery was delayed. Overall, decent experience.’);
GO
— 3. **process_logs Table: For REGEXP_INSTR Example**
DROP TABLE IF EXISTS process_logs
CREATE TABLE process_logs (
log_id INT PRIMARY KEY,
log_entry VARCHAR(1000)
);
INSERT INTO process_logs (log_id, log_entry) VALUES
(1, ‘Start process… Step 1: Initialize. Step 2: Load data. Step 3: Complete.’),
(2, ‘Begin… Step 1: Validate input. Step 2: Process data. Step 3: Success.’),
(3, ‘Step 1: Check configuration. Step 2: Apply settings. Step 3: Restart.’),
(4, ‘Step 1: Authenticate. Step 2: Transfer data. Step 3: Log complete.’),
(5, ‘Step 1: Initiate system. Step 2: Check logs. Step 3: Shutdown.’);
GO
— 4. **transactions Table: For REGEXP_REPLACE Example**
DROP TABLE IF EXISTS transactions
CREATE TABLE transactions (
transaction_id INT PRIMARY KEY,
credit_card_number VARCHAR(19)
);
INSERT INTO transactions (transaction_id, credit_card_number) VALUES
(1, ‘1234-5678-9101-1121’),
(2, ‘4321-8765-1098-7654’),
(3, ‘5678-1234-9876-5432’),
(4, ‘9876-4321-6543-2109’),
(5, ‘1111-2222-3333-4444’);
GO
— 5. **server_logs Table: For REGEXP_SUBSTR and Data Cleanup Example**
DROP TABLE IF EXISTS server_logs
CREATE TABLE server_logs (
log_id INT PRIMARY KEY,
log_entry VARCHAR(2000)
);
INSERT INTO server_logs (log_id, log_entry) VALUES
(1, ‘2023-08-15 ERROR: Connection timeout from 192.168.1.1 user admin@example.com’),
(2, ‘2023-08-16 INFO: User login successful from 10.0.0.1 user user1@company.com’),
(3, ‘2023-08-17 ERROR: Disk space low on 172.16.0.5 user support@domain.com’),
(4, ‘2023-08-18 WARNING: High memory usage on 192.168.2.2 user hr@office.com’),
(5, ‘2023-08-19 ERROR: CPU overload on 10.1.1.1 user root@system.com’);
GO
— 6. **personal_data Table: For REGEXP_REPLACE (Masking Sensitive Data) Example**
DROP TABLE IF EXISTS personal_data
CREATE TABLE personal_data (
person_id INT PRIMARY KEY,
sensitive_info VARCHAR(100)
);
INSERT INTO personal_data (person_id, sensitive_info) VALUES
(1, ‘John Doe – SSN: 123-45-6789’),
(2, ‘Jane Smith – SSN: 987-65-4321’),
(3, ‘Alice Johnson – Credit Card: 4321-5678-1234-8765’),
(4, ‘Bob Brown – Credit Card: 1111-2222-3333-4444’),
(5, ‘Eve White – SSN: 111-22-3333’);
GO
/*These tables contain realistic sample data for testing the regular expression queries.
You can modify or extend the records as needed for additional complexity. */
/* Let’s see the use cases for `REGEXP_LIKE`, `REGEXP_COUNT`, `REGEXP_INSTR`, `REGEXP_REPLACE`, and `REGEXP_SUBSTR` in SQL.
These examples are designed to handle real-world scenarios with multiple conditions, nested regex functions, or advanced string manipulations.*/
/* 1. **REGEXP_LIKE to filter based on Complex Pattern**
Scenario #1: find all the employees whose email addresses are valid and end with .com
*/
SELECT [Name], Email
FROM Employees
WHERE REGEXP_LIKE(Email, ‘^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.com$’);
GO
/*
Scenario #2: Recreate employees table with CHECK constraints for ‘Email’ and ‘Phone_Number’ columns
*/
DROP TABLE IF EXISTS Employees
CREATE TABLE Employees (
ID INT IDENTITY(101,1),
[Name] VARCHAR(150),
Email VARCHAR(320)
CHECK (REGEXP_LIKE(Email, ‘^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,}$’)),
Phone_Number NVARCHAR(20)
CHECK (REGEXP_LIKE (Phone_Number, ‘^(d{3})-(d{3})-(d{4})$’))
);
INSERT INTO employees ([Name], Email, Phone_Number) VALUES
(‘John Doe’, ‘john@contoso.com’, ‘123-456-7890’),
(‘Alice Smith’, ‘alice@fabrikam.com’, ‘234-567-8100’),
(‘Bob Johnson’, ‘bob@fabrikam.net’,’345-678-9012′),
(‘Eve Jones’, ‘eve@contoso.com’, ‘456-789-0123’),
(‘Charlie Brown’, ‘charlie@contoso.co.in’, ‘567-890-1234’);
GO
— CHECK Constraints – Ensure that the data fulfills the specified criteria.
— FAILURE – Try inserting a row with INVALID values:
INSERT INTO Employees ([Name], Email, Phone_Number) VALUES
(‘Demo Data’, ‘demo@contoso.com’, ‘123-456-7890’);
GO
SELECT * FROM Employees;
—
/* 2. **`REGEXP_COUNT` to Analyze Word Frequency in Text**
Scenario: Counting Specific Words in Large Text Data
Suppose you have a `customer_reviews` table, and you want to count the number of occurrences of specific words like “excellent”, “good”, “bad”, or “poor”
to evaluate customer sentiment. */
SELECT review_id,
REGEXP_COUNT(review_text, ‘b(excellent|good|bad|poor)b’, 1, ‘i’) AS sentiment_word_count, review_text
FROM customer_reviews;
GO
—
/* 3. **`REGEXP_INSTR to Detect Multiple Patterns in Sequence**
Scenario: Identify the Position of Multiple Patterns in Sequence
Imagine you have log data where each entry contains a sequence of steps, and you need to find the position of a specific pattern like “Step 1”, “Step 2”,
and “Step 3”, ensuring they occur in sequence. */
SELECT log_id,
REGEXP_INSTR(log_entry, ‘Steps1.*Steps2.*Steps3’, 1, 1, 0, ‘i’) AS steps_position
FROM process_logs
WHERE REGEXP_LIKE(log_entry, ‘Steps1.*Steps2.*Steps3’, ‘i’);
GO
—
/* 4. **`REGEXP_REPLACE` for replacing string based on the pattern match**
Scenario: Redacting Sensitive Information with Variable Lengths
You need to redact sensitive data from a table that contains personal information like Social Security Numbers (SSNs) and credit card numbers.
The challenge is that the data might be in different formats (e.g., `###-##-####` for SSNs and `####-####-####-####` for credit cards). */
SELECT sensitive_info,
REGEXP_REPLACE(sensitive_info, ‘(d{3}-d{2}-d{4}|d{4}-d{4}-d{4}-d{4})’, ‘***-**-****’) AS redacted_info
FROM personal_data;
GO
—
/* 5. **REGEXP_SUBSTR to Extract Nested Information**
Scenario: Extract Specific Parts of a Complex String Format */
SELECT [Name], Email, REGEXP_SUBSTR(email, ‘@(.+)$’, 1, 1,’c’,1) AS Domain
FROM employees;
GO
—
/* 6. **Combining Multiple REGEXP Functions for Data Transformation**
Scenario: Log Cleanup and Transformation
You have raw server logs that contain noisy data. Your goal is to:
1. Extract the date.
2. Count how many times the word “ERROR” appears.
3. Replace any email addresses with `[REDACTED]`.
*/
SELECT log_entry,
REGEXP_SUBSTR(log_entry, ‘d{4}-d{2}-d{2}’, 1, 1) AS log_date,
REGEXP_COUNT(log_entry, ‘ERROR’, 1, ‘i’) AS error_count,
REGEXP_REPLACE(log_entry, ‘[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,}’, ‘[REDACTED]’) AS cleaned_log
FROM server_logs;
GO
—
–*TVFs*
/* 7. **REGEXP_MATCHES – Find all the match in the string and return in tablular format***/
SELECT * FROM REGEXP_MATCHES (‘Learning #AzureSQL #AzureSQLDB’, ‘#([A-Za-z0-9_]+)’);
/* 8. **REGEXP_SPLIT_TO_TABLE – Split string based on regexp pattern**/
SELECT * FROM REGEXP_SPLIT_TO_TABLE (‘192.168.0.1|80|200|Success|192.168.0.2|443|404|Not Found’, ‘|’)
There are lot of exciting features in SQL Server 2025! The Linux version includes all engine features from the SQL Server 2025 on Windows. Check out the What’s New for SQL Server 2025 Preview on Linux for all the details.
Here are a few highlights:
- Set custom password policy for SQL logins in SQL Server on Linux
- Enable and run tempdb on tmpfs for SQL Server 2025 Preview on Linux
- Connect to ODBC data sources with PolyBase on SQL Server on Linux
These features make SQL Server on Linux super versatile and powerful, giving you the same robust experience as on Windows.
Conclusion
SQL Server 2025 on Linux is a game-changer, offering flexibility and power for developers and IT pros alike. Whether you’re developing, testing, or deploying in production, this setup has got you covered.
🔗 References
- aka.ms/sqlserver2025
- https://aka.ms/Build/sql2025blog.
- https://aka.ms/IntroMirroringSQL
- http://aka.ms/optimized-hp-blog
- https://aka.ms/tempdb-rg-blog
- https://aka.ms/sqlserver2025-ctp-diskann
- SQL Server on Linux FAQ