Archive for the ‘database’ Category

How to TWEET from a SQL CLR Stored Procedure

Here’s another SQL Server 2005 geek out moment, a CLR SPROC that tweets to Twitter. Big shoutout to Danny Battison for sharing the C# code to post to Twitter. This is what got me started on the C# side of things.  Also, you can skip all my ramblings here and just download code here and fire it up.  The zip file contains all the source code, the compiled assembly file, and install.sql that shows you how to hook this up.

Being the SQL junky that I am, I was interested in trying out SQL Server’s new CLR Stored Procedures. A CLR sproc is a stored procedure that is able to use .net code that you’ve compiled into an assembly file. For you classic ASP heads out there, think of the ASP page being the sproc, and the .net assembly being your COM object ( cringe, let’s talk about classic ASP ). While there are plenty of great articles on writing CLR stored procedures, I’m going to breeze through the code that makes up this project.

First make a .net class library that will be compiled into an assembly file.

using System;
using Microsoft.SqlServer.Server;
using System.Data.SqlTypes;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;

/// <summary>
/// This assembly will be used by a SQL2005 SPROC to communicate
/// with twitter.com
/// </summary>
public sealed class tweetsproc
{
    /*
     * TWITTER CODE BORROWED FROM :
     *  http://www.dreamincode.net/code/snippet2556.htm
     *
     * A function to post an update to Twitter programmatically
     * Author: Danny Battison
     * Contact: gabehabe@hotmail.com
     */

    /// <summary>
    /// Post an update to a Twitter acount
    /// </summary>
    /// <param name="username">The username of the account</param>
    /// <param name="password">The password of the account</param>
    /// <param name="tweet">The status to post</param>
    [Microsoft.SqlServer.Server.SqlProcedure(Name = "PostTweet")]
    //public static void PostTweet( string username, string password, string tweet)
    public static void PostTweet(   SqlString username,
                                    SqlString password,
                                    SqlString tweet)
    {
        try
        {
            // encode the username/password
            string user = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(username.ToString() + ":" + password.ToString()));
            // determine what we want to upload as a status
            byte[] bytes = System.Text.Encoding.ASCII.GetBytes("status=" + tweet.ToString());

            // Create a WebPermission.
            WebPermission myWebPermission1 = new WebPermission();

            // Allow Connect access to the specified URLs.
            myWebPermission1.AddPermission(NetworkAccess.Connect,new Regex("http://www\\.twitter\\.com/.*",
              RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline));

            myWebPermission1.Demand();

            // connect with the update page
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://twitter.com/statuses/update.xml");

            // set the method to POST
            request.Method = "POST";
            request.ServicePoint.Expect100Continue = false; // thanks to argodev for this recent change!
            // set the authorisation levels
            request.Headers.Add("Authorization", "Basic " + user);
            request.ContentType = "application/x-www-form-urlencoded";
            // set the length of the content
            request.ContentLength = bytes.Length;

            // set up the stream
            Stream reqStream = request.GetRequestStream();
            // write to the stream
            reqStream.Write(bytes, 0, bytes.Length);
            // close the stream
            reqStream.Close();

            // Let's get the Response from Twitter
            var webresp = request.GetResponse();
            // Let's read the Response
            var sread = new StreamReader( webresp.GetResponseStream() );

            // Use SqlContext to return data to the QueryAnalyzer results window
            SqlContext.Pipe.Send( sread.ReadToEnd() );

        }
        catch (Exception exc)
        {
            // send error back
            SqlContext.Pipe.Send(exc.Message);
        }
    }
}

Here’s the app.config for this assembly.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.web>
    <trust level="Full" processRequestInApplicationTrust="true" originUrl="" />
  </system.web>
</configuration>

Once you build this project, you should have your assembly ( tweetsproc.dll ) which will be used by your CLR Sproc. Now it’s time to do some SQL server work.

Enable CLR access for SQL server

EXEC sp_configure @configname = 'clr enabled', @configvalue = 1
RECONFIGURE WITH OVERRIDE
GO

Create the SQL Assembly

CREATE ASSEMBLY tweetsproc_clr_assembly from 'C:\Users\eric\Desktop\blog\tweetsproc.dll'
WITH PERMISSION_SET = EXTERNAL_ACCESS
GO

Create your SPROC

CREATE PROC tweetsproc_tweet(	@username as nvarchar(50),
								@password as nvarchar(50),
								@tweet as nvarchar(140)
							)
AS
	-- [Assembly Name].[Class Name].[CLR function Name]
	EXTERNAL NAME tweetsproc_clr_assembly.tweetsproc.PostTweet
GO

Tweet from a sproc

EXEC tweetsproc_tweet 'TwitterUsername', 'TwitterPassword', 'Hey @ericfickes, I''m tweeting from my database too!'

Running this sproc returns the XML response from Twitter.

Twitter response from tweet sproc

Tweetsproc returns the full Twitter response

That’s one sample CLR SPROC in the bank!  Feel free to download this code and try it out yourself.  I’d love to get some feedback on anybody looking to use this for real.  While tweeting from a stored procedure probably isn’t a hot topic for anybody, this is a nice teaser for what you can do with CLR sprocs now.

Download code here.

Inside this zip you’ll find this.

  • install.sql is everything you need to install this on your database
  • tweetsproc.dll is the twitter assembly used by the sproc
  • tweetsproc folder is the .net class library project
Contents of tweetsproc.zip

Everything you need to get TWEETING from a sproc

Does SQL Server Management Studio truncate your results?

Ever work with query results that are so long SQL Server Management Studio truncates the results?

truncated query results

sproc results are truncated

I ran into this issue recently while running some utility sprocs that generate C# code for me.  I was thinking I’d have to refactor my sprocs, but then I found this helpful setting under Query Options.

This is the Query Options dialog

Update Max.num characters per column in Query Options > Results > Text

This solved my problem and will hopefully solve yours as well.

  1. Right click the query editor
  2. Left click “Query Options…”
  3. Expand Results in the tree on the left ( in popup dialog )
  4. Click on Text under Results
  5. Set “Maximum number of characters displayed in each column” to a number large enough to see all your results.

Quick and easy, hope I remember this setting.

What happens in EXEC, stays in EXEC. Lifespan of a MSSQL table variable

One of my all time favorite features of MSSQL 2005+ is being able to create table variables on the fly from SELECT statements. This isn’t a lesson in what table variables are, but here is an easy sample in case this is a new concept.

Running this query

SELECT * INTO #myTableVar FROM YourTable

Gives you a new table variable named myTableVar. Table variables are scoped to the active connection, so running this will work.

// make table var
SELECT * INTO #myTableVar FROM YourTable
// show me the data
SELECT * FROM #myTableVar
// you can drop it if you wish
DROP TABLE #myTableVar

However, let’s say you have an aspx page or a sproc that runs this query.

SELECT * INTO #myTableVar FROM YourTable

You can not access myTableVar in a separate connection to the database because as soon as the first query’s connection closes, myTableVar gets dropped.   Here are a few other scenarios that also demonstrate the scoping of a table variable.

-- FAILS
EXEC ('SELECT * INTO #tmp FROM MyTable;');
-- #tmp does not exist
SELECT * FROM #tmp
#tmp only exists inside of EXEC

Table variable #tmp lives inside of EXEC

Here we see that the table variable #tmp only lives for the life of the statement inside of EXEC. The second SELECT * calls is outside of the EXEC statement.

-- #tmp2 works inside of EXEC statement
EXEC ('SELECT * INTO #tmp2 FROM MyTable; SELECT * FROM #tmp2');
table variables in EXEC live in EXEC

What happens in EXEC, stays in EXEC

Here #tmp2 works because it’s being used inside of the EXEC statement. This is worth knowing if you work with dynamic sql statements and exec.

-- works!
SELECT * INTO #tmp FROM MyTable;
-- #tmp exists
SELECT * FROM #tmp
typical sample of using mssql table variable

typical sample of using mssql table variable

This is a typical example that you may use inside a sproc, trigger, script, etc. Both sql calls live in the same space, so #tmp exists.

How to JOIN two tables using LINQ to SQL

Wanted to share this since it gave me so much trouble figuring out.  It’s a simple SQL query ported to LINQ to SQL that joins two tables to return a filtered listed of data.

Here are the tables from my schema
user, user_video, video tables

Here is a basic SQL statement I could fire to retrieve my user videos.

select  *
from    video v, user_videos uv
where   v.vid = uv.vid
and     uv.uid = 2

User 2 has two videos
Here is how you would run the same query using .net’s LINQ to SQL.

// create DB connection
var db = new DBCONN();
// run query
List<video> uvids = (
    from c in db.video
    join o in db.user_videos
    on c.vid equals o.vid
    where o.uid == 2
    select c
).ToList();

This query differs slightly from the screenshot below because I used it in a WCF Service.

Same data, different retrieval method

The variable DBCONN is my database connection that I established when mapping my DB.  If you are not familiar with how to set this up, use the Visual Studio’s “Add the ADO.NET Entity Data Model” wizard.  With your .net project open, right click your project, left click on “Add the ADO.NET Entity Data Model”.  This wizard will walk you through setting up everything you need to setup your DB model file ( edmx ), as well as setting up your database connection and saving it in web.config.

Jesse Liberty did a simple tutorial that uses this wizard in a WCF service application.

I hope this helps somebody out.