The general idea behind CLR procedures is that you can execute code from the SQL server. This is usefull when you reach the limits of what T-SQL can do without making your eyes bleed or as in my case need to interact with webbservices.
So just to get started with this I wanted to create a simple Hello World Example using Visual Studio 2010 that would take an argument, and return a slightly modified value.
First off we need to create a new project. So load up Visual Studio 2010 and create a new project of the type:
Database > SQL Server > Visual C# SQL CLR Database Project.
Make sure you select .NET 3.5 as SQL 2008 can not use CLR procedures compiled using .NET4.0
Image may be NSFW.
Clik here to view.
When you click OK, Visual Studio wants you to select a Database reference, ignore this and click on cancel.
Image may be NSFW.
Clik here to view.
To create our Hello World CLR procedure right click on the project and select Add > Stored Procedure
Image may be NSFW.
Clik here to view.
Name the class something smart, something simple enough that you can figure out what the class does on a Monday morning before the first cup of coffee.
Image may be NSFW.
Clik here to view.
Once you’ve added the procedure copy paste the following code into custom_CLR_HelloWorld (or whatever you named the file).
using System; using System.Data; using System.Data.SqlClient; using System.Data.SqlTypes; using Microsoft.SqlServer.Server; public partial class StoredProcedures { [Microsoft.SqlServer.Server.SqlProcedure] public static void custom_CLR_HelloWorld(SqlString input, out SqlString output) { output = "HelloWorld: " + DateTime.Now + " - " + input.ToString(); } };
Now we’re almost done with our CLR procedure, we just have to change one more thing before we can create our dll and that is to change a build option in the project properties. What we need to do is tell Visual Studio that we also need a Serialization dll along with our normal dll file. To do this go into the project properties and select the build tab and set Generate serialization assembly to On.
The only time you really must have it on is when you are accessing external datastructures, such as web services. If you leave this off you can skip the step below about adding the serialization assembly. Turning it On wont cause any problems even if you dont access web services, which is why I always set it to On anyways.
Image may be NSFW.
Clik here to view.
Image may be NSFW.
Clik here to view.
Once you’ve done this, save the project and Build it (Build > Build Solution). When the build has completed you should have 2 new files in the debug folder of the solution
Image may be NSFW.
Clik here to view.
Now were going to move over to SQL Server Management Studio.
I created a new database for this example and named it [CLRHelloWorld], untill you get the hang of it i suggest you do the same so you dont mess anything up.
When you’ve created a database or decided which database to use open up a new query window and enter the following code into the window. These lines change a few settings to allow us to actually run our CLR procedures.
USE CLRHelloWorld GO ---- Allows you to create external access CLRs ALTER DATABASE [CLRHelloWorld] SET TRUSTWORTHY ON ; GO ---- Enable .net Execution on the SQL server. sp_configure 'clr enable', 1 GO RECONFIGURE GO
You might also have to run the code below to add yourself as the owner of the database, but you can wait with this untill you get the error described, you may not have to run it at all.
-- If you get the message "The database owner SID recorded in the master database -- differs from the database owner SID recorded in database 'xxxxxxxx'" -- It means you have to change database owner. EXEC sys.sp_changedbowner 'CLRHelloWorld\JensB' -- Format: 'DOMAIN\user'
Once the above steps are done we can actually get down to the fun part. Below is the code to first of all remove any previous versions of the CLR and then add the new CLR assemblies and procedure.
-- Remove any previous versions of the CLR procedure IF EXISTS ( SELECT name FROM sysobjects WHERE name = 'custom_CLR_HelloWorld' ) DROP PROCEDURE custom_CLR_HelloWorld GO -- must drop this first because the other assembliy below references this one IF EXISTS ( SELECT [name] FROM sys.assemblies WHERE [name] = N'HelloWorldXmlSerializers' ) DROP ASSEMBLY [HelloWorldXmlSerializers] GO IF EXISTS ( SELECT name FROM sys.assemblies WHERE name = 'HelloWorld' ) DROP ASSEMBLY [HelloWorld] GO -- Add the new Assembly, Part 1 CREATE ASSEMBLY [HelloWorld] FROM 'D:\Projects\CLR\CLRHelloWorld\CLRHelloWorld\bin\Debug\CLRHelloWorld.dll' WITH PERMISSION_SET = EXTERNAL_ACCESS -- allows DLL to make external calls ie webservice calls or system I/O calls -- Add the new Assembly, Part 2 CREATE ASSEMBLY [HelloWorldXmlSerializers] FROM 'D:\Projects\CLR\CLRHelloWorld\CLRHelloWorld\bin\Debug\CLRHelloWorld.XmlSerializers.dll' WITH PERMISSION_SET = SAFE -- Unsafe for unmanaged code GO -- add the new procedure with the paramaters from the class we created CREATE PROCEDURE custom_CLR_HelloWorld @input NVARCHAR(100) , @output NVARCHAR(100) OUTPUT AS EXTERNAL NAME [HelloWorld].StoredProcedures.custom_CLR_HelloWorld -- this is the name from Part 1, followed by the path of the class in the Visual Studio Project GO
When you have gotten the above code to work you can call the shiny new procedure with the code below:
DECLARE @input AS NVARCHAR(100) = N'This is Input' DECLARE @output AS NVARCHAR(100)</p> EXEC custom_CLR_HelloWorld @input, @output OUT SELECT @output
The result should look something like this
HelloWorld: 2012-02-02 10:00:00 - This is Input