System vs User-Defined Functions in SQL Server: A First Look

System vs User-Defined Functions in SQL Server: A First Look

Every function you’ve used so far — COUNT, GETDATE, UPPER — ships with SQL Server itself. Soon (in the advanced course) you’ll write your own. Here’s the map before you get there, including why the choice between function types is a genuine engineering decision, not just a syntax preference.

Built-in Toolbox vs. Your Own(system functions vs user-defined)System Functionsbuilt-in — read onlyGETDATE()SUM()UPPER()COUNT()Your Functionsyou write theseCalculateAge()GetActiveStartups()GetStartupReport()vsA scalar UDF in WHERE can run onceper row, invisible to the optimizer —“which type” is a real perf decision.

Two Categories

Type Example Who defines it
System function GETDATE(), SUM(), UPPER() Built into SQL Server
Scalar UDF dbo.CalculateAge(birthdate) You write it, returns one value
Inline table-valued (iTVF) dbo.GetActiveStartups() You write it, returns a table, behaves like a parameterized view
Multi-statement TVF dbo.GetStartupReport(@year) You write it, builds a table procedurally, statement by statement

A Preview of What a Scalar UDF Looks Like

You’re not expected to write this yet, but seeing the shape demystifies it — it’s really just a named, reusable calculation:

CREATE FUNCTION dbo.CalculateAge (@birthdate DATE)
RETURNS INT
AS
BEGIN
    RETURN DATEDIFF(YEAR, @birthdate, GETDATE());
END;

-- Once created, it's used exactly like a built-in function:
SELECT name, dbo.CalculateAge('1995-06-15') AS age FROM dbo.Startup;

Notice it slots directly into a SELECT list, just like UPPER() or DATEDIFF() — from the caller’s perspective, a well-written scalar UDF is indistinguishable from a system function. That’s exactly the point: it extends SQL Server’s function library with your own domain-specific logic.

Why the Choice Between These Types Actually Matters

This isn’t just a naming exercise. A scalar UDF called inside a WHERE clause against every row of a large table can quietly turn a query that should take milliseconds into one that takes seconds — because (in most SQL Server versions before 2019’s scalar UDF inlining improvements) the function executes once per row, outside the query optimizer’s usual cost-based reasoning. An inline TVF, by contrast, gets expanded directly into the surrounding query and optimized like ordinary SQL. This single distinction — can the optimizer see through it or not — is one of the most consequential real-world performance decisions a T-SQL developer makes, and it’s covered in full in the advanced course once you have the query-plan-reading skills to actually verify the difference yourself.

Where This Goes Next

This Course Use system functions confidently and correctly Advanced Track Write your own scalar, iTVF, and mTVF functions

Writing your own functions — and understanding the real performance tradeoffs between the three types — is a full topic in SQL Server for Developers & DBAs (Chapter 2 there is dedicated entirely to this). For now, the goal is simply recognizing that this whole other category exists, and that “which function type” is a real design decision, not an arbitrary label.

Practice tip: Next time you use a built-in function like DATEDIFF or ROUND, pause and ask: “if I had to write this myself as a scalar function, what would the body look like?” You already have enough T-SQL from this chapter to answer that for several of them — which is exactly the mental bridge to writing real UDFs later.

Enjoyed this?

Subscribe to get every new SQL Server lesson as soon as it’s published, and share it with a developer who’d find it useful.

📡 Subscribe via RSS  | 
Share on X  | 
Share on LinkedIn  | 
Share on Facebook

Want the full structured course with quizzes, projects, and 10+ exercises per chapter? Check out SQL Server Fundamentals, coming soon on this site.