Most people use SQL Server to count things. I used it to draw a Christmas tree.
In a database.
On purpose.
If you’ve ever stared at SSMS and thought “this could use more festive chaos", this is for you.
What we’re doing
We’re going to:
- Create a temp table in tempdb
- Insert a bunch of geometry polygons that form a tree, trunk, and star
- Stamp “MERRY CHRISTMAS” on top using more polygons
- Render “AND A HAPPY / NEW YEAR” using a tiny pixel font built from squares
- Add random baubles because discipline is overrated
- Union it all so SSMS shows one clean shape
Then SSMS becomes your art gallery.
The only requirement is that you need SQL Server with the geometry type available (so basically modern SQL Server). SSMS helps because it can render spatial results visually.
The Code
Paste the whole thing into SSMS and execute it. Then click the Spatial results tab (or the spatial viewer) and enjoy your database becoming a greeting card.
USE tempdb;
GO
DROP TABLE IF EXISTS #xmasTREE;
CREATE TABLE #xmasTREE (shape geometry);
--------------------------------------------------------------------------------
-- 1) Xmas tree (insert ONCE)
--------------------------------------------------------------------------------
INSERT INTO #xmasTREE(shape)
VALUES
(geometry::STGeomFromText('POLYGON((4 0, 0 0, 4 2, 1 2, 4 4, 1 4, 4 6, 2 6, 5 10, 8 6, 6 6, 9 4, 6 4, 9 2, 6 2, 10 0, 4 0))', 0)),
(geometry::STGeomFromText('POLYGON((3.5 0, 4 -1, 6 -1, 6.5 0, 3.5 0))', 0)),
(geometry::STGeomFromText('POLYGON((5 9.5, 4.5 9.25, 4.6 9.9, 4.1 10.2, 4.8 10.2, 5 10.9, 5.2 10.2, 5.9 10.2, 5.4 9.9, 5.5 9.25, 5 9.5))', 0)),
(geometry::STGeomFromText('POLYGON((2 5.5, 1.5 5.25, 1.6 5.9, 1.1 6.2, 1.8 6.2, 2 6.9, 2.2 6.2, 2.9 6.2, 2.4 5.9, 2.5 5.25, 2 5.5))', 0)),
(geometry::STGeomFromText('POLYGON((8 5.5, 7.5 5.25, 7.6 5.9, 7.1 6.2, 7.8 6.2, 8 6.9, 8.2 6.2, 8.9 6.2, 8.4 5.9, 8.5 5.25, 8 5.5))', 0)),
(geometry::STGeomFromText('POLYGON((1 3.5, 0.5 3.25, 0.6 3.9, 0.1 4.2, 0.8 4.2, 1 4.9, 1.2 4.2, 1.9 4.2, 1.4 3.9, 1.5 3.25, 1 3.5))', 0)),
(geometry::STGeomFromText('POLYGON((9 3.5, 8.5 3.25, 8.6 3.9, 8.1 4.2, 8.8 4.2, 9 4.9, 9.2 4.2, 9.9 4.2, 9.4 3.9, 9.5 3.25, 9 3.5))', 0)),
(geometry::STGeomFromText('POLYGON((1 1.5, 0.5 1.25, 0.6 1.9, 0.1 2.2, 0.8 2.2, 1 2.9, 1.2 2.2, 1.9 2.2, 1.4 1.9, 1.5 1.25, 1 1.5))', 0)),
(geometry::STGeomFromText('POLYGON((9 1.5, 8.5 1.25, 8.6 1.9, 8.1 2.2, 8.8 2.2, 9 2.9, 9.2 2.2, 9.9 2.2, 9.4 1.9, 9.5 1.25, 9 1.5))', 0)),
(geometry::STGeomFromText('POLYGON((0 -0.5, -0.5 -0.75, -0.4 -0.1, -0.9 0.2, -0.2 0.2, 0 0.9, 0.2 0.2, 0.9 0.2, 0.4 -0.1, 0.5 -0.75, 0 -0.5))', 0)),
(geometry::STGeomFromText('POLYGON((10 -0.5, 9.5 -0.75, 9.6 -0.1, 9.1 0.2, 9.8 0.2, 10 0.9, 10.2 0.2, 10.9 0.2, 10.4 -0.1, 10.5 -0.75, 10 -0.5))', 0)),
(geometry::STGeomFromText('POLYGON((5 -2, 4.5 -2, 4.5 -1, 5 -1, 5.5 -1, 5.5 -2, 5 -2))', 0));
--------------------------------------------------------------------------------
-- 2) Top text "MERRY CHRISTMAS" (your existing polygons)
--------------------------------------------------------------------------------
INSERT INTO #xmasTREE(shape)
VALUES
(geometry::STGeomFromText('POLYGON((-2 11, -2 12, -1.75 12, -1.5 11.5, -1.25 12, -1 12, -1 11, -1.25 11, -1.25 11.7, -1.5 11.2, -1.75 11.7, -1.75 11, -2 11))', 0)),
(geometry::STGeomFromText('POLYGON((-1 11, -1 12, 0 12, 0 11.8, -0.75 11.8, -0.75 11.6, -0.25 11.6, -0.25 11.4, -0.75 11.4, -0.75 11.2, 0 11.2, 0 11, -1 11))', 0)),
(geometry::STGeomFromText('POLYGON((0 11, 0 12, 1 12, 1 11.5, 0.4 11.5, 1 11, 0.7 11, 0.2 11.4, 0.2 11, 0 11),(0.2 11.8, 0.8 11.8, 0.8 11.7, 0.2 11.7, 0.2 11.8))', 0)),
(geometry::STGeomFromText('POLYGON((1 11, 1 12, 2 12, 2 11.5, 1.4 11.5, 2 11, 1.7 11, 1.2 11.4, 1.2 11, 1 11),(1.2 11.8, 1.8 11.8, 1.8 11.7, 1.2 11.7, 1.2 11.8))', 0)),
(geometry::STGeomFromText('POLYGON((2 12, 2.2 12, 2.5 11.6, 2.8 12, 3 12, 2.6 11.5, 2.6 11, 2.4 11, 2.4 11.5, 2 12))', 0)),
(geometry::STGeomFromText('POLYGON((4 11, 4 12, 5 12, 5 11.8, 4.25 11.8, 4.25 11.2, 5 11.2, 5 11, 4 11))', 0)),
(geometry::STGeomFromText('POLYGON((5 11, 5 12, 5.2 12, 5.2 11.6, 5.8 11.6, 5.8 12, 6 12, 6 11, 5.8 11, 5.8 11.4, 5.2 11.4, 5.2 11, 5 11))', 0)),
(geometry::STGeomFromText('POLYGON((6 11, 6 12, 7 12, 7 11.5, 6.4 11.5, 7 11, 6.7 11, 6.2 11.4, 6.2 11, 6 11),(6.2 11.8, 6.8 11.8, 6.8 11.7, 6.2 11.7, 6.2 11.8))', 0)),
(geometry::STGeomFromText('POLYGON((7.2 11, 7.2 11.2, 7.4 11.2, 7.4 11.8, 7.2 11.8, 7.2 12, 7.8 12, 7.8 11.8, 7.6 11.8, 7.6 11.2, 7.8 11.2, 7.8 11, 7.2 11))', 0)),
(geometry::STGeomFromText('POLYGON((8 11, 8 11.2, 8.8 11.2, 8.8 11.4, 8 11.4, 8 12, 9 12, 9 11.8, 8.2 11.8, 8.2 11.6, 9 11.6, 9 11, 8 11))', 0)),
(geometry::STGeomFromText('POLYGON((9 11.8, 9 12, 10 12, 10 11.8, 9.6 11.8, 9.6 11, 9.4 11, 9.4 11.8, 9 11.8))', 0)),
(geometry::STGeomFromText('POLYGON((10 11, 10 12, 10.25 12, 10.5 11.5, 10.75 12, 11 12, 11 11, 10.75 11, 10.75 11.7, 10.5 11.2, 10.25 11.7, 10.25 11, 10 11))', 0)),
(geometry::STGeomFromText('POLYGON((11 11, 11 12, 12 12, 12 11, 11.75 11, 11.75 11.3, 11.25 11.3, 11.25 11, 11 11),(11.25 11.5, 11.25 11.8, 11.75 11.8, 11.75 11.5, 11.25 11.5))', 0)),
(geometry::STGeomFromText('POLYGON((12 11, 12 11.2, 12.8 11.2, 12.8 11.4, 12 11.4, 12 12, 13 12, 13 11.8, 12.2 11.8, 12.2 11.6, 13 11.6, 13 11, 12 11))', 0));
--------------------------------------------------------------------------------
-- 3) Bottom text "AND A HAPPY" / "NEW YEAR" (renderer)
-- IMPORTANT: no CREATE TABLE here, no tree insert here
--------------------------------------------------------------------------------
DECLARE @Scale2 decimal(10,4) = 0.18;
DECLARE @Gap2 decimal(10,4) = @Scale2;
DECLARE @Step2 decimal(10,4) = (5 * @Scale2) + @Gap2;
DECLARE @LineA nvarchar(50) = N'AND A HAPPY';
DECLARE @LineB nvarchar(50) = N'NEW YEAR';
DECLARE @XA decimal(10,4) = -0.5, @YA decimal(10,4) = -3.4;
DECLARE @XB decimal(10,4) = 0.5, @YB decimal(10,4) = -4.6;
DECLARE @Font2 TABLE (ch nchar(1), r tinyint, c tinyint);
-- Letters needed for these lines: A N D H P Y E W R (already defined here)
-- A
INSERT @Font2 VALUES
(N'A',0,1),(N'A',0,2),(N'A',0,3),(N'A',1,0),(N'A',1,4),(N'A',2,0),(N'A',2,4),
(N'A',3,0),(N'A',3,1),(N'A',3,2),(N'A',3,3),(N'A',3,4),(N'A',4,0),(N'A',4,4),
(N'A',5,0),(N'A',5,4),(N'A',6,0),(N'A',6,4);
-- N
INSERT @Font2 VALUES
(N'N',0,0),(N'N',0,4),(N'N',1,0),(N'N',1,1),(N'N',1,4),(N'N',2,0),(N'N',2,2),(N'N',2,4),
(N'N',3,0),(N'N',3,3),(N'N',3,4),(N'N',4,0),(N'N',4,4),(N'N',5,0),(N'N',5,4),(N'N',6,0),(N'N',6,4);
-- D
INSERT @Font2 VALUES
(N'D',0,0),(N'D',0,1),(N'D',0,2),(N'D',0,3),
(N'D',1,0),(N'D',1,4),(N'D',2,0),(N'D',2,4),(N'D',3,0),(N'D',3,4),
(N'D',4,0),(N'D',4,4),(N'D',5,0),(N'D',5,4),
(N'D',6,0),(N'D',6,1),(N'D',6,2),(N'D',6,3);
-- H
INSERT @Font2 VALUES
(N'H',0,0),(N'H',0,4),(N'H',1,0),(N'H',1,4),(N'H',2,0),(N'H',2,4),
(N'H',3,0),(N'H',3,1),(N'H',3,2),(N'H',3,3),(N'H',3,4),
(N'H',4,0),(N'H',4,4),(N'H',5,0),(N'H',5,4),(N'H',6,0),(N'H',6,4);
-- P
INSERT @Font2 VALUES
(N'P',0,0),(N'P',0,1),(N'P',0,2),(N'P',0,3),
(N'P',1,0),(N'P',1,4),(N'P',2,0),(N'P',2,4),
(N'P',3,0),(N'P',3,1),(N'P',3,2),(N'P',3,3),
(N'P',4,0),(N'P',5,0),(N'P',6,0);
-- Y
INSERT @Font2 VALUES
(N'Y',0,0),(N'Y',0,4),(N'Y',1,0),(N'Y',1,4),(N'Y',2,1),(N'Y',2,3),
(N'Y',3,2),(N'Y',4,2),(N'Y',5,2),(N'Y',6,2);
-- E
INSERT @Font2 VALUES
(N'E',0,0),(N'E',0,1),(N'E',0,2),(N'E',0,3),(N'E',0,4),
(N'E',1,0),(N'E',2,0),
(N'E',3,0),(N'E',3,1),(N'E',3,2),(N'E',3,3),
(N'E',4,0),(N'E',5,0),
(N'E',6,0),(N'E',6,1),(N'E',6,2),(N'E',6,3),(N'E',6,4);
-- W
INSERT @Font2 VALUES
(N'W',0,0),(N'W',0,4),(N'W',1,0),(N'W',1,4),(N'W',2,0),(N'W',2,4),
(N'W',3,0),(N'W',3,2),(N'W',3,4),(N'W',4,0),(N'W',4,2),(N'W',4,4),
(N'W',5,0),(N'W',5,2),(N'W',5,4),(N'W',6,1),(N'W',6,3);
-- R
INSERT @Font2 VALUES
(N'R',0,0),(N'R',0,1),(N'R',0,2),(N'R',0,3),
(N'R',1,0),(N'R',1,4),(N'R',2,0),(N'R',2,4),
(N'R',3,0),(N'R',3,1),(N'R',3,2),(N'R',3,3),
(N'R',4,0),(N'R',4,2),(N'R',5,0),(N'R',5,3),(N'R',6,0),(N'R',6,4);
DECLARE @i2 int, @len2 int, @ch2 nchar(1);
-- Line A
SET @i2 = 1; SET @len2 = LEN(@LineA);
WHILE @i2 <= @len2
BEGIN
SET @ch2 = SUBSTRING(@LineA, @i2, 1);
IF @ch2 <> N' '
BEGIN
INSERT INTO #xmasTREE(shape)
SELECT geometry::STGeomFromText(
CONCAT(
'POLYGON((',
CONVERT(varchar(32), CONVERT(decimal(18,6), @XA + ((@i2-1) * @Step2) + (c * @Scale2))), ' ',
CONVERT(varchar(32), CONVERT(decimal(18,6), @YA + ((6-r) * @Scale2))), ',',
CONVERT(varchar(32), CONVERT(decimal(18,6), @XA + ((@i2-1) * @Step2) + ((c+1) * @Scale2))), ' ',
CONVERT(varchar(32), CONVERT(decimal(18,6), @YA + ((6-r) * @Scale2))), ',',
CONVERT(varchar(32), CONVERT(decimal(18,6), @XA + ((@i2-1) * @Step2) + ((c+1) * @Scale2))), ' ',
CONVERT(varchar(32), CONVERT(decimal(18,6), @YA + ((6-r+1) * @Scale2))), ',',
CONVERT(varchar(32), CONVERT(decimal(18,6), @XA + ((@i2-1) * @Step2) + (c * @Scale2))), ' ',
CONVERT(varchar(32), CONVERT(decimal(18,6), @YA + ((6-r+1) * @Scale2))), ',',
CONVERT(varchar(32), CONVERT(decimal(18,6), @XA + ((@i2-1) * @Step2) + (c * @Scale2))), ' ',
CONVERT(varchar(32), CONVERT(decimal(18,6), @YA + ((6-r) * @Scale2))),
'))'
), 0)
FROM @Font2
WHERE ch = @ch2;
END
SET @i2 += 1;
END
-- Line B
SET @i2 = 1; SET @len2 = LEN(@LineB);
WHILE @i2 <= @len2
BEGIN
SET @ch2 = SUBSTRING(@LineB, @i2, 1);
IF @ch2 <> N' '
BEGIN
INSERT INTO #xmasTREE(shape)
SELECT geometry::STGeomFromText(
CONCAT(
'POLYGON((',
CONVERT(varchar(32), CONVERT(decimal(18,6), @XB + ((@i2-1) * @Step2) + (c * @Scale2))), ' ',
CONVERT(varchar(32), CONVERT(decimal(18,6), @YB + ((6-r) * @Scale2))), ',',
CONVERT(varchar(32), CONVERT(decimal(18,6), @XB + ((@i2-1) * @Step2) + ((c+1) * @Scale2))), ' ',
CONVERT(varchar(32), CONVERT(decimal(18,6), @YB + ((6-r) * @Scale2))), ',',
CONVERT(varchar(32), CONVERT(decimal(18,6), @XB + ((@i2-1) * @Step2) + ((c+1) * @Scale2))), ' ',
CONVERT(varchar(32), CONVERT(decimal(18,6), @YB + ((6-r+1) * @Scale2))), ',',
CONVERT(varchar(32), CONVERT(decimal(18,6), @XB + ((@i2-1) * @Step2) + (c * @Scale2))), ' ',
CONVERT(varchar(32), CONVERT(decimal(18,6), @YB + ((6-r+1) * @Scale2))), ',',
CONVERT(varchar(32), CONVERT(decimal(18,6), @XB + ((@i2-1) * @Step2) + (c * @Scale2))), ' ',
CONVERT(varchar(32), CONVERT(decimal(18,6), @YB + ((6-r) * @Scale2))),
'))'
), 0)
FROM @Font2
WHERE ch = @ch2;
END
SET @i2 += 1;
END
--------------------------------------------------------------------------------
-- 4) Baubles (optional)
--------------------------------------------------------------------------------
DECLARE @counter int = 0;
WHILE (@counter < 25)
BEGIN
INSERT INTO #xmasTREE(shape)
VALUES (geometry::Point(RAND() * 5 + 2.5, RAND() * 8.5, 0).STBuffer(0.3));
SET @counter += 1;
END
-- Show everything as one geometry so SSMS displays the full picture
SELECT geometry::UnionAggregate(shape) AS shape
FROM #xmasTREE
WHERE shape IS NOT NULL;
DROP TABLE #xmasTREE;
How it works (in plain English)
The tree is just polygons. The main outline is one polygon that zigzags upward like layered branches. The trunk is a small rectangle. The star and side ornaments are separate polygons too. This is the part most people miss: you do not “draw” in SQL, you describe shapes as coordinates.
“MERRY CHRISTMAS” is hard-coded geometry. Those letter shapes are prebuilt polygons. Brutal, yes. Reliable, also yes.
The bottom text is generated. This is the fun bit. You define a tiny 5x7-ish pixel font inside a table variable, where each character is a set of (row, col) pixels. Then the script loops through the string and stamps squares into the right places. That means you can write anything as long as you define the letters.
The baubles are circles made from points. This code creates a little circle:
geometry::Point(...).STBuffer(0.3)
Random coordinates make them look like decorations. One warning: RAND() inside loops is not truly random the way people assume. You’ll still get variation, but don’t pretend it’s cryptographically festive.
Three quick upgrades you should do before posting
If you skip these, you’re leaving impact on the table.
- Make the baubles deterministic - Right now, reruns change the look. That’s funny once, annoying after. Use a seeded approach with CHECKSUM(NEWID()) to generate repeatable pseudo randomness per row.
- Let readers customise the message easily - Expose @LineA and @LineB at the top with a comment like “Edit these to change the card.” People love changing the text and reposting.
- Add a second colour layer - SSMS won’t colour it, but you can separate layers (tree, star, baubles, text) into separate result sets so people can screenshot and stack them, or at least understand the composition.
Remix ideas
A few things you might try.
- Change the strings to your team name or your product launch
- Add a snowman using circles and polygons
- Write a tiny font generator and stop hard-coding letters forever
- Make it animate by outputting multiple frames (one per SELECT) and flipping through them
What this is really teaching
Spatial types aren’t just for GIS. They’re a geometric playground hiding in plain sight.
And yes, this is absolutely a misuse of tempdb. That’s the point.