navigate site menu

Start learning with our library of video tutorials taught by experts. Get started

SQL Server: Triggers, Stored Procedures, and Functions
Richard Downs

SQL Server: Triggers, Stored Procedures, and Functions

with Martin Guidry

 


This course investigates several key database-programming concepts: triggers, stored procedures, functions, and .NET CLR (Common Language Runtime) assemblies. Author Martin Guidry shows how to combine these techniques and create a high-quality database using Microsoft SQL Server 2012. The course also covers real-world uses of the INSERT, UPDATE, and DELETE procedures, and how to build a basic web form to connect to your database.
Topics include:
  • Comparing triggers, functions, and stored procedures
  • Installing and configuring SQL Server
  • Creating a stored procedure
  • Returning data using data sets
  • Creating user-defined functions
  • Using "after," "instead," and nested triggers
  • Modifying existing stored procedures
  • Implementing logging on DELETE
  • Choosing between T-SQL and CLR
  • Executing a stored procedure
  • Passing parameters

show more

author
Martin Guidry
subject
Developer, Databases
software
SQL Server
level
Advanced
duration
1h 52m
released
Sep 24, 2012

Share this course

Ready to join? get started


Keep up with news, tips, and latest courses.

submit Course details submit clicked more info

Please wait...

Search the closed captioning text for this course by entering the keyword you’d like to search, or browse the closed captioning text by selecting the chapter name below and choosing the video title you’d like to review.



Introduction
Welcome
00:04Hi! I'm Martin Guidry and welcome to SQL Server: Triggers, Stored Procedures, and Functions.
00:10I'll start by showing you how to create stored procedures using T-SQL or C# code.
00:16Then show you how to use SQL Server Management Studio to simplify
00:19database development.
00:21We'll see how to create triggers using SQL Server Management Studio and we'll
00:25take a look at the Common Language Runtime and how it enables us to create more
00:29powerful, faster performing stored procedures, and functions.
00:32We'll end with using Visual Studio to create a web application that utilizes the
00:37store procedures created earlier in the course.
00:40We'll be covering all these features plus best practices and techniques for
00:44avoiding common problems.
00:46Now let's get started with SQL Server: Triggers, Stored Procedures, and Functions.
Collapse this transcript
What you should know
00:00To get the most out of this course you should have a little
00:03background knowledge.
00:04Specifically, I expect you to know the basics of any version of Microsoft SQL Server.
00:09You will need to have some familiarity with SQL Server Management Studio and
00:14some knowledge of the T-SQL language.
00:17Things like UPDATE, INSERT, and DELETE statements.
00:19A great way to pick up this knowledge is SQL Server 2008 Essential Training with
00:25Simon Allardice here in the lynda.com online training library.
00:30Also, in the last two sections of the course we will be running some C# code.
00:35To get the most out of these sections you should be familiar with the basics of
00:39C# as well as the basics of Visual Studio.
00:43These topics are covered in C# Essential Training with Joe Marini also in the
00:48lynda.com online training library.
Collapse this transcript
Using the exercise files
00:00The exercise files for this course are organized into folders by chapter.
00:05Each chapter has an individual exercise file for the individual section.
00:10So for example Ch03 section 05 exercise file looks like this.
00:15This is stored in a text file even though it's actually SQL code.
00:19We will be copying and pasting this code into Management Studio and run into there.
00:25Don't do it just yet.
00:26I know you're anxious to get started, but go ahead and wait until we get to the
00:30individual section before you run in any of this code.
Collapse this transcript
1. Getting Started
Comparing triggers, functions, and procedures
00:00Before we get into creating triggers, functions, and stored procedures let's
00:05talk about the similarities and differences.
00:07First, the similarities.
00:09All of these are database objects containing code that will be executed as a single unit.
00:15These things are similar to what other development platforms might call a
00:18method, a subroutine, or a module.
00:21Some other platforms also use the term procedure and function, similar to the way
00:25SQL Server uses those words.
00:27In SQL Server, triggers, functions, and stored procedures are typically
00:31written in a T-SQL, but they can also be implemented in any of the .NET
00:35languages like C# or VB.NET.
00:39Now let's talk a little bit about the differences.
00:41Triggers and stored procedures are allowed to change data and commonly do change
00:46data, whereas a function is not allowed to change any data.
00:49The point of a function is always to return data.
00:54Sometimes it returns a single scalar value, sometimes it returns a table.
00:58Triggers never return data.
01:00A trigger has to accomplish all of its work by changing data and tables and
01:05there is no return value from a trigger.
01:08Stored procedures are somewhere in-between.
01:10Typically, the point of a stored procedure is to change data in the underlying
01:14tables, but it is allowed to return a value if it wants to.
01:17It commonly returns a 0 or 1 to indicate success or failure.
01:22Probably, the biggest difference between the three is how they are called.
01:26The easiest to work with is a stored procedure.
01:30For a stored procedure, we just simply execute it directly from code using the
01:35phrase EXEC or the full word EXECUTE and then the name of the stored procedure.
01:41This will cause a stored procedure to run at that time.
01:44We cannot use this technique with the other ones.
01:47So a function has to be part of a SELECT statement.
01:51So we see here we have a typical SELECT statement, calling first name and last
01:57name, but if I wrote a function that combined that into full name, I could just
02:02use that in line with the SELECT statement.
02:05I can use a function in the column list of a SELECT statement.
02:10I can also use it in the WHERE clause.
02:12I could also use it in the ORDER BY clause of a single SELECT statement.
02:20These are all functions that return scalar values.
02:23It's also possible for a function to return an entire table and that will
02:27replace the table name here.
02:29We are not limited to just SELECT statements.
02:34we can also do the same thing with UPDATE, INSERT, and DELETE statements.
02:41So something like this where we're using the function to filter a DELETE statement.
02:47Calling triggers is yet again a third technique.
02:50There is no way for me to issue a command that causes a trigger and just a trigger to run.
02:56A trigger always runs as a reaction to something.
02:59So I do something else on my machine, the machine performs that action, and then
03:03afterwards runs the trigger.
03:06Most commonly, triggers react to UPDATE, INSERT, or DELETE statements.
03:10So if I have a trigger set up on a table and I run an insert statement on that
03:15table, immediately after that insert the trigger will take over and execute its code.
03:21There is no way to just type in and save run this trigger now.
Collapse this transcript
Why use a stored procedure?
00:00Now I'd like to talk about some of the advantages of using stored procedures.
00:04One of the primary advantages is to simplify the administration and maintenance
00:09for common routines.
00:11On a large database project we could have dozens of developers writing code to
00:15read and manipulate data in the same table.
00:18If each developer independently writes a simple INSERT statement for the table,
00:22there is a large chance someone will make an error.
00:25Also, if that table ever changes, every single developer has to go back
00:30and change their code.
00:31However, if we wrote one insert stored procedure and allowed all the developers
00:36to use that stored procedure, we gain some advantages.
00:39First, we reduce the chances of error.
00:42We also reduce the level of effort when a change is required.
00:45We can simply change the stored procedure.
00:48As long as the name of the stored procedure and the input parameters of
00:51the stored procedure stay the same, the developers will likely have no
00:54need to change their code.
00:56Another advantage is, with stored procedures, our code is stored with the data.
01:02I typically have common task I regularly perform on a database.
01:05Rather than type in that code everytime I want to run it, I prefer to type it in
01:10once and save it for the next time.
01:12Certainly, I could create a code folder on my desktop and store all the scripts there.
01:17But I prefer to create a stored procedure.
01:20That way the code is stored in the database.
01:22Which reduces the chances the code will ever be misplaced, and it also
01:26provides the advantage of every time the database is backed up, all of my code is backed up.
01:31Stored procedures can improve our security and simplify the administration of security.
01:37Using stored procedures we can easily provide different levels of access
01:41to different users.
01:43I often prevent any user from directly accessing any table.
01:47The only way they can read or modify the data is to utilize my stored procedure.
01:52This technique makes it very simple to prevent certain actions.
01:55For example, if I don't want a certain user to delete any data from a particular
02:00table, I can just deny them access to the delete stored procedure, or if I don't
02:06want anyone deleting data, I'd just never implement a delete stored procedure.
02:11They won't have access to the underlying table.
02:14They won't be able to go there directly.
02:16And saving the best for last, the most important advantage of using a stored
02:20procedure is a performance improvement.
02:23To understand this performance improvement we'll have to talk a little bit about
02:27what happens every time you run code in SQL Server.
02:31If I just type in a query, when I go to run it, the machine performs several
02:36steps before it runs the query.
02:39First, the information is parsed.
02:42Parsing means checking to make sure my syntax is good.
02:45I haven't misspelled a keyword or used a keyword that's invalid.
02:50Next, my code is algebrized and that means it changes object names to
02:56a consistent format.
02:57So for example, the categories table could be referenced just as categories
03:03or it could be referenced as dbo.categories, or we can even put the name of
03:08the database first.
03:10So with all of these different options on how to name things, the machine has to
03:14standardize all of the names in a consistent format before it can run it.
03:19The third step is optimizing and optimizing the database decides which
03:24data structures to use.
03:26It will have to enumerate a list of all the tables to be read.
03:29It will decide which order it reads the tables in.
03:32It will look for indexes that could help in other optimization strategies.
03:37After the machine performs these three steps:
03:40parse, algebrize, and optimize, it results in an execution plan and it
03:45immediately executes that execution plan.
03:49If I were to run this exact query again, it starts over from the top.
03:54It will parse it, it will algebrized it, it will optimize it, it will come up
03:58with an execution plan, and it will execute the execution plan.
04:02That is somewhat displeasing to me that it executed all those steps again.
04:07Apparently, someone at Microsoft had same feelings as me and stored procedures
04:11bypass some of this.
04:13So the very first time I run a stored procedure, it does go through all those steps.
04:17But when it creates the execution plan, it also saves the execution plan at that time.
04:23So the next time I run the stored procedure it can skip the parsing, it can skip
04:28algebrizing, it can skip the optimizing.
04:31It goes directly to the saved execution plan and just executes that immediately.
04:36This can result in a significant performance improvement, typically in the
04:40optimizing stage is where we see the most improvement.
04:43If you have a large database with lots of indexes rather than the machine
04:47having to make a decision on which index to use every time, all of that can be
04:53saved in the execution plan, and we can see a significant performance increase
04:57from a stored procedure.
Collapse this transcript
Why use functions?
00:00Now let's talk about some of the advantages of using functions.
00:04Functions have most of the same benefits of stored procedures.
00:07They can simplify administration and maintenance of common routines.
00:11The code is stored with the data.
00:13They do have some of the same security options as stored procedures, but people
00:18don't use these quite as commonly as they do with stored procedures.
00:21And we also have all of the performance improvements of the stored execution plan.
00:27Additionally, functions have some other benefits.
00:31In line functions can be very easy and intuitive.
00:35A developer who is familiar with select statements can quickly adapt to a select
00:40statement written with functions rather than with typical database objects.
00:44It's just not that big of a jump to go from a mindset of not using functions
00:49to a mindset of using functions, because the code is still structured so similarly.
00:54Functions can also be a quick way to abstract some complex ideas.
00:58So something like formatting an address.
01:01Well, if you have customers from dozens of different countries that all need
01:05their address formatted different ways,
01:08we don't want our developers to spend lots and lots of time writing that code
01:12every time they need an address.
01:14Creating a function that formats the addresses properly for whatever country can
01:20allow the developer to move past that complexity and just focus on other tasks.
Collapse this transcript
Why use triggers?
00:00Let's talk little bit about some of the advantages of using triggers.
00:04Triggers can be used to audit changes to the database.
00:08We can set up triggers on tables to record every change to every record in the table.
00:13Typically, this is accomplished by copying the record before it's modified to a different table.
00:18A table we might call historical data.
00:21Triggers can also be used to ensure the integrity of our data.
00:25SQL Server has some other ways to do this such as checks and constraints.
00:30But those are designed to be pretty simple.
00:32They check for a data type or they might check to make sure some value is
00:36greater than or less than some other value.
00:40Triggers allow for more robust logic.
00:42We can generate data integrity rules that implement complex business logic,
00:47that can reference multiple tables based on the value in those tables, decide if
00:52a certain piece of data is valid or invalid.
00:56Triggers can also be used to block mistakes.
00:58Triggers can undo an attempt to change data.
01:01They can even undo an attempt to change the structure of the database.
01:06So something like dropping a table can be blocked by a trigger.
Collapse this transcript
2. Installing SQL Server
Configuring your environment
00:00Before I get into my demonstrations, I'd like to help you set up a
00:04development environment very similar to what I'm using so you can perform
00:08these steps at home.
00:09We are going to be using two products:
00:12Microsoft SQL Server 2012 Express Edition and Microsoft Visual Web Developer
00:182010 Express Edition.
00:21First let's look at SQL Server 2012 Express Edition.
00:26You can find that add the URL www.microsoft.com/express/database.
00:35This takes me to the standard landing page for SQL Server Express Edition.
00:40I have a big red button in the middle of the screen.
00:43I'll click on that and it shows me some different choices.
00:47You definitely want to get one of the versions that has the database engine and
00:52the tools include Sequels Server Management Studio which is an important tool
00:56in many of our demos.
00:58So I'm going to with the top one here.
01:02That takes me to another page where I'll select the 64-bit edition Express with Tools.
01:13Now that we've downloaded SQL Server 2012 Express Edition let's go ahead and install it.
01:19So in this interface I want the top option New SQL Server stand-alone
01:23installation, and I'd like to perform a new installation of SQL Server 2012, so
01:30the default there is appropriate. I'll click Next.
01:34I need to read and accept the license and then click Next.
01:40I need to choose what features I'm going to install.
01:44I definitely want the Management Tools.
01:47The SQL Server Replication is not necessary for anything we're going to do in
01:51the course, but you could install if you want though. Click Next.
01:58At this point I'd like to name this instance.
02:01You can use whatever name you want, probably do something descriptive.
02:05I can choose a folder to install to.
02:07I'm going to accept the default and click Next.
02:14Here it's asking me which service accounts I would like to use.
02:17In a tested environment I typically accept the defaults here.
02:21If you'd like to use something other than the default accounts, you may do so.
02:28This interface is asking me which authentication mode I would prefer.
02:32One of our demos will require SQL Server authentication.
02:35So I'm going to click Mixed Mode to allow SQL Server authentication.
02:40That will force me to import a password for the SA account.
02:45So I'm going to of when to use a secure password.
02:47It also has automatically added the current user as an administrator of SQL Server.
02:53That's typically something you'll want to do.
02:55If you want to add additional users, you can do so in the interface at the bottom.
03:01Asking me whether or not I want to send error reports to Microsoft, I'll just
03:05click Next and now we are installing.
03:09I should mention we are installing SQL Server version 2012.
03:14Many of the demos I'll be doing would work exactly the same in 2008 or 2005.
03:21So if we have that kind of environment already set up, you could stick with that.
03:25I also anticipate that the majority of the stuff in the course will not change
03:29in a future version.
03:31So when Microsoft releases the next version of SQL Server, I can't be 100% sure
03:37but I imagine the basics of triggers, functions, and stored procedures will
03:41still work the same.
03:43In this sense your SQL Server 2012 installation completed successfully
03:46with product updates.
03:48Sounds like good news.
03:50I'll close this and then I can also close this window and we have successfully
03:55installed SQL Server.
03:57Now it's time to install Microsoft Visual Studio Web Developer 2010 Express.
04:03You can get this from www.microsoft.com/express.
04:10This takes me to a landing page for Visual Studio 2010 Express products.
04:14There are a few different versions. I'll scroll down.
04:17The one I'm interested in is all the way here to the right, Visual Web
04:22Developer 2010 Express.
04:30I'll click Install at the bottom and I'll need to accept the licensing
04:35agreement, and here we have a message saying the following products were
04:39successfully installed.
04:40That sounds like good news.
04:42I'll click on Finish and I'll click in Exit and we have successfully installed
04:48Microsoft Visual Web Developer 2010 Express Edition.
Collapse this transcript
Downloading and installing a sample database
00:00Now that we've installed SQL Server let's go ahead and set up a test database
00:04to run some demos on.
00:06I've already staged some code for you in your Exercise Files folder.
00:11The one says create_database, just copy and paste all of that into Management Studio.
00:18You notice near the top it's going to try to create some files in C:\program
00:23files\Microsoft SQL Server, et cetera, et cetera.
00:27This is the default path for database and log files.
00:31You're welcome to use a different path if you want to.
00:33What I have on the screen here just represents the default.
00:36So we'll go ahead and run that.
00:38Command completed successfully.
00:41And that gives us a new database called myDatabase.
00:44We do need to add one table to that database and populate it with just a
00:49little bit of data.
00:50We have script for that also.
00:53So again I'll copy and paste that over, and execute, and we see now we have an
01:00Authors table and we should have of a few records in that Authors table. It looks good.
01:07I think we're ready to go.
Collapse this transcript
3. Stored Procedures
Creating a stored procedure
00:00I'd like to talk to you little bit about creating stored procedures in
00:04Microsoft SQL Server.
00:05To do this we're going to start of with the keyword CREATE and then the keyword PROCEDURE.
00:11After that we need to give it a name.
00:13Well, we have lots of options on naming.
00:15Almost any combination of letters and numbers and punctuation marks will work.
00:19One of the few exceptions is you are not allowed to start with a numeral.
00:23So if I try to type in numerals at the beginning, the machine will get upset
00:27with that and put that little red squiggly line in there.
00:30That is because you're not allowed to start with numerals.
00:33You are allowed to end with numerals or have numerals anywhere else in the name.
00:38But just as a matter of preference I typically avoid both punctuation marks and
00:42numerals and go with just text.
00:44Once we've decided on a name we will need the keyword AS and the keyword BEGIN.
00:50I typically put those on separate lines, but that's not necessary.
00:53You could put all of this on one line.
00:55I just find it makes it a little easier to read spaced out like this.
00:59After BEGIN, we have to actually do the work of the stored procedure and just
01:03about any T-SQL statement is valid.
01:06We're going to start off easy and just do a very simple one line that
01:10will return some text.
01:12Then in single quotes the word hello.
01:15At the end of the stored procedure we need to type in the keyword END and
01:20that signifies to the machine this is the end of our stored procedure.
01:23We will then click on the red exclamation point for Execute and we get at the
01:28bottom a green check mark that says Query executed successfully, and the phrase
01:34command completed successfully.
01:36So it would certainly seem as we were successful.
01:38We've got two forms of positive feedback.
01:40The stored procedure is now stored in our database.
01:43We can see that by expanding the myDatabase menu to the left.
01:47Then we expand Programmability.
01:50Inside of there we will have Stored Procedures.
01:52It's not coming up yet.
01:53I bet if I click Refresh, there it is, a stored procedure called myTest.
02:00So there we can see the stored procedure exists.
02:03The next logical thing to do would be to execute the stored procedure, and in
02:07order to execute you can just type in the keyword EXECUTE and then the name of
02:13the stored procedure, click the red exclamation point again and we see our
02:17data returned to us.
02:18We ask the stored procedure to return the word hello.
02:22It did in fact return the word hello.
02:24So it seems as if things are going well for us.
02:27The keyword execute can be abbreviated.
02:29You can type in just EXEC and it will accomplish the exact same thing.
02:35So that's an alternative way to execute our stored procedure.
02:38So these are the basics of creating a stored procedure.
02:41In the next section we will work on modifying a stored procedure.
Collapse this transcript
Modifying a stored procedure
00:00Now that we've created a stored procedure, it's likely I would want to change it at some point.
00:06The easiest way to modify a stored procedure is to come back to our favorite menu,
00:09the Programmability menu, open that up, locate the stored procedure we would
00:14like to change, right-click on it, and one of the options in the right-click
00:18menu will be Modify.
00:20When I click on Modify, it throws some code up on the screen.
00:23Notice that lines 8 through 12 here are extremely similar to what I wrote.
00:30The only difference is rather than have the keyword CREATE, it has changed it to
00:35the keyword ALTER, which makes a lot of sense.
00:37We are not trying to create a new stored procedure anymore, we are trying to
00:41modify a stored procedure, and in the SQL world, we use the word alter for when
00:47we want to change things.
00:48So I could make a small change to my stored procedure, and click on the red
00:53exclamation point again.
00:55And it will say that it completed my command successfully, which means the
00:59stored procedure has been modified.
01:01In order to see this, I will need to execute it again.
01:06So we will again do EXEC and the name of the stored procedure, and we see it is
01:11now giving the new text; the text from the modified stored procedure which
01:16reassures me we have successfully modified the stored procedure.
01:20I could go back to the other window and change it again,
01:24Execute and come back to my window where I'm executing the stored procedure and
01:29we see change again.
01:31When you're working with stored procedures, it's likely that you will be
01:35modifying them often, and it would be preferable to not have to bounce back and
01:39forth between one window and the other.
01:42I don't want to have to go to one window to change my stored procedure, and a
01:46different window to execute the stored procedure.
01:49We can do that all from one window.
01:51I'll take this code here and a little copy and paste to my other window.
01:56And the only thing I need to do is in between them add the keyword GO so that
02:02the machine knows these are two separate chunks of code.
02:05Everything above the GO is used to modify the stored procedure and then
02:09everything after GO is used to execute the stored procedure.
02:13When I click Execute, it will run both and so I can modify the stored procedure,
02:20and we see the modifications of that immediately.
02:23So during development, this is typically the way that I like to work.
02:27It's the quickest and easiest way to modify stored procedure, and immediately
02:31see the results of those modifications.
Collapse this transcript
Returning data using data sets
00:00Now I'd like to talk about returning data through stored procedures,
00:04specifically returning data as datasets primarily.
00:08We'll also talk a little bit about a return value.
00:10I have some code on the screen here that is available in our exercise files.
00:15This is very similar to what we were doing in the previous section.
00:18It's code that allows us to modify a stored procedure and execute that stored procedure.
00:23I'm going to modify the stored procedure to have a return value.
00:27So at the end, the very last thing before the end statement, I will simply issue
00:32the keyword Return, and give it a numeral.
00:35So in this case, Return 1.
00:37When we execute that, we will likely not see that one returned just yet, we have
00:42to go through a little more effort to actually see what is returned.
00:47We will declare a variable to hold that value.
00:52We will then execute the stored procedure, and take what is returned, and store
00:58it in our newly created variable, and then we'll need one last line of code to
01:03display that returned value.
01:07Go ahead and execute all of that, and so we see we got two results in the
01:12Results pane at the bottom;
01:13one says, Hello World, this is fun which is the data returned from the
01:17stored procedure, and then also the numeral that we returned, and in this
01:21case, we returned 1.
01:22We could change that easily to return a different numeral and now it returns 12.
01:28Microsoft recommends as a best practice every stored procedure should return a
01:33value. Typically you return either 0 or 1 for success or failure.
01:37So if the stored procedure failed for some reason, you would return a 0, if it
01:43was successful, you would return 1.
01:45Different people like to have a little different naming conventions for that.
01:48For example, if the stored procedure returned an error, you could return a code
01:52that signifies an error in your mind, maybe something like -1.
01:55But the bottom line is Microsoft recommends, and I also agree with this
02:00recommendation, the last line of every stored procedure should be returned a
02:04numeral to me, and that numeral should have some meaning.
02:07Beyond returning numerals, you probably want your stored procedure to return some data.
02:12And we've been doing that;
02:13we have Select, and then we're returning some text. We can return multiple
02:18datasets by having multiple SELECT statements.
02:23So I'll have a second SELECT statement that will return a second set of data.
02:28Now at the bottom, we see that we return three different things;
02:32the first data set, below that the second dataset, and then finally the return value.
02:38You could additionally add a third dataset, a fourth dataset, a fifth dataset.
02:42The machine does not put an upper limit on what we can and cannot return.
02:46Good common sense says, you probably want to limit what one stored procedure
02:51returns, but two or three datasets is not uncommon.
02:55Notice I said that the return -1 or return whatever numeral you have should be
03:00the last line of the stored procedure.
03:02Let's see what happens if you violate that recommendation, and we put that in
03:07the middle right here.
03:09You notice it returned the first dataset, "Hello World this is fun."
03:12It returned the -1, it did not return the phrase "This is more text."
03:17The machine stops returning after the line with the keyword RETURN.
03:21It will perform the return on that line.
03:24It will not do any returns after that.
03:27So the keyword RETURN almost always needs to be the very last thing in
03:32your stored procedure.
03:33So in this demonstration, we've seen returning data from a stored procedure as
03:38either a numeral or a dataset.
03:40In our next video, we'll talk about returning data as a cursor.
Collapse this transcript
Returning data using cursors
00:00Next, I'd like to talk about returning data from a stored procedure using a cursor.
00:05A cursor is a data structure that contains multiple rows of data, and it allows
00:10us to cycle through each row one at a time and perform an action on each row.
00:16Returning a cursor from a stored procedure is pretty similar to returning data
00:20from a stored procedure using output parameters.
00:22And in a lot of ways you can think of a cursor as a special type of output parameter.
00:27I have some code on the screen.
00:29This code is available in your exercise files.
00:32The top-half of this code is going to create a stored procedure called procedure
00:36cursor that accepts one parameter that's called Authors, and that parameter has
00:41a data type that is defined by two words;
00:44one word is CURSOR and the second word is VARYING.
00:49Meaning, this cursor isn't always going to be exactly the same.
00:52It could be a different size based on the data that's currently in the database.
00:58This cursor will sometimes return a different number of records than other times.
01:02And then the last word is OUTPUT. That's the same as we've had before because
01:06this cursor will be used as an output parameter.
01:09We still need the keyword OUTPUT.
01:11In the body of the stored procedure on line 4, we set the author's cursor equal
01:16to a cursor, and then we put a SELECT statement.
01:19So line 6, 7, and 8, I wrote a SELECT statement that's just going to select the
01:23first name from the author's table. Just keeping it simple right now.
01:27Line 10 is very important where we open the author's cursor.
01:32Notice in this stored procedure we never close the author's cursor. We will close it;
01:37we're just going to close it outside of the stored procedure.
01:40So in the stored procedure, we only open it.
01:43On line 13, we have the keyword GO, and I'm going to scroll down so we can see
01:48what happens after this.
01:49This is all the code to execute the stored procedure, and get back that cursor.
01:53So the top two lines are declaring variables, then line 18 executes the stored
01:59procedure, and takes the output and puts it into my cursor.
02:04Line 20 and 21, cycle through the first record in my cursor, and then very
02:08important, 23 and 24 close the cursor, and de-allocate the cursor.
02:14Close the cursor means it cannot be used anymore, de-allocate means it is
02:19removed from memory.
02:20It's important to do these things because the machine will not do them for you automatically.
02:24If you do not specifically say de- allocate the cursor, it will remain in memory
02:29for quite a long time;
02:31probably will remain there until you reboot your SQL server.
02:34So for the sake of efficiency, you always want to de-allocate.
02:38Let's go ahead and run this, and we see the stored procedure is created and
02:43it returns one record;
02:45the first name of the first author in the table.
02:48We could if we wanted to modify this code at the bottom to do another fetch
02:53to get the next record, and another fetch to get the next record, so on, and so forth.
02:58Or most likely, you would put it in a loop to walk through all of the items in the cursor.
03:04Some developers are very much against cursors.
03:07Cursors can take up a lot of memory space, obviously the amount of memory they
03:11use is always proportional to the size of the table.
03:15So if you're working with a small amount of data, cursors are a good idea.
03:19If you're working with a very large table, you might want to look at an alternative.
03:24As mentioned earlier, there are particular performance problems if you do not
03:29remove the cursor from memory.
03:31So again, the DEALLOCATE statement is important and the DEALLOCATE statement has
03:35to come after the CLOSE statement.
03:38So when working with cursors, remember, keep it small and always destroy
03:43what you create.
Collapse this transcript
Using input and output parameters
00:00Now I'd like to talk about sending input parameters and returning output
00:05parameters from a stored procedure.
00:07These are optional.
00:08We have worked with stored procedures thus far without working with parameters,
00:12so they are optional.
00:13I have some code on the screen.
00:15It's available in our exercise files.
00:17It basically alters the stored procedure and then executes the stored procedure.
00:22So I am going to alter the stored procedure to include a 1 input parameter for now.
00:28I do that by creating some parentheses.
00:30We will need to put all of our parameters in parentheses.
00:33Then I need to give the parameter a name.
00:36And remember, in SQL Server, variable names always start with the at sign, and
00:42beyond that, you can name it almost anything you would like to name it.
00:45We will also need to declare what datatype we're going to use.
00:49Any of the typical SQL Server datatypes are in play, so for example, integer,
00:54varchar, datetime, all of those are perfectly valid.
00:57So I will declare this one as an integer.
01:00So we're going to alter this procedure to now accept one parameter.
01:04That parameter is called @param1.
01:07We can reference that parameter throughout our code, and I will also alter our
01:12stored procedure to select parameter 1.
01:16So rather than select some arbitrary text, it's going to select that parameter
01:21that we passed to it.
01:22The code on top is now ready to go.
01:24It will successfully alter the stored procedure.
01:26The code on the bottom will need to be modified to pass it a parameter.
01:30The stored procedure is now expecting a parameter.
01:33So we had better pass it a parameter and that parameter had better be an integer.
01:37So I will just pass it the integer 12. We'll run that.
01:41And it behaves as expected.
01:44Our code passed the parameter 12 to the stored procedure, and that exact
01:48value was returned to us.
01:50No surprises there. We'll call this a success.
01:52A few little notes on the syntax, when you are passing the parameter, you should
01:57not use parentheses.
01:59Although your instincts may tell you to use parentheses, you will in fact get an
02:03error if you use the parentheses.
02:04So no parentheses when passing parameters.
02:08And also like I mentioned, it has to in fact be an integer.
02:10If I try to pass it some text, the machine will also get upset about that.
02:16It says error converting from varchar to integer and that is expected.
02:21So that's the basics of an input parameter.
02:23We could do multiple input parameters.
02:26I will come back up here to my parameter list, and put a single comma, and then
02:31I can list a second parameter.
02:33And again, it will need a datatype, and again, I will have to come down here,
02:37and make sure I am passing a second parameter to it, and that runs successfully.
02:44We haven't actually done anything with the second parameter, so this becomes
02:47mildly more interesting, if we go ahead and display both parameter 1 and parameter 2.
02:53So no surprises there.
02:55We passed it the value 12 and Hello.
02:57It returned the value 12 and Hello. This is good.
03:00So now we've successfully worked with input parameters and we want to talk a
03:05little bit about output parameters.
03:07So we want to take this value that's being passed to it.
03:10Parameter 1 has a value of 12 and we're going to modify that value and then read
03:16the value as it comes out.
03:18In order to do this, I will need to change a little bit of the code around
03:21the execute statement.
03:22Rather than just pass it the value 12, I want to pass it a variable.
03:26I will declare a new variable, just call it X, and we'll have to say that it is
03:32an integer, and I will go ahead and give it the value.
03:35We will then pass that variable to the stored procedure, and then we will read
03:41the value of that variable.
03:43And if all goes well, once we're done with this, it will be changing the
03:47value of that variable.
03:48We haven't written the code for that just yet.
03:50But we can see it successfully passes the value of 13, and then reads the value
03:55of 13, as we are now, it is expected.
04:00So let's go ahead and try to change the value of the parameter.
04:03And here, we can say SET @param1 equal to some value other than 13;
04:09I will just choose a random number, 27.
04:11So what's going on here is lines 11, 12, and 13, should pass the value 13 to
04:18the stored procedure, the stored procedure should change that to 27, and then
04:22we can read that value.
04:24This is not going to work just yet though.
04:27There is one more step that is a little counterintuitive to some people.
04:30We have to actually declare the parameter to be an output parameter.
04:35SQL Server assumes all parameters are input only.
04:39So if you would like them to be output, you have to specifically use the
04:43keyword OUTPUT in line 1 where we declare the stored procedure, we have to
04:48specifically say OUTPUT.
04:50And then again, on line 12 where we are passing the parameter, we also have to
04:57say specifically OUTPUT.
04:59Now we should be able to successfully return the value 27.
05:03That is in fact what's happening. We've had success.
05:06So again, parameters are assumed to be input values.
05:11If you would like them to be both input and output, you have to use the keyword
05:15OUTPUT, and you have to use that keyword twice.
05:17We have to use output once when you declare the stored procedure, and once where
05:21we execute the stored procedure.
Collapse this transcript
Using security and permissions
00:00One of the main advantages of stored procedures is how they allow us to have
00:04more control over the security of the database.
00:07We will be working with a hypothetical user in this exercise called John.
00:11There is a script in your exercise files for creating the John user.
00:15Consider the scenario where we want to give John read only access to a
00:18particular table, and maybe not even the entire table. Maybe just one or two
00:22columns in the table.
00:24You could manually go in and set all these permissions on the table of our
00:28each individual column.
00:29You could either grant or deny permission.
00:32But it might be a lot of work to do that for a whole bunch of users.
00:36So we can hopefully lower our administrative effort by using a different
00:39technique to accomplish the same thing.
00:41I have on the screen a basic stored procedure. Again, you can find this in
00:45your exercise files.
00:46This stored procedure is called securityTest.
00:49It will form a SELECT statement.
00:51I'm going to select two columns from the authors table, fairly simple.
00:55When we Execute this, we get the results we expected.
00:58Nothing too exciting just yet.
01:00We get FirstName and LastName from every row in the table.
01:05Now let's talk about John.
01:06So let's go and give John permission to run this stored procedure.
01:10We will right-click on it and at the bottom we have Properties, over here we can
01:15go to Permissions, we will be setting permissions for John and we'll go into it
01:21and allow him to Execute and that's it.
01:23I don't want him doing anything other than executing the stored procedure.
01:26So I'll Logout and then log back in, as John.
01:35And he can get into the myDatabase.
01:37You can see one of the stored procedures.
01:40Now remember our database has three stored procedures. John can only see one of them,
01:45the one we gave him permission to, and he should be able to execute that stored procedure.
01:51And yes, in fact he can, and he gets the exact same results as any other user.
01:56John can not see the table.
01:58He doesn't see the underlying table.
02:00So he has no way of knowing there were other columns in this table.
02:04Some of these other columns in the table are in fact storing things like
02:08Address and Phone Number, which could be confidential information.
02:11Using this technique, we've completely masked not only the contents of
02:16those columns from John,
02:17we've also masked even the fact that those columns exist.
02:21So we are in a situation like this where we want a stored procedure to
02:26allow access to a table where the user does not have permission to that underlying table,
02:32in order for it to work, the stored procedure in the table, we need to have the
02:36same owner, and in fact, our stored procedure is owned by dbo.
02:40And the table is also owned by dbo.
02:44If either of them was owned by someone else this would not work.
02:47So let's go ahead and demo that.
02:49I'm going to logout as John.
02:53Log back in as someone who has the necessary permissions to change this stuff.
02:59So our authors table is currently owned by dbo.
03:03Let's go ahead and change that.
03:05So we're going to use this stored procedure designed for changing ownership.
03:10And it's called SP_changeObjectOwner and the thing we want to change, the
03:17owner of is dbo.Authors and we will want to change the owner to Martin, and it
03:25looks like it worked.
03:26Click Refresh right here, yes.
03:29We'll also need to make one change to the stored procedure.
03:32The stored procedure is looking for dbo.Authors, which no longer exists.
03:37So we'll change that to Martin.Authors.
03:41Then now, I'd like to test to make sure this stored procedure still works for
03:44Martin, because Martin should still have enough permission for this to run.
03:47So Execute dbo.securityTest.
03:53And that still runs for Martin.
03:55I'm anticipating this will not work properly for John.
03:58Let's go ahead and test that.
03:59I'm going to logout as Martin, log back in as John.
04:05John can still see the stored procedure,
04:06but when he tries to execute the stored procedure, it gives the error:
04:12The SELECT permission was denied on the object "Authors".
04:16So now, because the stored procedure and the authors table have different
04:20owners, the permissions are not passed back and forth the same way.
04:24And John is no longer able to query that from the stored procedure, even though
04:29he has permission to the stored procedure.
04:31In this case, he would also need permission to the underlying table.
04:34So the hypothetical, we were working through, we first stored this, now we
04:40want to allow access to John, will only work if both items are owned by the same owner.
04:45So now let's do a little housekeeping to clean up some of the changes we made here.
04:49First of all, I'm going to logout as John, because the remainder of the work I
04:53want to do as a different user.
04:54I'll log back in as myself.
04:59And we should see the authors table is still owned by Martin.
05:03I'll prefer to put it back to be and owned by dbo.
05:06And if you want your environment to match mine, go ahead and execute the code
05:09that's on the screen and make sure it's Martin.Authors.
05:15And when we refresh, yes;
05:17we should see that is now owned again by dbo and it will remain that way for the
05:21remainder of our course.
Collapse this transcript
Using transactions
00:00Database developers can and should use transactions, to provide a logical
00:05grouping of actions.
00:06Transactions can happen inside of a stored procedure or outside of the stored procedure.
00:10I typically do most of my transactions inside of stored procedures.
00:15And we'll talk a few reasons about why.
00:16I have on the screen some code you can get from the exercise files.
00:21It's a basic stored procedure, that's going to either delete or deactivate an author.
00:25There's one UPDATE statement that runs on line 6, 7 and 8.
00:30That's going to set the particular author's active status to 0, meaning he is inactive.
00:36And then lines 10, 11 and 12, set his phone number equal to Null.
00:40So this is a hypothetical where we want to stop tracking personal information
00:45about people that are no longer active.
00:48Lines 14 to 17, allow us to potentially roll- back the transaction if there's a problem.
00:55So this will help us avoid the situation, where we might end up with an author
01:00who we couldn't mark as inactive.
01:02We don't want to still remove his phone number.
01:05So fairly straightforward, I'm going to scroll down some more.
01:07So we can see at the bottom where we're actually going to execute this stored
01:11procedure on John Doe.
01:14So we execute this and it does in fact mark John Doe as inactive.
01:19And set his phone number equal to null.
01:22This is certainly not the only way to do this.
01:24We could have created one store procedure that does the UPDATE statement on
01:29line 6, 7 and 8 and a different store procedure that does the UPDATE statement on 10, 11 and 12.
01:36And then run those to stored procedures as part of the same transaction.
01:40From a developer point of view, I would rather do it the way it's on the screen
01:44here, where the structure of my code also reflects some business logic.
01:48Now these are two things that I've always want to be run together in the same transaction.
01:53And this type of mindset can often help us decide what to put into a single
01:57stored procedure versus when to create a new stored procedure.
02:01So anytime you are inside of a stored procedure, creating a second transaction,
02:06you should stop and think, hey, maybe that information, maybe that code, maybe
02:10that function should be moved to a different store procedure.
02:13So if you have two transactions or three transactions inside of the same stored
02:17procedure, you need to think about maybe that should actually be broken out in
02:21to separate stored procedures.
02:22Conversely, if we have two stored procedures that we pretty much always run
02:26together and they always run as part of the same transaction, you need to stop
02:31and think about maybe we could combine those two stored procedures into one
02:34stored procedure, and in there put the business logic about the transactions.
02:39Meaning, we really have to think about the logic once but get it done in the
02:43store procedure right and never have to worry about it again.
Collapse this transcript
4. User-Defined Functions
Creating a user-defined function
00:00Now I'd like to talk a little bit about functions, sometimes called user-defined
00:05functions in SQL Server 2012.
00:08I'm going to start off with creating a new function.
00:11So very similar to creating a stored procedure.
00:14We start off with the keyword CREATE and then the keyword FUNCTION.
00:17And then we need to give a name, typical naming rules in play here.
00:23After the name, you have to supply a list of parameters in parenthesis.
00:28So we could list out as many parameters as we want.
00:33You also have the option to do zero parameters which if you'd like to do
00:37zero parameters, you still have to put the empty parenthesis, which I will do here.
00:43Next, we have to declare what type of data, this function is going to return.
00:48Every function will return something and we don't at this point have to decide
00:52the exact value we're returning,
00:54but we do have to decide what data type you're going to return.
00:58So are you going to return a date, a piece of text, a number?
01:02You have to make that decision at this time.
01:04You type in the keyword RETURNS, plural, and I'll use an integer for this one.
01:10So this function will return an integer.
01:12Then we put the keyword AS and the keyword BEGIN.
01:16Most of these things do not have to be on separate lines.
01:19I just find it makes it a little bit easier to read, if you do in fact put them
01:23all on separate lines.
01:24After the keyword BEGIN, we'll need to add some T-SQL statements that accomplish
01:29whatever it is that you want to accomplish.
01:31For now, we'll keep it very simple and we're just going to return a value.
01:36I previously declared we would be returning an integer.
01:39So I will stick with that and say return 7.
01:44Now that I'm done with my function, I will put in the keyword END.
01:49I can execute this and we see some positive feedback at the bottom, command(s)
01:54completed successfully.
01:56I'll go over to the left and expand my favorite menu, Programmability. Underneath
02:01that, we see Functions and this is a Scalar-valued Function.
02:06So I'll hit refresh and now my function appears there, my Test Function.
02:13So notice under the functions category, we have Table-valued Functions,
02:18Scalar-valued Functions, Aggregate Functions and System Functions.
02:22The System Functions are the one created by the machine. We cannot change those.
02:27The other three Table-valued Functions, Scalar-valued Functions and Aggregate
02:32Functions, we will be working within this course starting off with
02:35Scalar-valued Functions for now.
02:38So I've successfully created a Scalar- valued Function called myTestFunction, I
02:43would like to run that function.
02:45Typically, the easiest way to do that is to put it as part of a SELECT statement.
02:50So I will say SELECT and then I need to give it the name of the schema, the name
02:54of the function, and empty parentheses.
02:57When I run that, it returns 7 and that is exactly what we had hoped for
03:03returning a single value.
03:06Notice, if I don't put the parenthesis, I will in fact receive an error or
03:11if I don't list the name of the schema, I will receive an error.
03:16That's a little unusual because at most places in Microsoft SQL Server, the name
03:19of the schema is optional, here it is not optional.
03:23You do have to in fact have say schema.function name ().
03:29That is the only way it's going to work.
03:31Back looking at our function, if we would like to modify it, we can alter
03:37our function thusly.
03:38I wanted to talk briefly about a few common mistakes that happens;
03:43the most common of which is the data type mismatch.
03:46So I said I was going to return an integer. What if I write code that
03:51doesn't return an integer?
03:54Surprisingly, it let me do this! The machine said command(s)
03:57completed successfully.
03:59But, now let's go back and try and run that function.
04:02The error message says;
04:03conversion failed when converting from text to number.
04:07So it couldn't take a value that I gave it.
04:10I told it to return the value test.
04:12It could not convert that to an integer and it did give me an error.
04:16The surprising part is it allowed me to create the function with the error.
04:21It just never allows me to run the function.
04:24So you get the error at a time may be a little different than what you thought.
04:28The other thing to be real careful about, when creating these is, the keyword
04:33RETURN with no S versus the keyword RETURNS with an S.
04:39The first time we use returns, it does have an S, the second time it does not
04:45and if you get those backwards.
04:47It will say incorrect syntax near the keyword RETURN.
04:52So this first one needs an S and the second one does not.
Collapse this transcript
Exploring single-value functions
00:00Now I would like to talk a little more about user defined functions,
00:04specifically, when Microsoft calls a Scalar-valued Function.
00:09Scalar is a single piece of data, such as a single number, a single date, a
00:13single piece of text.
00:15So any function that returns a single piece of data is called a
00:18Scalar-valued Function.
00:19These are the most common functions we work with in Microsoft SQL Server.
00:24In this example, we will be working with some of the code in your exercise files.
00:29The first thing, I'd like to do is populate the authors table with a few addresses.
00:33We're going to be working through some examples with addresses.
00:37And right now no one has an address yet, so we'll go ahead and execute some
00:41code that should give two our users some addresses.
00:48Yes, look at that, now John Doe and Sally Smith both have valid addresses.
00:55So now looking at the code that creates the function;
01:01the function is called format addresses.
01:03It takes four inputs one called city, one called street, one called state
01:08and one called zip.
01:09I think those are all self explanatory.
01:12On line 7, we see it returns a varchar 255.
01:16So it returns a single piece of text that makes it a Scalar-value Function.
01:21Lines 12 through 15, you see we are checking to see if any of the inputs were
01:27null. If that is the case, if any of them are null, we are just going to return
01:31the phrase 'incomplete address'.
01:33We don't have enough information to completely format an address.
01:37I'll scroll down a little more, we see lines 19 through 23, or in a lightweight case
01:43statement, that will take the abbreviation for a state and change it into the
01:47full name for the state. I didn't do all 50 lines.
01:50I just did enough for a demo.
01:52We see line 26 returns, street space city comma state space zip.
02:00So in other words, how an address is typically formatted.
02:04Go ahead and run that and we will see the command(s) completed successfully. That's good news.
02:10Come back to our sample code, and I have one line that will go ahead and
02:15test this function.
02:22We are passing the inputs 100 Main and Buffalo New York and that zip code, and we
02:28see the return is pretty much exactly what we expected.
02:32Just doing this for ad hoc data is not very interesting.
02:36These functions become much more useful when we make them part of a larger query.
02:41So here I have a SELECT statement, it's going to select things from the authors table.
02:48Select first name, last name and then we see the name of the function
02:52dbo.format address.
02:55And then it will pass in the four parameters:
02:57address, city, state and zip.
02:59When we run that, we see the top two lines returned incomplete address and that is correct.
03:06We do not have address information for those two people.
03:10And then lines 3 and 4 returned a properly formatted address, they changed the
03:15state abbreviation to the full name for the state, and it added in the comma in
03:20between the city and state.
03:22So that's very useful as being part of the SELECT statement. We can also make a
03:27function part of a 'where' clause.
03:29So we can filter this query based on results from that function.
03:36To me a very logical thing would be, I want to know everyone that has an
03:40incomplete address, and we'll run that.
03:44And now we see we've got only the users with the incomplete address, fairly useful.
03:48It is also possible to do an order by, on that function field.
03:56In this example, this may not be quite as practical as doing the where clause
04:01but, we can see that we can order by the value of the functions field.
04:05So any time you create a Scalar- valued Function, it is possible to use that
04:10function as part of the SELECT statement, part of the where clause and or part
04:16of the order by clause.
Collapse this transcript
Exploring table value functions
00:00Now I'd like to talk about another type of function, what Microsoft calls a
00:05Table-valued Function.
00:06As the name implies, the results of this function will be an entire table.
00:11I've a little code prepared for you in your exercise files, copy that over.
00:21So the top starts off just like any other function.
00:23We're going to create a function call it 'authors by status' and it will take
00:28one input parameter.
00:29Line 2 says what we are going to return, and we are going to return a table.
00:34And then lines 3 through 11 define that table.
00:37So just like if you were creating a new table, you have to define all the
00:41columns, give it a name, a data type and whether or not we allow nulls for
00:47each particular field.
00:48So it can be a lot of typing to get all this in because we have to define,
00:53in a fair amount of detail of the entire table we want to define.
00:57The meat of this starts on around line 13, and we see an INSERT statement.
01:03So we defined a table. Right now that table is empty.
01:06In order for this to be useful, we have to insert something into that table.
01:10And what are we going to insert?
01:12We are going to insert the results of a query.
01:14Line 16, 17 and 18, define that query.
01:18It's everything from the authors table depending on the value in the active field.
01:25Remember that the only parameter passed to this function is a value that
01:29represents is active.
01:31So this query will filter our results based on that value.
01:35Go ahead and run this, command(s) completed successfully.
01:39You should see it in there now and there we go.
01:47So now this function behaves very much like a table.
01:52We can do a SELECT, store.
01:54Normally you would say SELECT, store FROM table.
01:57But, instead we are going to say select store from our function. Remember, it
02:02does take one parameter.
02:05So there would be all of our authors whose status is equal to zero, or we can
02:10pass it a 1, and there would be all of our authors whose status is equal to one.
02:15This is fairly useful.
02:17Obviously, there's other ways that could accomplish this. For example,
02:20a view would do some similar things.
02:23But, remember you can't pass a parameter to a view.
02:26So the strength of Tabled-valued Functions is that we can pass one or more
02:31parameters to it and get different results based on those parameters.
02:35Other than that they function largely like tables or views.
Collapse this transcript
5. Triggers
Using "after" triggers
00:00In this chapter, I'll be working with two new tables; a products table and
00:04a categories table.
00:06I've created a script that will generate those tables and populate them with some data.
00:11There in your exercise files. You can copy and paste all of that into
00:16Management Studio and run it.
00:19And it should've given me two new tables.
00:22And let's double check and make sure we have some data in those tables. Oh, that looks good.
00:28The first type of trigger I'd like to talk about is called an 'after' trigger.
00:32It's called this because it executes immediately after an insert, update
00:37or DELETE statement.
00:39The trigger allows the original statement to occur with no modifications.
00:43Then it immediately takes over and starts doing some work.
00:47In this example, we're going to use the trigger to enforce a business rule.
00:51The business rule states that whenever a category is marked as inactive, all of
00:57the products in that category should immediately be marked as inactive also.
01:02So I have some code staged for this in your exercise files.
01:06Just like with functions and stored procedures, we start with the keyword Create
01:11and then we use the keyword Trigger.
01:13Then we have to give it a name.
01:15I called mine CategoryDeactivation.
01:16Line 2, we are setting a relationship with a table.
01:20Every 'after' trigger is related to one table and is going to react to
01:24actions only on that table.
01:26Line 3 says AFTER UPDATE.
01:29So that's the one verb I'm interested in.
01:31This trigger will ignore, insert and DELETE statements.
01:35It will only run immediately after an UPDATE statement.
01:38Then let's look at the bulk of the code; line 6 through 14.
01:43We start off on line 6 creating a variable to hold the isActive bit.
01:47I want to make sure with the update that came in, was someone trying to set a
01:54category as active or trying to set it as inactive.
01:56So on line 11 there, I'm looking at the isActive bit in saying it whether or not
02:02it is equal to zero.
02:04If it is in fact equal to zero, I'll perform the actions that start on line 12
02:09which is UPDATE Products.
02:11Set active equal to zero and then we are saying where category ID is in the
02:17category ID from inserted.
02:19Notice there on the line 14, where you are querying in a table called inserted.
02:24Inserted is a temporary table that's only available inside of the trigger.
02:30It's automatically created by the machine and it holds all of the new
02:34information that someone is trying to put into the table.
02:38So let's go ahead and run this, command(s) completed successfully. That's good.
02:43And now we should be able to go under the categories table and see a new trigger.
02:47And there it is, CategoryDeactivation.
02:53So to test this, let's first look again at the products table, and we see three
03:02items in category one all of them are active.
03:05Now I'm going to issue a command that will mark the category one as inactive.
03:12When I execute this, it should perform that action and then the trigger
03:16will fire and update the product table, and mark everything in category 1 as inactive.
03:22That would appear to be successful.
03:28Let's look at the product table just to make sure.
03:30And yes, our three products in category 1 are now inactive.
03:37We use the trigger to enforce the business rule that whenever a category is
03:42marked inactive all of the products should immediately be marked as
03:45inactive also.
Collapse this transcript
Using "instead of" triggers
00:00The next type of triggers we will talk about are 'instead of' triggers.
00:04These triggers are executed as an alternative to an INSERT, UPDATE, or DELETE statement.
00:10These triggers completely block the original statement leaving the data unchanged.
00:14However, inside the body of the trigger we can choose to modify data and we usually do.
00:20In this example, I'll be of using a trigger to enforce a data integrity rule.
00:25The rule states that we cannot ever delete a category.
00:28We must just mark that category as inactive.
00:31So if someone tries to delete the category, I want to trigger to block the
00:35action and instead update the record and set active equal to 0.
00:40I staged some code for you in your exercise file.
00:44Let's talk about this code.
00:45CREATE TRIGGER CategoryDelete on (dbo).(Categories) and line 3 says INSTEAD OF DELETE.
00:53So again that will prevent the DELETE statement from happening.
00:57Line 6, 7, and 8 perform an update on the categories table instead of the delete.
01:03It's going to set active equal to 0 where the category is in and then we select
01:09from the deleted table.
01:11The deleted table is a temporary table automatically created by the trigger that
01:16contains the data the user was trying to delete.
01:18So let's go ahead and run this.
01:21Command successful.
01:23We can refresh our trigger section and we should see CategoryDelete. That's good news.
01:29Now let's test it.
01:31We can select from our categories table and see what it looks like now.
01:38And we see category number 2 Pants is currently marked as active.
01:42Let's see what would happen if someone tried to delete that category.
01:48What should've happened is the trigger should've caught this DELETE statement,
01:52blocked the DELETE statement, and turned it into an update instead.
02:00That appears to be exactly what happened.
02:01Category two is still there.
02:03It has not been deleted it, but instead the trigger marked it as inactive.
02:07It certainly looks like success.
Collapse this transcript
Using nested triggers
00:00In our two previous examples we created one trigger that will block deletions
00:04from the categories table, instead marking records as inactive, and we created
00:09another trigger that when a category is marked as inactive, it marks all
00:13products as inactive also.
00:16This means that if I issue a DELETE statement, the first trigger fires, blocking
00:21my DELETE statement, and instead updating the record.
00:24That update, the update that was caused by the trigger, will in turn cause the
00:29second trigger to fire.
00:31This situation where the actions of one trigger cause the next trigger to fire
00:35is called nested triggers.
00:37The ability to nest triggers is turned on by default, but you can turn it off if you want to.
00:43I have some code in your exercise files that will do this.
00:47It's an SP configure, the feature we would like to configure is nested triggers.
00:52It is turned on by default which would be a 1.
00:55So we'll use a 0 to turn it off and if you'd like to turn it back on, just use a 1.
01:01Even when nested triggers is turned on, it is always limited to 32 levels.
01:06So we can have trigger 1, cause trigger 2 to fire which causes trigger 3 to
01:11fire, which causes trigger 4 to fire, but you can only go 32 levels deep.
01:16That is at least the machine says, you can only go 32 levels deep.
01:20As a best practice I would recommend a lot less than 32 levels.
01:23Obviously, something that goes 30 or 31 levels deep could be very difficult to
01:28troubleshoot and very difficult to get your mind around what's going on.
01:32As a best practice, I usually try and limit my nesting to three levels or less.
Collapse this transcript
Using database-level triggers
00:00The triggers we've seen thus far are all at the table level, meaning they react to
00:04an INSERT, UPDATE, or DELETE statement issued to one table.
00:09SQL Server also supports triggers at the database level.
00:13These trigger fire whenever a statement is issued that would change the
00:16structure of that database.
00:17I have an example staged for you in your exercise files.
00:24This trigger we're saying is on the database on line 2, so that means it applies
00:28to the entire database.
00:30Line 3 says it is for any attempt to drop a table or any attempt to alter a table.
00:37The body of the trigger is very simple.
00:39It's going to PRINT a message say you do not have permission to drop or alter to
00:42the table and then is going to ROLLBACK.
00:44In other word it's going to undo whatever someone was attempting to do.
00:49So I'll execute this, and now we can find these triggers under the
00:53Programmability menu.
00:54We have a folder called Database Triggers.
00:58If I refresh that, I see the new trigger I just created.
01:01So let's go ahead and test this trigger.
01:03I'm going to attempt to drop a table and the triggers should stop that from happening.
01:12It did in fact say you do not have permission to drop or alter tables.
01:15It also said the batch has bit aborted.
01:18Meaning it completely blocked me from happening.
01:21And if I do a refresh, I see clearly the Authors table is still there. So good job
01:27trigger! You blocked me from possibly making a mistake.
01:30I do implement this type of trigger and production databases often, because in
01:35my opinion no one should be changing my production databases.
01:38You can make the triggers slightly more robust and check permissions.
01:42So check who is trying to do drop and then possibly allow or do not based on that.
01:48But this is a nice way to stop some mistakes from happening or possibly even
01:53stop some malicious users from doing bad things to your database.
Collapse this transcript
6. Putting It All Together
Exploring a real-world INSERT procedure
00:00Now I'd like to demonstrate some more complex stored procedures.
00:03These are the types of procedures I commonly see on large databases in the real world.
00:08They implement business rules as well as enforce data integrity requirements.
00:13In order to execute the examples in this section we'll need a new table.
00:17I have a text file of data in your folder of exercise files.
00:20Let's import that data now.
00:22I'll right-click on myDatabase, go to Tasks, and near the bottom we have Import Data.
00:29On this screen I'll click Next.
00:31The first question it asked me is, what's my data source?
00:32My data source will be a Flat File and I'll browse to that file now.
00:39It's in the Chapter 6 section of your exercise files.
00:43This dialog box defaults to text files.
00:46What I want is want is actually a CSV, so there we will pick up students.csv,
00:51and now it's just a whole bunch of Next, Next, Next, Next, Finish.
00:58And I get a bunch of green check mark saying Success. That seems good.
01:02I'll hit a refresh here and I have a new students table.
01:06Let's go ahead and look at some of that data.
01:08We have things like a student ID, last name, first name, state, some other contact
01:13information including an email address, a graduation year, GPA, and a yes or
01:20no on whether or not they would like to receive our email newsletter. Great!
01:25Now that we have data to work with the first stored procedure I'll implement is
01:28an insert stored procedure.
01:30I'm going to make up the following fairly plausible hypothetical rules about inserting.
01:36When inserting, every ID must be unique.
01:39It's something that could be handled by the database automatically, if it was
01:43automatically assigning IDs, but in this hypothetical I'm going to say different
01:47system is assigning IDs and as they come in to my system, I want to double-check
01:51and make sure they're unique.
01:53Also, things like a GPA must be between 0 and 4 with no more than two decimal places.
01:58That's something that a front-end application should handle, but it doesn't hurt
02:02for me to double-check it.
02:03Let's say hypothetically someone else is writing the front-end application and
02:07they are either unwilling or unable to make this check.
02:11Then I'll check it on the way into the database and we're going to return a 1
02:16for success or 0 for failure.
02:18So I have a stored procedure stage already in your Exercise folder.
02:22It significantly longer than some of the stored procedures we've worked with earlier.
02:26So I'll walk you through it.
02:28We start off of course with keyword, create keyword procedure, and then we have
02:32to accept quiet number of parameters.
02:33The number of parameters I am accepting is exactly the same as the number of
02:37columns in the table.
02:39I need one parameter for each field we're going to insert.
02:42Scrolling down a little right after the BEGIN statement, the first I want to do
02:47is check to make sure the ID does not already exist in the database.
02:50So that's one of my business rules.
02:52We have to have unique IDs.
02:53So line 18, 19, 20, 21 will perform a query to see how many times this ID already exists.
03:01Line 23 checks to see if that number is greater than 0.
03:05If it is, it raises an error and returns 0.
03:09That is exactly the desired functionality.
03:12Once that happens, the code will move on to line 31, 31, 32, 33.
03:18We will format our GPA as two decimal places.
03:21That was one of our business requirements and then line 36, make sure the GPA is
03:26within a certain range.
03:28If the GPA is greater than 4 or less than 0, I am going to return an error to the user again.
03:35If we pass that check we're down to lines 44 where it's time to actually attempt
03:39the insert, fairly straightforward, INSERT statement.
03:43The very last thing I do is check to see the value of a variable @@ROWCOUNT.
03:48This as a very variable I did not create.
03:51SQL Server automatically creates and the updates this variable with how many
03:55records were modified by the previous statement.
03:58If everything worked properly, I should've modified exactly 1 row.
04:02So if that value does =1, I'll return a 1 to the user indicating success of
04:07the stored procedure.
04:09So we'll go ahead and execute that, command(s) completed successfully.
04:12I always like hearing that.
04:14So there's my stored procedure, Students_Insert.
04:19Now let's go ahead and execute this.
04:21I also have a little code stage for you for that.
04:25So I am going to try to insert the values, ID 123456, last name Guidry, firstname
04:30Martin, some basic contact information there.
04:33Notice that 7.1; I am intentionally trying to insert bad data.
04:38I am claiming that my GPA is 7.1.
04:40Obviously, very ambitious.
04:42If our stored procedure functions properly, it should return an error.
04:46So let's go ahead and execute.
04:47Look at that! It says GPA is invalid.
04:50That is a good catch.
04:51So I'll change that to a more realistic value and we will try to run it again,
04:56and now it's says one row affected.
04:58That likely means success.
04:59I'll go check the database here in just a second, but I am going to run it again
05:03and it should say ID already exists.
05:06So it successfully did the insert the first time.
05:08If I try to run it again, it stops me saying this would be a duplicate ID,
05:12which is a bad thing.
05:14Just to make sure it actually got in there.
05:16Let's go ahead and query the table.
05:21That returns exactly 1 row. That's good news.
05:24We'll scroll over.
05:25You see my GPA there formatted to two decimal places.
05:28That was one of the requirements.
05:30So it seems like everything is working great.
Collapse this transcript
Exploring a real-world UPDATE procedure
00:00Next I'd like to talk about a real-world UPDATE stored procedure.
00:04On this one we're going to work with a slightly different set of business rules.
00:09Now in the real-world your insert and UPDATE stored procedure would likely
00:12have the same set of rules.
00:14I am going to go with a different set of business rules just for the sake of
00:16having more things to demo.
00:18So our update rules are you can not subscribe to the newsletter if your
00:23email address is null.
00:24This makes sense because our newsletter is an email newsletter.
00:27So you can't subscribe if you don't have an email address.
00:30The update stored procedure should not be allowed to change the ID.
00:33It can change any other piece of data, but it cannot change someone's ID.
00:37It needs to return an error if the ID does not exist.
00:40If someone attempts to modify student 1234 but student 1234 does not exist in
00:46the database, we need to let them know about that problem, and then we have my
00:51general best practice return 1 for success and 0 for failure.
00:55So I have a stored procedure staged that should accomplish all of this and
00:59we'll start from the top.
01:01So we're going to CREATE PROCEDURE Students_Update.
01:04One parameter for every field will take as an input, the ID will tell us which
01:10record we want a change, and everything else will represent the new values
01:14that were changing to.
01:15Scroll down a little.
01:17Lines 18 through 21 will count the number of times this ID exists in the database.
01:23If it comes out as 1, we will continue on, but if it comes out as anything other
01:28than 1 that's an error condition.
01:30So if the ID does not exist, then there's nothing to update.
01:34If the ID exists more than once we've got a bigger problem on our hands.
01:38So we'll only continue if the ID exists once and exactly once.
01:43Line 30 to 32 implement the rule of you cannot subscribe to the newsletter
01:49if your email is null.
01:50This turned out to be a relatively small amount of code.
01:53It checks to see if email address is null, and if so it sets your
01:57subscription to off.
01:58You're not subscribed to the newsletter.
02:01Line 36 down is a big UPDATE statement that concludes with a where clause on
02:07line 47 where we're checking to make sure the ID that we are updating is in fact
02:11the ID that was passed to us.
02:13Then similar as before, line 51 through 54 is checking to make sure we modified
02:19exactly 1 record that would indicate success.
02:22Anything other than modifying one record would indicate failure.
02:27So I'll run this, commands completed successfully.
02:32So I now have Students_Update and I have a little code staged that'll run this.
02:37So now let's go ahead and execute this stored procedure.
02:41Notice that I'm updating my own record.
02:43I'm setting my email address to null and I'm trying to subscribe to the newsletter.
02:48I went ahead and put it 1 for my newsletter subscription, the stored procedure
02:52should catch that and change that to a 0. So I'll run this.
02:56It looks like success.
02:58Now let's go ahead and check that and there I am.
03:05My record is still intact, email has been set to null, and newsletter has been set to 0.
03:10So stored procedure is functioning as desired.
Collapse this transcript
Implementing logging on DELETE
00:00For our DELETE stored procedure, the rules we're going to implement is the
00:05stored procedure can only delete one record at a time, and we must maintain a
00:09log of who deleted and when.
00:11So in order to maintain that log I'd like to create a new table that will be
00:15used for that logging.
00:16I have some code staged for that.
00:18It's a three column table; one column for user name, the person who did the
00:22deletion, one column for the ID that they deleted, and one column for the date.
00:26I also have some codes staged for the stored procedure.
00:30So starting at the top we have with CREATE PROCEDURE Students_Delete.
00:34This time we are only taking one parameter.
00:36All I need is the ID of what you would like to delete.
00:39Line number 2 there is new to us.
00:41We're saying EXCUTE AS CALLER.
00:43There are some context in which a stored procedure might execute as the
00:47system, but in this one, one of my business requirements is to log who is running this.
00:52So I am going to specifically saying EXCUTE AS CALLER.
00:56Line 6 through 11 we check to make sure that this ID already exists and make
01:01sure it only exists in the database once.
01:04Now we did something very similar to this in the INSERT stored procedure, and the
01:08UPDATE stored procedure.
01:10Now we're going to have it a third time in the DELETE stored procedure.
01:13This is becoming a little displeasing to me to have an essentially the exact
01:17same code running in three different places.
01:19So I'm going to use a technique we talked about earlier in this course of
01:22simplifying our lives.
01:23I am going to create a function that performs all of this and that way we'll
01:28just be able to use the function.
01:30We won't have to maintain the exact same code in three different places.
01:33So we'll take a slight detour and I'll pull up the code I had for the function.
01:37So this is a function that is going to count the number of times that a certain
01:41ID exists in our students table.
01:45The only parameter you have to pass to it is an ID.
01:49The ID you're in fact looking for.
01:50It'll return an integer, a single integer saying how may times does this ID occur.
01:58Execute that, command(s) completed successfully. That's good news.
02:02So now I'll go back to the stored procedure and replace that code.
02:05This code that appears in three different places.
02:08I want to simplify my life and get rid all that.
02:12All I need to check on is the value of this. So that code will pass the ID in
02:19question to the function called Count IDs, and that function will return the
02:25number of times that ID occurs in our table.
02:29Beyond that, things are fairly straightforward.
02:31Line 50 and 16 will perform the delete.
02:34Line 20 checks to see if we did in fact delete exactly 1 record, and if we did
02:39we need to meet our other business requirements of logging who did the deletion.
02:43So line 22 and 23 will insert a new record into Student_Delete log.
02:49The values we are looking for is suser_ sname which is a SQL Server variable that
02:56stores the name of who is running the stored procedure.
02:59The next thing we pass to it is the ID that was deleted, and the last thing we
03:03pass is the current date.
03:05Let's go ahead and run that and that gives us one stored procedure for
03:14deleting a student, one stored procedure for inserting a student, and one for
03:18updating a student.
03:19We have nice a little package of all of the things we're likely to perform on a student.
03:24Go ahead and test the delete functionality.
03:29It says one row affected so that should have deleted that ID from the student
03:34table, and yes, in fact that record is gone.
03:38We also said we we're going to log this.
03:41So let's check to make sure our log is functioning properly, and we see one
03:45record in there, User Name Martin, deleted the ID 123456.
03:50There is the date the record was deleted.
03:52So we have successfully implemented all of the business rules for a
03:56DELETE stored procedure.
Collapse this transcript
7. Using CLR Assemblies
Understanding the Common Language Runtime (CLR) and the .NET framework
00:00Now I would like to talk about a very different technique of creating stored
00:04procedures and functions.
00:06I will create some stored procedures using the .NET framework languages.
00:10In the demos I'll focus on C# which is certainly the most popular language, but
00:15we can also use any of the hundreds of .NET languages C#, VB.NET, F#, J#
00:23IronPython, IronRuby, and many others.
00:27It is possible to write a stored procedure at the .NET framework, because both
00:32the .NET framework and SQL Server are heavily integrated with the Common
00:36Language Runtime, commonly called the CLR.
00:39However, not every version of the CLR is compatible with every other version.
00:45So here on the screen I have a chart showing some of the compatibility levels.
00:48SQL Server 2005 and 2008 is compatible with the CLR versions 2.0, 3.0, and 3.5.
00:59And SQL Server 2012 we still get 2.0, 3.0, 3.5, but we also additionally get 4.0.
01:07This can lead to some interesting decisions for a developer as to which version
01:11should you write your code in.
01:13But in many cases it's not that hard to change what version you're an after the fact.
01:19Inside of Visual Studio you can right- click on any project, go to Properties,
01:25and you'll see one of the dropdowns is Target framework.
01:28Here it's been selected to the 4.0.
01:30It would be very easy to change this to 2.0, 3.0, 3.5.
01:34Obviously, there are a few features that are limited to a specific version of
01:40the framework and we can have some compatibility issues.
01:43But the majority of your code will work with any version of the .NET framework
01:50and it's very easy to change right here.
Collapse this transcript
Using CLR with SQL Server 2012
00:00In order to use .NET code in our SQL Server we must first enable CLR Integration.
00:07CLR Integration is a default feature, but the default is that it is turned off.
00:11So we merely need to turn it on.
00:13We will do this by using the sp_configure command.
00:19The feature we're interested in configuring is called clr enabled.
00:24Notice there is a space in there, no underscore.
00:27We want to set that equal to a value of 1, but the syntax here rather than
00:32use the equal sign so we use a comma.
00:35So this will reconfigure our server to set clr enabled equal to 1.
00:40After issuing a command like that you have to issue another command called
00:44RECONFIGURE and that should be all we need.
00:50We notice at the bottom it says configuration options clr enabled change from 0 to 1.
00:55So in other word, it went from turned off to turn on.
00:58So that's the first step.
01:00CLR is now enabled for the entire instance of SQL Server.
01:04There's no way to turn this on and turn it off for one particular database.
01:08It is a setting that applies to the entire server, not just one database.
01:13Also, once it turned on it will remain on.
01:15So even if you reboot the server when it comes back up, this would still be on.
01:20The only way to turn it off would be to issue the same command and use a 0 instead of 1.
01:27Now that clr is enabled we can add an assembly.
01:30So under myDatabase we have Programmability and the fourth option below that is Assemblies.
01:36It should already be one assembly and there a default assembly
01:40Microsoft.SqlServer.Types.
01:42We can now add our own assembly.
01:44An assembly is basically a DLL that was written in any of the .NET languages.
01:49For now I am going to assume that DLL already exists.
01:52Let's say it was written by a different developer, although a few movies down
01:56the road we're going to be ride in our own DLLs.
01:59So we right-click, say New Assembly, and we will have to say where that file is
02:04and now have an assembly called Hello World.
02:11Again, that's a DLL that was written in C#.
02:15Compiled inside of that assembly is some code to write a stored procedure.
02:19So we will now need to tell SQL Server that we want create a new stored
02:23procedure based on the C# code.
02:26The beginning of the syntax is very similar to other stored procedures.
02:29We will need the keyword CREATE and the keyword PROC and then we have to give it a name.
02:39Then instead of writing code here we're going to tell the machine that this is
02:44external to SQL Server.
02:46So we say EXTERNAL name and then we have to tell it the name.
02:52The first part of this is going to be the name of the Assembly which is helloworld.
02:58The next part is the name of the class that's inside of the Assembly, which I
03:02happen to know is HelloWorldProc.
03:08Then the third part is the name of the particular method we're looking for which
03:13is also HelloWorld.
03:18So that successfully created a new stored procedure.
03:21Again the name in the EXTERNAL name is three parts separated by periods.
03:24It's the name of the assembly, dot name of the class, dot name of the method, and
03:32we have successfully created a stored procedure.
03:35We can go onto our Stored Procedure section and see a new one called test.CLR.
03:40That's exactly what I expected, and let's go ahead and execute that.
03:49And it returns the phrase Hello world!
03:50Again, we did not write any T-SQL there.
03:54All of that was implemented in C#, was compiled into a DLL, we imported the
04:00DLL as an assembly, we created a new stored procedure based on that DLL, and
04:05now we can execute that stored procedure just the exact same way as any other
04:10stored procedure.
Collapse this transcript
Writing stored procedures with C# .NET
00:00Now we're going to write some C# code that will eventually become a stored procedure.
00:05We'll start off by create a new project in Visual Studio.
00:09For the project type I want it to be a Class Library.
00:13The result of a Class Library is a DLL and we will import that DLL into SQL Server.
00:20We'll name our Class Library CLRtest.
00:25Rather than use of the default class they have, I'll create a new class.
00:32And I'll call the class mySprocs.
00:38The machine automatically wrote some code for me.
00:40Some of it I want, some of it I don't want, and I'll keep the using statements,
00:44but I'll also need to add a few of my own using statements, because we're
00:48working with a database, we will need to add using system.Data.
00:53We will also need to add using system. Data.SqlClient and system.Data.SqlTypes.
01:05One more with the Microsoft.SqlServer.Server.
01:12So that should be all the using statements we need.
01:15I said I'd call myClass mySprocs.
01:17It'll need to be marked as a public class, and inside of that a class for now
01:25we're only going to have one method.
01:28The method will have to be marked as public and static.
01:32In this case it'll also be void, because it does not return anything.
01:37The name will be InstertAuthor which is a descriptive name, because I plan to
01:41use this method to insert one record into the author's table.
01:46Before I build out the body of the method I'll need to decorate the method.
01:51The decoration sends information to the compiler on what we plan to do with this method.
01:58It will slightly change the behavior of the compiler.
02:02In this case we will decorate with the phrase
02:04Microsoft.SqlServer.Server.SqlProcedure, and most other places it's called a
02:14stored procedure and here it's called a SqlProcedure.
02:18So this declaration will tell the compiler to compile this a little different,
02:22because it's going to be a SQL stored procedure.
02:26The body of the method will need a connection to the database.
02:31Typically, when creating a connection to a database, we have to go through a
02:35lot of effort to say the name of the server or the IP address of the server,
02:39the name of the database we want to connect to, the permissions, et cetera, et cetera.
02:43Here we can get off a lot easier, because remember this code is going to be
02:46running inside of a database.
02:48So we can get away with just saying connect to the database that we are part of
02:54already, and we say context connection=true.
02:59In other words, use the connection that you are already part of the context of.
03:05Execute a single SQL statement, insert into authors.
03:10For this case we're just going to insert into two columns, FirstName and LastName.
03:15We'll insert the VALUE Sally, Smith.
03:18The next line, make sure that our command and our connection are talking to each
03:22other, and then we have three lines at the bottom, one to Open the connection
03:26one to ExecuteNonQuery.
03:28That's a NonQuery, because we're not expecting data to be returned and then we Close.
03:33Obviously, best practice to close whatever you open.
03:37This looks like it's ready to go.
03:39We can go ahead and Build, and off the bottom we see a message saying build
03:45succeeded in the very lower left-hand corner.
03:48The only thing left to do now is to save this DLL.
03:51We're going to need to save it someplace that's easy to find.
03:55So I'll save it in the exercise files and then we will save it as CLRtest.
04:02Okay, so I should be done with Visual Studio.
04:04Now I have to get into SQL Management Studio and I want to import that assembly.
04:10That will be a right-click > New Assembly, and I'll have to browse to the same
04:15directory I was just in, and there's my DLL. That looks successful.
04:28I now see the assembly CLRtest.
04:31So now that CLRtest has been imported,
04:34we can create a stored procedure based off of it.
04:38Keyword CREATE PROC, and I'll need it to give it a name.
04:43I could name it anything I want, but it seems like the easiest thing would be to
04:47use the same name here as I used in the C# code which was InsertAuthor, and then
04:55I'll say AS EXTERNAL NAME.
04:58The first part is the name of the assembly, and then the name of a class, and then
05:07the name of the method and that ran successfully.
05:14Good news, good news. We will look at our stored procedures, hit refresh and
05:18we see InsertAuthor. So great!
05:21Let's go ahead an execute that.
05:26And it says again completed successfully.
05:29Let's go ahead and look at the AuthorsTable and we would expect to see one
05:32record for Sally Smith, and there we go.
05:36The last line Sally Smith has now been inserted.
05:39So we've successfully wrote some C# code, compiled that C# code into a DLL,
05:44imported the DLL, made a stored procedure based on that DLL, and we can execute
05:49the stored procedure.
Collapse this transcript
Writing functions with .NET
00:00In this section I am going to talk about using C# to write a user defined function.
00:06So here in Visual Studio we'll create a new project. Again, I want it to be of
00:11type Class Library and I'll call it a CLRfunctions.
00:19I prepared some code ahead of time that you can find in your exercise files, so
00:24I'll copy and paste that over to Visual Studio and we can talk about it.
00:28The top eight lines are typical using statements that we have with any SQL
00:32Server stored procedure or function, and then I created a new class, starting on
00:37line 10, public class myFunctions. There is one method in there called isActive,
00:43it is decorated with Microsoft.Sql.Server .Server.Sql.Function. This will provide
00:50a clue to the compiler that we are in fact writing a SQL function.
00:54Notice on line 13 we declared the method to be public static and the Return type is SqlString.
01:02When we're working with C# code, that's going to eventually be executed
01:06inside of SQL Server, we have to use slightly different data types, rather
01:10than use things like sting, an integer, we've to specify it as a SqlString or a SqlInteger.
01:17So we work with slightly different data types.
01:19Here we have SqlIntegar as the Return type of the function, and we're passing one
01:24parameter called ActiveBit and that is a SqlInt, in this case at 32bit
01:30SqlInteger, so SqlInt32.
01:34The point of this function, it is going to read the bit, the 1 or 0 we used to
01:39store whether or not someone is active, and just return something that's a
01:43little more friendly, return some text that actually spells out the word Active
01:48or Not Active, based on the value of that bit.
01:51So we see some fairly straightforward logic; line 15, 16, 17 and 18, a simple if
01:57statement, if (ActiveBit == 1) we'll return the phrase Active, else, we return
02:04the phrase Not Active.
02:06So this is all the code we need. We go ahead and Build Solution, and in the lower
02:11left we see the build succeeded. That's certainly good news.
02:14Now we'll need to save all of this in a place that's easy to find, and now that
02:21should be everything we need to do in Visual Studio.
02:23We will flip over to SQL Server Management Studio, we will need to import the New
02:30Assembly, and we'll have to browse to where we just dropped that. We
02:42successfully created the assembly CLRFunctions.
02:46So now it's time to create our function.
02:47I have again pre-staged some code for you that's in your exercise files. We will
02:55copy and paste that. We see it says CREATE FUNCTION, we gave it a name, and then
03:01it's going to take one parameter. That parameter is an integer.
03:04We say it RETURNS NVARCHAR.
03:08So we talked earlier a little bit about the differences in data types, C# is
03:13going to return what it calls a SqlString.
03:15SQL recognizes is that as the NVARCHAR data type, and we'll have to match those up.
03:22If those didn't match we would get an error when creating this function.
03:27And in the bottom part EXTERNAL NAME, which again goes
03:31assemblyname.classname.method, so that CLRfunctions.myFunctions.isActive.
03:39We execute that. It says Command(s) completed successfully. That's good news.
03:44I can come over here in my Functions section and expand out Scalar-valued
03:49Functions, hit a quick refresh, and I see isActive is now a valid function.
03:55So now we're going to write a SELECT statement that actually uses that.
04:02So I want to SELECT FROM the Authors table.
04:08And I want to select three things: FirstName, LastName, and this new function
04:16we just created. That takes one input parameter and that parameter will be the ActiveBit.
04:26We run that, and we see every line Returns Not Active, which is in fact accurate.
04:32All of our Authors are In Active, based on things we did in previous demos.
04:37This might be a little bit more interested if we had an author who was active,
04:40so let's go ahead and do that.
04:46We'll make John Doe, we'll make him Active, and we'll run this again.
04:52We see our function is operating properly. Anytime the Active field is equal to
04:571, our function writes the phrase Active, and anytime the Active field is not
05:04equal to 1, it writes the phrase Not Active.
Collapse this transcript
Choosing between T-SQL vs. CLR
00:00Now that we've seen how to create a stored procedures using T-SQL and how to
00:04create stored procedures using C#, you're going to be faced with a decision.
00:09Every stored procedure you create, you have to choose either T-SQL or C#. I'd like
00:14to give you some tips on which one to use.
00:18There's very little that can be done and one that can't be done in the other. If
00:22you try hard enough, you can accomplish anything with either one.
00:25But each one does have its stress and its weaknesses.
00:28T-SQL's strength is certainly querying data.
00:32We can just go in there and directly write a SELECT, UPDATE, INSERT or DELETE statement.
00:37You don't have to set up a connection, don't have to close a connection. We just
00:41write our T-SQL statements and they run.
00:44T-SQL however, is poor with complex logic.
00:48We have very few decision structures. Basically, you've an if, and not a whole
00:53lot of else, and we have a very few looping structures.
00:55You have a while, and not a whole lot else.
00:58T-SQL does not natively support, arrays, collections, for-each or classes, and
01:04all of those are things that the typical programmer wants.
01:07The .NET languages, their weakness is querying data and it's not super
01:12difficult to query data, but you're going to have to write approximately 3 to 5
01:16lines of code to set up a connection, and then every time you want to use that
01:21connection, you should manually open the connection, and manually close the connection.
01:25So it's placing some administrative overhead on the developer.
01:29The .NET however, is very robust with looping and control of flow.
01:34We've lots of great looping structures, lots of great decision structures in
01:38all of the .NET languages.
01:40And the .NET languages can be compiled for multiprocessor environments and will
01:44run much faster and much more efficiently in a multiprocessor environment.
01:48So when making this choice, Microsoft has clearly stated repeatedly that you
01:55should use T-SQL for any stored procedure where the primary focus is data access.
02:01However, if you have complex logic or a CPU intensive function, they
02:05recommend the .NET framework.
02:07I certainly agree with both of those recommendations.
02:11I'll go ahead and add a third one, but you also have to think about human
02:14resources, the people that are writing the program, if they are much stronger
02:18in T-SQL, or much stronger in C#, obviously, that's going to influence your decision.
02:24But if your team of developers has approximately the same level of experience
02:29with both, then certainly these are valid ways to make the choice.
02:32T-SQL for data access and .NET for complex logic.
Collapse this transcript
8. Exploring an ASP.NET Web Application
Creating a basic web form and connecting to a database
00:00Now let's look at assembling some of the pieces we're going to use to create our
00:04web application that will communicate with our SQL Server stored procedures.
00:08Here in Visual Web Developer, I am going to create a new website.
00:13I'd like to use the template--a C# template for an ASP.NET Empty Web Site.
00:18I'd like to drop that in our Exercise folder and we'll call it the AuthorsSite.
00:25So this gives me an empty solution with no data in there.
00:32I'd like to add a new basic web form, so I'll right-click and say Add New Item,
00:37I'd like to add a web form and I'd like to call that web form, AuthorsPage.
00:42The machine will write some code for me, but that--I'm not going to use that.
00:49I've already written some code that should be in the exercise files.
00:53We'll look at the code real quick;
00:55we have some styles that we're setting up.
00:57Two styles, one for the headings, and one for the body, and then we have a
01:01table, that's creating a space for a list of all active authors, and another
01:06space for us to create a form to insert new authors.
01:11If we flip over to Design view, we can see this, our two headings and two empty
01:16spaces available and ready for us to put exciting stuff in there.
01:20Now I'd like to bring this home with something a little more practical.
01:24Obviously, users won't go directly to the database to update and insert records.
01:29More likely, they would go to an application or a website to manipulate the
01:33records in our database.
01:35So I am going to go ahead and create a small web application that connects to our database.
01:40It'll use some stored procedures and functions, and we'll see that if we take
01:44some time and effort to set up our stored procedures and functions correctly,
01:48then the level of effort and the amount of code we have to write on the
01:52website is very easy.
01:54The next thing we'd like to do is create a connection between our web
01:57application and our database.
01:59We'll do this off of a Window called Database Explorer.
02:03Inside of Database Explore, the top option is Data Connections.
02:06We can right-click that and say Add Connection.
02:09Up there you'll need to give it the name of your SQL Server or the IP address. There is mine.
02:15We have the option to Use Windows Authentication of SQL Authentication.
02:19I'm going to stick with Windows and we will need to choose which database
02:23we're interested in;
02:24my database that we were working in previous examples, hit Test Connection, it says succeeded.
02:30That's good.
02:32And now we see a new connection named thusly, basically it's the name of our
02:36server.name of the database.
02:39To open that up in Explorer, we see the tables we were working with previously.
02:44And we also see the stored procedures we worked with previously, and the
02:48functions we worked with previously.
02:50So we are very close to being able to run the stored procedures off of the
02:55web page.
Collapse this transcript
Executing a stored procedure
00:00Now I'd like to go ahead and implement the functionality that will call a
00:04stored procedure and display data on the screen.
00:07Here we can see we have a space available for a list of active authors.
00:12So first let's write a stored procedure that returns all the active authors and
00:17then we'll connect that to the web page.
00:19I have some code prepared in the exercise files.
00:22And it's a very simple stored procedure that selects store from the Authors
00:26table where Active equals 1. So that would be all of our active authors. That looks good!
00:32Going back to Visual Studio, I'll insert my cursor into the appropriate table
00:38cell, and off the toolbox I want find the Data section.
00:42So I'll scroll down a little and underneath the Data section there is a GridView.
00:49I'll drag our GridView over and it's asking me a few questions; one of them,
00:52what is my Data Source, and currently it's None.
00:55I'll create a new Data Source.
00:57I want that to be a SQL Server data source.
01:02We created the connection a few videos back, so now we have the option to
01:06use that connection.
01:09In this interface, it's asking me if I'd like to use a table or a custom stored
01:14procedure. I'd like to use a custom stored procedure.
01:17Then I'll hit next, and this one is asking me the name of my stored procedure. We
01:22just created getActiveAuthors. That's the one I want.
01:26We can hit a test, return some data and that certainly looks like the accurate
01:31data we were hoping for.
01:32So I'll hit Finish. We're now ready to test this.
01:35So I'll go ahead and start debugging, and look at that! We've got a web page and
01:40we have got a list of all of our active authors successfully.
01:44We connected that stored procedure to our website, didn't actually write any
01:49code in the website just yet. We will be getting into that a few sections down the road.
01:54But for now it's just a matter of click and drag and setting a few parameters, so
02:00the bulk of the work was the original setup of the stored procedure.
Collapse this transcript
Passing parameters
00:00Now it's time to implement the functionality that will allow the user to
00:04insert a new author.
00:06In order to do this, we'll have to get our web page to accept some input and
00:10then pass that input as parameters to a stored procedure.
00:14First let's create the stored procedure that expects the parameters.
00:19I have pre-staged a stored procedure.
00:22We'll go ahead and look at that code.
00:24The procedure's name is InsertNewAuthor and accepts two parameters, a firstName
00:28parameter and a lastName parameter, and then it executes a simple INSERT
00:33statement, inserted into the Authors table, FirstName LastName and the Active
00:38status of 1. Command(s) completed successfully. That looks good.
00:43Now back on our web page, I'll insert my cursor into the blank area under insert
00:48new author, and I'm going to type the phrase FirstName and then, I'll drag a text
00:55box from the Toolbox that will be used to insert the FirstName.
01:00I'll then put a hard Return after that and type LastName, drag another
01:05textbox, and then under all that, we'll want a single button that will cause
01:12the insert to happen.
01:14I want to rename that first textbox, so I'll right-click on it and look at the Properties.
01:19At the very bottom of the Properties, it currently has the ID of TextBox. It's
01:23not very descriptive.
01:24I'd like it to have the ID of FirstName.
01:28and similarly the other textbox should have the ID of LastName.
01:34So that's ready to go.
01:35Now I'll double-click on the button and that'll take me to the area where I can
01:39write the code, and again, I have pre-staged some code, so I'm going to delete
01:44all of the stuff that's already there and copy and paste my own.
01:49Looking at the top, we have several using statements that are all necessary to
01:53communicate between the web page and the database, and then we see the bulk of
01:57our work happens here in the Button_Click method.
02:00We're going to create a new connection and I'll scroll over and show you that
02:04connection is based on the ConnectionString we created previously,
02:08myDatabaseConnectionString.
02:11We'll create a new command, the CommandText will be InsertNewAuthor, the exact
02:16name of our stored procedure and the CommandType will be StoredProcedure and
02:21we'll connect the command to the connection.
02:23Now for the parameters. We're creating two parameters:
02:26one called firstNameParam and one called lastNameParam. These correspond to the
02:31parameters the stored procedure is expecting called firstName and lastName
02:35respectively, and they will get their values from the textbox, FirstName.Text and LastName.Text.
02:43Just creating the parameters doesn't connect them to the command.
02:47So we have to do that in two additional lines of code, where we add the
02:51parameters to the command.
02:53Then we have our typical open the connection, ExecuteNonQuery and close the connection.
02:58I've also included one more line of code to refresh the DataGrid. The DataGrid
03:04that's on the top of the screen that shows our active authors will now need to
03:08be refreshed, because we just inserted a new author. So let's test this.
03:14So for my new author, we'll do a FirstName of Steven, LastName of Jones, hit the
03:22button, and look at that, in our Active Authors grid, we now see Steven Jones.
03:27So this proves we successfully made a round-trip from the web page, it took the
03:32parameter Steven and the parameter Jones, passed those two parameters to the
03:37stored procedure and the stored procedure executed as desired.
Collapse this transcript
Getting return values
00:00I mentioned earlier to you a recommendation that as a best practice;
00:04every stored procedure return a value indicating success or failure.
00:08Typically, we return a 0 for failure and the 1 for success.
00:12We haven't yet implemented that.
00:14So let's go ahead and work on it.
00:16I'll change this code that creates a stored procedure into a code that alters
00:20a stored procedure.
00:21The last allow will be RETURN 1 for success.
00:26We also need to define some failure condition.
00:28As a hypothetical, we're going to say that if the first name is too short,
00:33let's say extremely short, less than two characters, we'll define that as
00:37a failure condition.
00:38Check for the if len(@FirstName).
00:42If it's less than 2 characters, that is now defined as a failure condition.
00:47So we'll need to RETURN a 0 to indicate this stored procedure was unsuccessful.
00:52And as soon as it hits that line of RETURN 0, it will not execute the bottom.
00:57It will not do the insert.
00:59Command(s) completed successfully. That's good news.
01:01Now we need to go over to our website and do a little more work.
01:06In order to accept that return value we're going to have to create a new parameter.
01:10So websites accept return values from stored procedures as a special type of parameter.
01:15I have some code already written in your exercise files.
01:18I'm going to insert that now.
01:21There is one chunk that goes right before the connection.open and another chunk
01:27they goes right after connection.close.
01:31Now let's look at what this code does.
01:32The top part creates a new parameter called returnParameter, and it sets an
01:37unusual direction on that.
01:39For every parameter we have the choice to set a direction.
01:42Our choices are Input, Output, both Input and Output, or the one I'm going to
01:48choose ReturnValue.
01:50And this line just adds the parameter to the existing commands.
01:55Below the close, I added some code that reads the value of the return value and
02:00checks to see if it's equal to 0.
02:02If it is in fact equal to 0, that is an error condition and I'm going to put
02:06a label on the screen that will hold the message this is an error in the stored procedure.
02:11So I'll need to come back over to the graphical port and drag a Label right
02:16next to the button.
02:17I'll go ahead and run this, and I'm going to intentionally enter some bad data.
02:24So for the first name I'll make sure does in fact too short and we receive the
02:29message there was an error in the stored procedure.
02:32It did not do the insert and instead did what we expected.
02:35It returned a 0 to us indicating the stored procedure had failed.
02:40So this follows a common best practice of using a 0 to indicate failure, a 1 to
02:46indicate success, and every stored procedure should always return either
02:51success or failure.
Collapse this transcript
Conclusion
Next steps
00:00This concludes our course on Microsoft SQL Server Triggers Functions and Stored Procedures.
00:06I want to thank you for your time.
00:08I hope you enjoyed watching this course as much as I enjoyed making it.
00:11I'd like to leave you with a few resources
00:14you can look into if you have further questions about Microsoft SQL Server or
00:18just want to explore the vast world of SQL Server information out there.
00:22The first one I'll recommend to you as Microsoft itself.
00:25Personally, I feel SQL Server is the best documented product I've ever worked with.
00:30So I often visit the Microsoft website, probably on a daily basis;
00:34microsoft.com/sqlserver will take you to the official Microsoft website with
00:40lots of good information directly from Microsoft.
00:42One of the most important areas for beginners is the Learning Center.
00:47Another good resource is SQL Server Central which you can find just at
00:50sqlservercentral.com.
00:53It has lots of good information, mostly developed by a community of SQL Server
00:57developers and practicing DBAs.
00:59Some of the content here does require you to sign up.
01:02It is a free sign up.
01:03I recommend you do that.
01:05I subscribed to a few of their newsletters.
01:07About once a week they'll send you lots of good information, specifically on
01:11SQL Server and also about database administration and database development in general.
01:16The last thing I'd like to recommend to you is my blog which is
01:19windowsdba.blogspot.com.
01:24I maintain a blog about Microsoft SQL Server and also some information about
01:29Microsoft Windows, particularly things that will affect how SQL Server runs and
01:34things that developers and DBAs need to be aware of.
01:38Again, thank you for your time and I wish you the best of luck on your career as
01:42a database developer.
Collapse this transcript


Suggested courses to watch next:

SQL Essential Training (2h 22m)
Bill Weinman

SQL Server 2008 Essential Training (6h 54m)
Simon Allardice


Are you sure you want to delete this bookmark?

cancel

Bookmark this Tutorial

Name

Description

{0} characters left

Tags

Separate tags with a space. Use quotes around multi-word tags. Suggested Tags:
loading
cancel

bookmark this course

{0} characters left Separate tags with a space. Use quotes around multi-word tags. Suggested Tags:
loading

Error:

go to playlists »

Create new playlist

name:
description:
save cancel

You must be a lynda.com member to watch this video.

Every course in the lynda.com library contains free videos that let you assess the quality of our tutorials before you subscribe—just click on the blue links to watch them. Become a member to access all 104,141 instructional videos.

get started learn more

If you are already an active lynda.com member, please log in to access the lynda.com library.

Get access to all lynda.com videos

You are currently signed into your admin account, which doesn't let you view lynda.com videos. For full access to the lynda.com library, log in through iplogin.lynda.com, or sign in through your organization's portal. You may also request a user account by calling 1 1 (888) 335-9632 or emailing us at cs@lynda.com.

Get access to all lynda.com videos

You are currently signed into your admin account, which doesn't let you view lynda.com videos. For full access to the lynda.com library, log in through iplogin.lynda.com, or sign in through your organization's portal. You may also request a user account by calling 1 1 (888) 335-9632 or emailing us at cs@lynda.com.

Access to lynda.com videos

Your organization has a limited access membership to the lynda.com library that allows access to only a specific, limited selection of courses.

You don't have access to this video.

You're logged in as an account administrator, but your membership is not active.

Contact a Training Solutions Advisor at 1 (888) 335-9632.

How to access this video.

If this course is one of your five classes, then your class currently isn't in session.

If you want to watch this video and it is not part of your class, upgrade your membership for unlimited access to the full library of 2,025 courses anytime, anywhere.

learn more upgrade

You can always watch the free content included in every course.

Questions? Call Customer Service at 1 1 (888) 335-9632 or email cs@lynda.com.

You don't have access to this video.

You're logged in as an account administrator, but your membership is no longer active. You can still access reports and account information.

To reactivate your account, contact a Training Solutions Advisor at 1 1 (888) 335-9632.

Need help accessing this video?

You can't access this video from your master administrator account.

Call Customer Service at 1 1 (888) 335-9632 or email cs@lynda.com for help accessing this video.

preview image of new course page

Try our new course pages

Explore our redesigned course pages, and tell us about your experience.

If you want to switch back to the old view, change your site preferences from the my account menu.

Try the new pages No, thanks

site feedback

Thanks for signing up.

We’ll send you a confirmation email shortly.


By signing up, you’ll receive about four emails per month, including

We’ll only use your email address to send you these mailings.

Here’s our privacy policy with more details about how we handle your information.

Keep up with news, tips, and latest courses with emails from lynda.com.

By signing up, you’ll receive about four emails per month, including

We’ll only use your email address to send you these mailings.

Here’s our privacy policy with more details about how we handle your information.

   
submit Lightbox submit clicked