Quantcast
Viewing all articles
Browse latest Browse all 3160

Write More Compact SQL Server Code Using New Features - Part 2

By:Sergey Gigoyan | Last Updated: 2018-12-03 || Related Tips:More > T-SQL

Problem

In theprevious article, we have discussed how the new features of SQL Server allows us to rewrite the old code in a more compact way. In this article, we will continue to demonstrate some other new features of SQL Server 2016/2017, allowing us to write shorter code for the same tasks.

Solution

In this article, we will demonstrate the usage of two string functions STRING_SPLIT and CONCAT_WS introduced in SQL Server 2016 and 2017 correspondingly and will compare the old code written without using these functions with the new code.

Creating the test environment

In theprevious article, we created the TestDB database with three tables and data: Student, Course, and StudentCourse table that represents the mapping between Student and Course tables:

USE master
GO
--Database
CREATE DATABASE TestDB
GO
USE TestDB
GO
--Tables
CREATE TABLE Student
(
StudentID INT NOT NULL,
LoginName NVARCHAR(50),
PRIMARY KEY (StudentID)
)
GO
CREATE TABLE Course
(
CourseID INT NOT NULL,
CourseName NVARCHAR(50) UNIQUE,
PRIMARY KEY (CourseID)
)
GO
CREATE TABLE StudentCourse
(
StudentCourseID INT NOT NULL IDENTITY(1,1),
StudentID INT,
CourseID INT,
PRIMARY KEY (StudentCourseID),
CONSTRAINT UC_StudentID_CourseID UNIQUE(StudentID,CourseID),
)
GO
--Filling data
INSERT INTO Student(StudentID, LoginName)
VALUES (1, ' <a href="/cdn-cgi/l/email-protection" data-cfemail="99edf6f4d9edfceaedecf7f0effcebeaf0ede0b7faf6f4">[email protected]</a> '),
(2, '<a href="/cdn-cgi/l/email-protection" data-cfemail="6a190b072a1e0f191e1f04031c0f1819031e1344090507">[email protected]</a> '),
(3, ' <a href="/cdn-cgi/l/email-protection" data-cfemail="5238333c371226372126273c3b243720213b262b7c313d3f">[email protected]</a>'),
(4, '<a href="/cdn-cgi/l/email-protection" data-cfemail="f1909f9fb185948285849f9887948382988588df929e9c">[email protected]</a>')
INSERT INTO Course(CourseID, CourseName)
VALUES (1, 'psychology'),
(2, 'physics'),
(3, 'chemistry'),
(4, 'astrology'),
(5, 'mathematics'),
(6, 'biology'),
(7, 'geography')
INSERT INTO StudentCourse(StudentID, CourseID)
VALUES (1, 1),
(1, 3),
(1, 5),
(2, 5),
(3, 1),
(3, 2),
(3, 3),
(3, 4),
(3, 5),
(3, 6),
(3, 7),
(4, 2),
(4, 4),
(4, 5)

In this article, we will also use this environment for testing the remainder of the examples.

Build a Single-Column SQL Server Table from Separated Values in a String

Many developers have faced a situation where they needed to separate values in a string into several rows. Let's imagine, that we regularly receive updated, comma-separated list of subjects and we need to update the data in the 'Course' table.

Let's assume that we have been provided with the following string as a list of subjects to compare them with the subjects in the 'Course' table and add the new subjects to the table:

'psychology,physics,chemistry,astrology,mathematics,biology,geography,computer science,history'

Having a single-column table, like in the picture below, instead of the comma-separated list will allow us to compare and merge data into the existing table. So, we need to convert the comma-separated string to a single-column table.


Image may be NSFW.
Clik here to view.
Write More Compact SQL Server Code Using New Features - Part 2

Earlier SQL Server Versions - Separate Delimited String into Rows Using a Loop

Before SQL Server 2016, we can solve this task in the following way:

USE TestDB
GO
--Comma-separated string into table in older versions of SQL Server
DECLARE @Subject TABLE
(
SubjectName NVARCHAR(50)
)
DECLARE @CurrentValue NVARCHAR(50)
DECLARE @str NVARCHAR(MAX)='psychology,physics,chemistry,astrology,mathematics,biology,geography,computer science,history'
WHILE CHARINDEX(',',@str)>0
BEGIN
SET @CurrentValue = (SELECT SUBSTRING(@str,1,CHARINDEX(',',@str)-1) )
INSERT INTO @Subject(SubjectName)
VALUES(@CurrentValue)
SET @str=(SELECT RIGHT(@str, LEN(@str)-LEN(@CurrentValue )-1 ))
END
INSERT INTO @Subject(SubjectName)
VALUES(@str)
SELECT * FROM @Subject

We declare a table variable and inside the WHILE loop, we separate each subject from the string by using several string functions and then insert these values into the table variable.

SQL Server 2016 and Beyond - Separate Delimited String into Rows Using STRING_SPLIT

SQL Server 2016 introduced the function STRING_SPLIT. This allows us to solve the same task by writing a single line of code. This function accepts two parameters: string and separator and returns a table with one column called VALUE, where values in the VALUE column are fragments of the string defined by the separator. Using this function, we can rewrite the code above in the following way:

USE TestDB
GO
--Comma-separated string into table in SQL Server 2016 and higher versions
SELECT VALUE AS SubjectName
FROM STRING_SPLIT('psychology,physics,chemistry,astrology,mathematics,biology,geography,computer science,history', ',')

As we can see the code is much shorter, but the result is the same:


Image may be NSFW.
Clik here to view.
Write More Compact SQL Server Code Using New Features - Part 2

We can then use a MERGE statement to insert the new subjects into the Course table as follows:

USE TestDB
GO
DECLARE @MaxCourseID INT
SET @MaxCourseID = (SELECT MAX(CourseID) FROM Course)
MERGE
Course AS target
USING
(SELECT ROW_NUMBER() OVER (ORDER BY VALUE) + @MaxCourseID AS SubjectID,
VALUE AS SubjectName FROM STRING_SPLIT('psychology,physics,chemistry,astrology,mathematics,biology,geography,computer science,history', ',') ) AS source
ON target.CourseName=source.SubjectName
WHEN NOT MATCHED BY target
THEN INSERT (CourseID, CourseName) VALUES(source.SubjectID, source.SubjectName);
SELECT *
FROM Course
ORDER BY CourseID

We can see that two new courses, (history and computer science) have been added to the table:


Image may be NSFW.
Clik here to view.
Write More Compact SQL Server Code Using New Features - Part 2

Concatenating Several Columns into one Column in SQL Server

For each row, we need to group values from the given columns into one string.

We have a table called StudentAddress for storing students addresses:

USE TestDB
GO
CREATE TABLE StudentAddress
(
StudentAddressID INT NOT NULL IDENTITY(1,1),
StudentID INT REFERENCES Student(StudentID),
AppartmentNum NVARCHAR(25),
Street NVARCHAR(50),
City NVARCHAR(50),
[State] NVARCHAR(50),
PostalCode NVARCHAR(25),
Country NVARCHAR(50),
PRIMARY KEY (StudentAddressID)
)
GO
INSERT INTO StudentAddress(StudentID,AppartmentNum,Street,City,[State], PostalCode, Country)
VALUES (1, 202, 'Queen Street', 'Albany','NH','03818', 'USA'),
(2, 54, 'Teryan Street', 'Yerevan','Yerevan','0204', 'Armenia'),
(3, 97, 'King Str', 'Albuquerque','NM','87101', 'USA'),
(4, 299, 'Woodbin ave', 'Toronto','ON','M4C5K7', 'Canada')
GO
--Students' addresses
SELECT s.LoginName, AppartmentNum,Street,City,[State], PostalCode, Country
FROM Student s
INNER JOIN StudentAddress a ON s.StudentID=a.StudentID

In this table, we have a separate column for each attribute of the address:


Image may be NSFW.
Clik here to view.
Write More Compact SQL Server Code Using New Features - Part 2

However, we have to write a report that will show the students addresses in t

Viewing all articles
Browse latest Browse all 3160

Trending Articles