SQL Saturday Chicago take 2

SQL Saturday #67 is now in the books. We learned from the first event and made some changes and I think the result was better. Here are some things that we changed:

Core Team

Last year:

Last year the event was organized by Ted (blog | twitter), Wendy (blog | twitter) and myself. This was our first event and we were learning as we went.

This year:

This year in addition to Ted, Wendy and myself, Norm (blog | twitter), Bill (twitter), Bob (blog | twitter) and Rich (twitter) also were part of the planning with Jes (blog | twitter) stepping up at the last minute to help with the T-shirts. Having the additional people with additional contacts was an absolute boon. Responsibilities were able to be delegated and just removed from the list of concerns as well as conversations and creativity was improved (hey 8 heads are better than 3 ).

Venue

Last year:

The event was at a hotel with 5 rooms that could accommodate between 75 and 200 per room. Two of the rooms were able to be combined to allow for 350 or so. The 2 main challenges we had were:

1. Moving between rooms was almost an impossibility due to 350+ people trying to navigate through the same 20’x20’ area at the same time

2. Screens in the largest 2 rooms weren’t large enough for entire room to see them easily.

This year

The event was at DeVry with 8 rooms that could accommodate between 30-75, and the common room. This solved the 2 problems from last year by allowing more space to move between rooms as well as each room was already equipped with a projector and whiteboard. Awesome. There were a couple more challenges that we had to overcome such as we didn’t have a space that could accommodate all the attendees at the same time. Plus due to some of the class sizes being smaller, some of the rooms had people sitting on the floor or standing along the walls. We tried to limit these challenges with better scheduling.

Schedule

Last year:

Last year we scheduled 4 rooms with eight 1 hour sessions each. Personally I loved because when I go to an event like this I go to seep all the learning I can out of it. However feedback we received was it was a little too hard core and people were just brain dead with a session and a half to go. Secondly last year we made the mistake of “assuming” time in between sessions. We scheduled sessions at an hour figuring presentations would last around 50 minutes which would allow 10 minutes to move between sessions. However due to Q&A, longer sessions and the problems moving between sessions mentioned above, this ended up being a huge oversight on our part. Lastly we had many speakers giving multiple sessions and tended to give MVP’s or other community leaders more speaking time.

This year:

This year we scheduled 8 rooms with five 1:15 session each. We also provided a 15 minute windows to move between rooms explicitly. This allowed for a much more relaxed feel throughout the day, people didn’t feel rushed and were able to have more conversations and connect with each other. I saw a lot more community interaction this year. Also in regarding to scheduling we had something around 50+ speakers submit over 140 sessions. However this year we decided to go back to the basic tenet of SQLSaturday:

We focus on local speakers, providing a good variety of topics, and making it all happen through the efforts of volunteers.

So we decided to only allow a speaker 1 timeslot and pick some people that aren’t as well-known as speakers. In fact we had at least 1 first time speaker Christina (blog | twitter).

Food

Last year:

Last year we wanted to do a breakfast, lunch and afternoon snack. However we were limited in finances as well as the venue not allowing us to bring in food. So we ended up going predictable and easy – we had the hotel do coffee in the morning, water through the day and a pizza buffet for lunch. Everyone loves pizza right? There were some time challenges in the buffet line as it just takes time to build up your plate.

This year:

With the venue allowing us to bring in outside food plus having a little more freedom in our finances this year we were able to do more. For breakfast Keith (blog | twitter) was gracious enough to order and pick up bagels, donuts and coffee. For lunch we consciously made the decision to not do pizza. We didn’t know what we wanted to do, but we wanted to do something else. Then Norm the idea of using Meatyballs (blog | twitter) a lunch truck in Chicago by Chef Foss. In addition to that Bob and Wendy were also able to bring in food from Aldi’s and Costco to supplement throughout the day.

Registration

Last year:

We had a single area with separate lines dependent on last name. Due to limit in financed we were unable to print out name badges and had attendees write in their own name tags.

This year:

Speed PASS = awesome. I’m not going to go into the nitty-gritty you can see that here. We had around half the attendees or so sign up for SpeedPass which significantly reduced time at the registration tables. The process is highly recommended. Rich, who was unable to actually attend the event, did all the programing and emailing of the Speed Pass process, please be sure to thank him if you liked it.

Room for Improvement

I felt we still missed on a couple things. Most notably in my opinion was the session and event evaluation process. This process needs to be easier, period. Also while the event allowed more time and space to travel between rooms, due floor plan on the building, some people were confused. Better directional signs as well as room signs identifying what sessions are in which room would also be an improvement.

Final Thoughts

Overall I felt the event was much better this year. In the end it was more volunteers, more sessions, more speakers, more time for discussions, in essence; more community. Thanks to the SQL Community for having another successful event.

Database Project with CLR Project Dependency

Since I started blogging again, I haven’t done any technical posts yet and I figured it’s about time.

I have been using Visual Studio Database Projects since DataDude beta’s came out in 2005.  A while ago, I was tasked with a database project that had a CLR dependency and working through the dependency.  Here’s how to have a database project that depends on a CLR project and works for Deployment. 

Let’s create a simple Database Project with just 1 table for Customers.  In the Customer table  we’ll store an email that will have a constraint for proper email format written in CLR.  We’ll also build the dependency between the projects and configure proper deployment.

So first we need to create the Database Project called CLRDependency:

ProjectName

And a simple Customers table:

CREATE TABLE [dbo].[Customers]
(
    pkCustomerID int NOT NULL IDENTITY(1,1),
    FirstName varchar(25) NULL,
    LastName varchar(25) NOT NULL,
    EmailAddress varchar(50) NOT NULL
);

Next let’s add a new CLR project called CLRFunctions:

CLRFunctions

When creating this, it will ask for a database to reference.  Since we haven’t created the database yet you can just click Cancel.  Next Create a UserDefinedFunction called ValidateEmailAddress.cs with the following code:

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Text.RegularExpressions;

public partial class UserDefinedFunctions
{
    [Microsoft.SqlServer.Server.SqlFunction]
    public static SqlBoolean ValidateEmailAddress(SqlString emailAddress)
    {

        return new SqlBoolean(Regex.IsMatch(emailAddress.Value, @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$"));
    }
};

In Solution Explorer, Right-click on References in the database project and click on Add Reference, then select the project :

ProjectReference Reference ProjectDependency

You’ll see CLRFunctions appear under References:

CLRDependency

Now you only have to build the CLRFunctions Project and the Assembly will appear in your Database Schema View:

Schema 

Now we need to create the UserDefinedFunction in the Database Project so Right-Click on Functions and Add a Scalar Function:

CREATE FUNCTION [dbo].[ValidateEmailAddress]
(
    @EmailAddress nvarchar(50)
)
RETURNS BIT
AS
    EXTERNAL NAME [CLRFunctions].[UserDefinedFunctions].[ValidateEmailAddress];

Lastly let’s create the Check Constraint:

 CheckConstraint

ALTER TABLE [dbo].[Customers]
    ADD CONSTRAINT [CK_ValidateEmailAddress]
    CHECK  ([dbo].[ValidateEmailAddress](EmailAddress) = 1);

So now we have the two projects working together and everything is great.  However if you build it, you’ll see this:

------ Build started: Project: CLRFunctions, Configuration: Debug Any CPU ------
  CLRFunctions -> C:\AMLProjs\Local\CLRDependency\CLRFunctions\bin\Debug\CLRFunctions.dll
------ Build started: Project: CLRDependency, Configuration: Debug Any CPU ------
  CLRDependency -> C:\AMLProjs\Local\CLRDependency\CLRDependency\sql\debug\CLRDependency.dbschema
------ Deploy started: Project: CLRFunctions, Configuration: Debug Any CPU ------
Error: Cannot deploy. There is no database connection specified. To correct this error, add a database connection using the project properties.
------ Deploy started: Project: CLRDependency, Configuration: Debug Any CPU ------
    Deployment script generated to:
C:\AMLProjs\Local\CLRDependency\CLRDependency\sql\debug\CLRDependency.sql 

    The deployment script was generated, but was not deployed. You can change the deploy action on the Deploy tab of the project properties.
========== Build: 2 succeeded or up-to-date, 0 failed, 0 skipped ==========
========== Deploy: 1 succeeded, 1 failed, 0 skipped ==========

That’s not good, we have a failure.  However this is easily solved.  Just uncheck the deployment option on the CLR Project in the solution properties:

DontDeployProperties

And now when you deploy you will see:

------ Build started: Project: CLRFunctions, Configuration: Debug Any CPU ------
  CLRFunctions -> C:\AMLProjs\Local\CLRDependency\CLRFunctions\bin\Debug\CLRFunctions.dll
------ Build started: Project: CLRDependency, Configuration: Debug Any CPU ------
    Loading project references...
    Loading project files...
    Building the project model and resolving object interdependencies...
    Validating the project model...
    Writing model to CLRDependency.dbschema...
  CLRDependency -> C:\AMLProjs\Local\CLRDependency\CLRDependency\sql\debug\CLRDependency.dbschema
------ Skipped Deploy: Project: CLRFunctions, Configuration: Debug Any CPU ------
Project not selected to build for this solution configuration
------ Deploy started: Project: CLRDependency, Configuration: Debug Any CPU ------
    Deployment script generated to:
C:\AMLProjs\Local\CLRDependency\CLRDependency\sql\debug\CLRDependency.sql

    Creating CLRDependency...
    Creating [CLRFunctions]...
    Creating [dbo].[Customers]...
    Creating [dbo].[ValidateEmailAddress]...
    Creating CK_ValidateEmailAddress...
    Checking existing data against newly created constraints
========== Build: 2 succeeded or up-to-date, 0 failed, 0 skipped ==========
========== Deploy: 1 succeeded, 0 failed, 1 skipped ==========

Something to remember is that you can actually deploy this to a server that does not have CLR Enabled, however when you go to insert anything into that table, it will fail with this error: 

Msg 6263, Level 16, State 1, Line 1
Execution of user code in the .NET Framework is disabled. Enable "clr enabled" configuration option.

So make sure you enable CLR on the Server.  Now onto testing (you do test your work right?)

USE CLRDependency;
GO
INSERT INTO dbo.Customers
    (FirstName, LastName, EmailAddress)
VALUES
    ('Aaron', 'Lowe', 'AaronL@AaronLowe.net');
GO
INSERT INTO dbo.Customers
    (FirstName, LastName, EmailAddress)
VALUES
    ('Aaron', 'Lowe', 'boo');
GO

Results as expected:

(1 row(s) affected)
Msg 547, Level 16, State 0, Line 1
The INSERT statement conflicted with the CHECK constraint "CK_ValidateEmailAddress". The conflict occurred in database "CLRDependency", table "dbo.Customers", column 'EmailAddress'.
The statement has been terminated.

A Slice of Humble Pie

Message to Seniors:

Math was always easy for me.  I took calculus in high school and enjoyed it very much.  However, during my post-graduate degree, I took an accounting class, which was very difficult for me to grasp.  The whole double-entry idea was foreign to me and I got frustrated.  Here is an example conversation from that course:

Me: “[Classmate Name], I don’t understand, can you help me with problem #2?”

[Classmate Name]: “Oh that problem was easy” or “You should be able to get that” or even “I can’t believe you didn’t get that one”

Again, we go back to good ol’ Nick Burns either talking down to colleagues for the purposes of making ourselves sound or feel better or having unrealistic expectations.

In reference to talking ourselves up, the answer to that is humbleness.  Be humble.  Even if you are the expert and know every potential option of a feature because you wrote it, be humble.  Arrogance is an immediate turn off and a path to working alone.  Not to mention there is always someone who knows more than you do (and they are probably younger). If you are having problems with that see Be Excellent to Each Other.

As far as unrealistic expectations go—there is nothing wrong with having high expectations, however I am not going to yell at my 4-year-old daughter for not being able to write this blog post for me.  It would be great if she was able to and I would dote on her.  That would increase her confidence and excitement to write again.  However, if she does not write it, then I am not going to tear her down for not being able to do something that is really outside of her current ability.  Of course that does not mean she will not get there one day, but I have to allow her time to grow and learn.

Message to Juniors:

Let’s be honest, one of the best things about the SQL Community is everyone’s willingness to help.  I do not see any other community with a specific twitter help hashtag, let alone training on cruises.  However, the other side of that is someone can fake a lot by getting all their answers from the community.  They can even be seen through social networking as knowing more than they really do. However if you sit down and talk with them, you will quickly start seeing how much they know or do not know.

This can be due to the “fake it till you make it” mentality or just pride.  Let me be clear here, there is nothing wrong with ambition or confidence.  However when it turns into pride, you are in trouble.   Pride means you have stopped learning because you know it all now.

If someone is helping or teaching and the response is often or always:

  • I did it that way this time, but I usually do it [insert best practice here].
  • I always just write it that way to start and clean it up later
  • Yeah I know that
  • I used to do that all the time, just haven’t done it in a while
  • I was trained on that but didn’t use it right away, so I lost it
  • I always create my own scripts from scratch
  • Yeah that is what I meant

If you catch yourself saying things like that often, then expect to lose your help soon.  They are willing to help and share their knowledge—soak it up, do not reject it.  The old adage is true, the more you learn, the more you realize you don’t know.  It is ok to say, “I don’t know”.  That is what leads to learning and even mentorship. 

Am I a senior or a junior?

The answer is unequivocally, both.  So if you only read one section, go read the other :) .  No one knows everything about everything.  So maybe you are a senior in SSIS, but a junior in SSRS.  Maybe you are an absolute expert in tuning queries but your IO turned to molasses and you are a junior on SANs.  In our industry we are always learning as there is a huge amount of depth and even larger amount of breadth, and, oh yeah, things are changing constantly.

Be honest if you don’t know something; give yourself and others the time they need to learn.  Pride goes before the fall and humbleness is a virtue.

Proverbs 16:18