← Back to list

Call Rust code from SQL Server using CLR functions

Let’s make SQL Server taste the speed of Rust through the means of Common Language Runtime (CLR) functions.

Luis Lema · 2026-02-20 03:50 · 5 claps · 9.1 min read
#sqlserver2025 #rust #dot-net-framework
Open on Medium ↗

Call Rust code from SQL Server using CLR functions

Let’s make SQL Server taste the speed of Rust through the means of Common Language Runtime (CLR) functions.

SQL Server doesn’t support calling Rust functions natively, but we can use CLR functions, which let us do things SQL Server can only dream of 😌.

CLR functions have been available since SQL Server 2005.

The body of a CLR function is implemented in the .NET Framework platform.

The .NET Framework is a legacy platform, replaced by .NET (formerly .NET Core). The former is supported by Microsoft but will not evolve further. The latter cannot be used from SQL Server.

With the introduction covered, let’s dive into coding the solution.

Describing the environment we will use

First of all, this is my environment:

  • Visual Studio 2026 (with the .NET desktop development workload)
  • SQL Server 2025 Enterprise Developer
  • Windows 11

Creating the Rust project

Run these commands in the terminal:

cargo new rust_for_sqlserver --lib
cd rust_for_sqlserver

Open the lib.rs file and replace the code with this function:

pub fn remove_numbers(the_string: String) -> String {
    let mut result = String::new();
    for c in the_string.chars() {
        if !c.is_numeric() {
            result.push(c);
        }
    }

    result
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_remove_numbers() {
        let result = remove_numbers("abc123".to_string());
        assert_eq!(result, "abc");
    }
}

I’ve added a test function. If you want to run the test, use this command:

cargo test test_remove_numbers

Now, we need to compile this function into a .dll library so it can be used from a CLR function written in the .NET Framework.

Compile Rust into a dll library

Add the [lib] section to the Cargo.toml file:

[package]
name = "rust_for_sqlserver"
version = "0.1.0"
edition = "2024"

[dependencies]

[lib]
crate-type = ["cdylib"]

cdylib is a build configuration option that tells Rust to export a C interface from Rust code.

Open the lib.rs file and add the following functions to add the C interfaces:

use std::ffi::{CStr, CString};
use std::os::raw::c_char;

// [...]

#[unsafe(no_mangle)]
pub extern "C" fn remove_numbers_c(input: *const c_char) -> *mut c_char {
    if input.is_null() {
        return std::ptr::null_mut();
    }

    let c_str = unsafe { CStr::from_ptr(input) };
    let input_str = match c_str.to_str() {
        Ok(s) => s,
        Err(_) => return std::ptr::null_mut(),
    };
    let result = remove_numbers(input_str.to_string());
    match CString::new(result) {
        Ok(c_string) => c_string.into_raw(),
        Err(_) => std::ptr::null_mut(),
    }
}

#[unsafe(no_mangle)]
pub extern "C" fn free_string(s: *mut c_char) {
    if !s.is_null() {
        unsafe {
            let _ = CString::from_raw(s);
        }
    }
}

This code manages strings and frees memory to avoid leaks.

The procedure to call the free_string function from the .NET project will be described later.

Run this command to create the .dll file for Windows:

cargo build --release --target x86_64-pc-windows-msvc

Note that I’m targeting the x64 platform; this is important because the CLR function must also target x64.

The above command should create the .dll file in the target folder of your Rust project, for example:

c:\rust_for_sqlserver\target\x86_64-pc-windows-msvc\release\draft_rust_for_sqlserver.dll

On my machine, the library looks like this:

With the Rust library ready, it’s time to focus on the SQL Server integration.

Create a .NET library project

Open Visual Studio (2026) and create a Class Library (.NET Framework) project by going to the File > New > Project > Solution… menu.

Click Next.

In the Configure your new project, set these values:

  • Project name: SSFunction
  • Framework: .NET Framework 4.7.2

Leave the other fields with their default values.

You can target other .NET Framework versions if SQL Server supports them and they’re installed.

Add the FunctionDefinitions.cs file and replace the code with this:

using System;
using System.Runtime.InteropServices;
using Microsoft.SqlServer.Server;

namespace SSFunction
{
    public class FunctionDefinitions
    {
        [DllImport(@"C:\rust_for_sqlserver\target\x86_64-pc-windows-msvc\release\rust_for_sqlserver.dll")]
        internal static extern IntPtr remove_numbers_c(string input);

        [SqlFunction(DataAccess = DataAccessKind.Read)]
        public static string RemoveNumbersWithRust2(string input)
        {
            if (input == null)
            {
                return null;
            }
            string result = remove_numbers_c(input);
            return result;
        }
    }
}

The DllImport lets us execute native code from a .dll file.

Ensure that the DllImport parameter points to the full path of the Rust library ( .dll ).

Press Ctrl+B to compile the project.

In the project folder, you’ll find the bin\Debug folder, where the .NET library file called SSFunction.dll is located:

We will upload the .dll file to SQL Server later.

Security considerations for .NET assemblies

Since we are executing native code (rust_for_sqlserver.dll file) from a .NET library SSFunction.dll file, SQL Server requires that the .NET library be a trusted assembly.

That’s because who knows what nasty code 😈 you are intending execute from a native library.

Microsoft made SQL Server 2017 and later versions paranoid enough to mark .NET assemblies UNSAFE by default.

You have two options to make SQL Server trust your .NET assembly:

  1. Set the [TRUSTWORTHY](https://learn.microsoft.com/en-us/sql/relational-databases/security/trustworthy-database-property?view=sql-server-ver17) database property to ON.
  2. Sign your .NET assembly to give it a unique identity.

Allow any non-signed .NET assembly by using the [sys.sp_add_trusted_assembly](https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sys-sp-add-trusted-assembly-transact-sql?view=sql-server-ver17) .

The first option (TRUSTWORTHY ) is not recommended as it leaves your database open to malicious attacks.

I’ll go with the second option because it is the one Microsoft recommends.

Signing .NET assemblies prevents collisions when multiple assemblies have the same file name.

Signing the .NET assembly (library)

As mentioned in the last section, we are going to sign our .NET library.

In Visual Studio, go to the menu Project > SSFunction Properties.

Click in the Signing section, and check the Sign the assembly box. Expand the list from the Choose a strong name key file field, and select the <New…> item.

In the Create Strong Name Key dialog, type a name in the Key file name field:

I will call the file ssfunctionkey.snk , feel free to choose another name.

Uncheck the Protect my key file with a password option (you can also add a password if you wish).

Leave the other fields with their default values and click OK.

Visual Studio will create a file called ssfunctionskey.snk in the root of the project:

Compile the project again with Ctrl+B .

Enabling the CLR in the SQL Server

Check if you have CLR enabled in SQL Server:

SELECT name,
       value,
       value_in_use
FROM sys.configurations
WHERE
    name = 'clr enabled'

Next are the meanings of the value results:

  • 0: CLR is not enabled
  • 1: CLR is enabled

If CLR is not enabled, run this code:

sp_configure 'show advanced options', 1
GO
RECONFIGURE
GO
sp_configure 'clr enabled', 1
GO
RECONFIGURE
GO

Make sure your login to SQL Server has ALTER SETTINGS server-level permission to change or enable CLR.

Uploading the .NET library to SQL Server

Time for some SQL Server bureaucracy to upload the SSFunction.dll file.

I’ll use an existing database called Household .

First and foremost, log in to SQL Server with an account that has the CONTROL permission in the master database.

Run the following code:

USE master
GO
DROP MASTER KEY
CREATE MASTER KEY
    ENCRYPTION BY PASSWORD = '25600you_should_not_share__this_password!';
GO

ALTER MASTER KEY
    ADD ENCRYPTION BY SERVICE MASTER KEY;
GO

Replace the value 25600you_should_not_share__this_password! with your own password.

Next, we need to create an asymmetric key and a login for the .NET assembly; use this code:

USE master
GO
DROP LOGIN SSFunctionLogin
DROP ASYMMETRIC KEY SSFunctionKey
CREATE ASYMMETRIC KEY SSFunctionKey
    FROM EXECUTABLE FILE = 'C:\SSFunction\SSFunction\bin\Debug\SSFunction.dll';

GO
CREATE LOGIN SSFunctionLogin FROM ASYMMETRIC KEY SSFunctionKey;
GO
GRANT UNSAFE ASSEMBLY TO SSFunctionLogin;
GO

Recall to enter the complete path where the SSFunction.dll file is located.

Don’t worry about the SSFunctionLogin login; you won’t use it to log into SQL Server, nor use it from your application.

Now we are ready to upload the .NET library to SQL Server.

Switch to the database from which you want to call the Rust function, in my case, it’s the Household database:

USE Household
GO

DROP FUNCTION IF EXISTS dbo.RemoveNumbersWithRust
DROP ASSEMBLY IF EXISTS SSFunctionAssembly
CREATE ASSEMBLY SSFunctionAssembly
    FROM 'C:\SSFunction\SSFunction\bin\Debug\SSFunction.dll'
    WITH PERMISSION_SET = UNSAFE;
GO

DROP FUNCTION IF EXISTS dbo.RemoveNumbersWithRust
GO
CREATE FUNCTION dbo.RemoveNumbersWithRust(@input NVARCHAR(MAX))
    RETURNS NVARCHAR(MAX)
AS
    EXTERNAL NAME SSFunctionAssembly.[SSFunction.FunctionDefinitions].RemoveNumbersWithRust
GO

Ensure the path to the SSFunction.dll file matches the one used previously for the asymmetric key setup.

Call the Rust function from SQL Server

Here comes the funny part.

If you followed the steps so far, run this statement in your SQL Server database:

USE Household
GO

SELECT dbo.RemoveNumbersWithRust(N'The leading prime numbers are: 1, 2, 3, 5') AS result;
GO

You should get something like this:

Now Rust is at your spell! 🙂

What if you need to change your .NET library? Here’s what to do

Good question. You have to apply any change you want to the .NET library and upload it again to SQL Server.

Let’s modify our SSFunction.dll library.

Do you remember the free_string Rust function we added in an earlier section?

Well, this function frees the memory that Rust allocated for the string we are sending from SQL Server.

You have to free that memory into the .NET library.

Open the FunctionDefinitions.cs file and modify the code:

using System;
using System.Runtime.InteropServices;
using Microsoft.SqlServer.Server;

namespace SSFunction
{
    public class FunctionDefinitions
    {
        [DllImport(@"C:\rust_for_sqlserver\target\x86_64-pc-windows-msvc\release\rust_for_sqlserver.dll")]
        internal static extern IntPtr remove_numbers_c(string input);

        [DllImport(@"C:\rust_for_sqlserver\target\x86_64-pc-windows-msvc\release\rust_for_sqlserver.dll")]
        internal static extern void free_string(IntPtr ptr);

        [SqlFunction(DataAccess = DataAccessKind.Read)]
        public static string RemoveNumbersWithRust(string input)
        {
            if (input == null)
            {
                return null;
            }

            IntPtr ptr = remove_numbers_c(input);
            if (ptr == IntPtr.Zero)
            {
                return null;
            }

            try
            {
                string result = Marshal.PtrToStringAnsi(ptr);
                return result;
            }
            finally
            {
                free_string(ptr); // Call this here to free the memory
            }
        }
    }
}

Compile the .NET project with Ctrl+B .

Go to SQL Server and run this statement:

USE Household
GO
/* The ALTER ASSEMBLY statement will fail if the .dll file has not changes since it was created or last altered. */
ALTER ASSEMBLY SSFunctionAssembly
    FROM 'C:\SSFunction\SSFunction\bin\Debug\SSFunction.dll'
    WITH PERMISSION_SET = UNSAFE;

GO

Test the dbo.RemoveNumbersWithRust function in SQL Server, and it should work:

When you need to alter an assembly in SQL Server, consider keeping method signatures. Find the complete list of restrictions in this documentation.

By the way, if you want to modify the Rust code, you only have to apply your change and build the project to get the updated rust_for_sqlserver.dll file.

Wrapping up

  • One approach to calling Rust code from SQL Server is to use CLR functions from the .NET Framework.
  • The .NET Framework (C# code) acts as an intermediary between SQL Server and Rust.
  • You have to upload your .NET library (which contains the CLR functions) to SQL Server.

Find the whole project in GitHub.

Do you want to know how the story continues in the obfuscated panels?

Let me know in the comments.


메타데이터
post_id
edf79ad476d8
slug
call-rust-code-from-sql-server-using-clr-functions-edf79ad476d8
url
https://medium.com/@lemalcs/call-rust-code-from-sql-server-using-clr-functions-edf79ad476d8
canonical_url
https://medium.com/@lemalcs/call-rust-code-from-sql-server-using-clr-functions-edf79ad476d8
author_url
https://medium.com/@lemalcs
status
ok
fetched_at
2026-07-13 06:56:16