The PARSENAME function in SQL Server is a handy tool for splitting object names into their constituent parts.
While its primary purpose is to parse fully qualified SQL Server object names, it’s often creatively used for other string parsing tasks.
Let’s dive into how PARSENAME works, its practical applications, and some creative uses that might surprise you.
At its core, PARSENAME is designed to break down four-part SQL Server object names. Here’s its basic syntax:
PARSENAME(object_name, object_piece)
The object_name
is the string you want to parse, and object_piece
is a number from 1 to 4, indicating which part of the name you want to extract. Here’s a quick example:
SELECT PARSENAME('AdventureWorks.dbo.Employee.LastName', 3);
-- Output: dbo
In this example, PARSENAME returns ‘dbo’, which is the third part of the object name when counting from right to left.
One crucial aspect of PARSENAME is that it counts parts from right to left. This can be counterintuitive at first, but it aligns with how SQL Server object names are typically written. Here’s a breakdown:
SELECT
PARSENAME('AdventureWorks.dbo.Employee.LastName', 4) AS DatabaseName,
PARSENAME('AdventureWorks.dbo.Employee.LastName', 3) AS SchemaName,
PARSENAME('AdventureWorks.dbo.Employee.LastName', 2) AS TableName,
PARSENAME('AdventureWorks.dbo.Employee.LastName', 1) AS ColumnName;
This query returns:
DatabaseName SchemaName TableName ColumnName
AdventureWorks dbo Employee LastName
PARSENAME is flexible when dealing with object names that have fewer than four parts:
SELECT
PARSENAME('Employee.LastName', 2) AS TableName,
PARSENAME('Employee.LastName', 1) AS ColumnName;
This returns:
TableName ColumnName
Employee LastName
If you try to parse a part that doesn’t exist (like asking for the 4th part of a two-part name), PARSENAME simply returns NULL:
SELECT PARSENAME('Employee.LastName', 4) AS NonExistentPart;
-- Output: NULL
While PARSENAME is designed for SQL object names, it’s often used creatively for other purposes. Let’s say you have a table of file paths and you want to extract different parts of the path:
CREATE TABLE FilePaths (
ID INT PRIMARY KEY,
Path VARCHAR(255)
);
INSERT INTO FilePaths (ID, Path) VALUES
(1, 'C:\Users\JohnDoe\Documents\report.docx'),
(2, 'D:\Projects\Website\index.html'),
(3, 'E:\Backups\2023\June\database_backup.bak');
SELECT
ID,
PARSENAME(REPLACE(Path, '\', '.'), 1) AS FileName,
PARSENAME(REPLACE(Path, '\', '.'), 2) AS ImmediateDirectory,
PARSENAME(REPLACE(Path, '\', '.'), 3) AS ParentDirectory,
PARSENAME(REPLACE(Path, '\', '.'), 4) AS GrandparentDirectory
FROM FilePaths;
This query first replaces backslashes with periods (since PARSENAME uses periods as delimiters) and then parses the resulting string. The output might look like this:
ID FileName ImmediateDirectory ParentDirectory GrandparentDirectory
1 report.docx Documents JohnDoe Users
2 index.html Website Projects NULL
3 database_backup.bak June 2023 Backups
Another creative use of PARSENAME is for manipulating IP addresses. Since IP addresses use dots as separators, they’re perfect candidates for PARSENAME:
CREATE TABLE NetworkDevices (
ID INT PRIMARY KEY,
DeviceName VARCHAR(50),
IPAddress VARCHAR(15)
);
INSERT INTO NetworkDevices (ID, DeviceName, IPAddress) VALUES
(1, 'MainServer', '192.168.1.100'),
(2, 'Printer', '192.168.1.101'),
(3, 'Router', '192.168.0.1');
SELECT
DeviceName,
IPAddress,
PARSENAME(IPAddress, 4) AS Octet1,
PARSENAME(IPAddress, 3) AS Octet2,
PARSENAME(IPAddress, 2) AS Octet3,
PARSENAME(IPAddress, 1) AS Octet4
FROM NetworkDevices;
This query splits each IP address into its constituent octets:
DeviceName IPAddress Octet1 Octet2 Octet3 Octet4
MainServer 192.168.1.100 192 168 1 100
Printer 192.168.1.101 192 168 1 101
Router 192.168.0.1 192 168 0 1
You can then use these parsed values for further analysis or filtering:
SELECT *
FROM NetworkDevices
WHERE PARSENAME(IPAddress, 2) = '1' AND PARSENAME(IPAddress, 1) > '100';
This query finds devices in the ‘..1.*’ subnet with the last octet greater than 100.
PARSENAME becomes even more useful when combined with other SQL functions. For example, let’s use it with STUFF to modify IP addresses:
SELECT
DeviceName,
IPAddress,
STUFF(IPAddress,
LEN(IPAddress) - LEN(PARSENAME(IPAddress, 1)) + 1,
LEN(PARSENAME(IPAddress, 1)),
'255') AS BroadcastAddress
FROM NetworkDevices;
This query replaces the last octet of each IP address with ‘255’, effectively creating the broadcast address for each subnet:
DeviceName IPAddress BroadcastAddress
MainServer 192.168.1.100 192.168.1.255
Printer 192.168.1.101 192.168.1.255
Router 192.168.0.1 192.168.0.255
While PARSENAME is versatile, it has limitations. It only works with up to four parts and uses periods as delimiters. For more complex parsing, you might need to combine it with other techniques. Here’s an example that parses a string with more than four parts:
DECLARE @LongString VARCHAR(100) = 'part1.part2.part3.part4.part5.part6';
WITH NumberedParts AS (
SELECT
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS PartNumber,
value AS Part
FROM STRING_SPLIT(@LongString, '.')
)
SELECT
MAX(CASE WHEN PartNumber = 1 THEN Part END) AS Part1,
MAX(CASE WHEN PartNumber = 2 THEN Part END) AS Part2,
MAX(CASE WHEN PartNumber = 3 THEN Part END) AS Part3,
MAX(CASE WHEN PartNumber = 4 THEN Part END) AS Part4,
MAX(CASE WHEN PartNumber = 5 THEN Part END) AS Part5,
MAX(CASE WHEN PartNumber = 6 THEN Part END) AS Part6
FROM NumberedParts;
This approach uses STRING_SPLIT and a pivoting technique to handle strings with any number of parts.
While PARSENAME is convenient, it’s not always the most efficient option for large-scale data processing. For bulk operations, consider alternatives like:
Here’s an example of using an indexed computed column:
ALTER TABLE NetworkDevices
ADD LastOctet AS CAST(PARSENAME(IPAddress, 1) AS INT);
CREATE INDEX IX_NetworkDevices_LastOctet ON NetworkDevices(LastOctet);
-- Now you can efficiently query based on the last octet
SELECT * FROM NetworkDevices WHERE LastOctet BETWEEN 100 AND 200;
This approach precalculates the last octet and allows for efficient querying.
The PARSENAME function, while simple in concept, opens up a world of possibilities for string parsing in SQL Server. We’ve explored:
Remember, while PARSENAME is a handy tool, it’s important to choose the right tool for each job. For simple parsing of up to four parts, PARSENAME is excellent. For more complex scenarios, consider combining it with other SQL features or using alternative approaches.