6.8 CreateandCall SQL Server2000 User-Defined Functions In SQLServer 2000, I have heard that you can createuser-defined functions (UDFs). Where would you use UDFs, and how do you createandcall them from within T-SQL? Technique UDFs have been used for years in application development languages. You can now create them in SQLServer2000 as well. Creating SQLServer2000 UDFs You can create UDFs in SQLServer2000 by using the CREATE FUNCTION command. Normally, you would do this using the Enterprise Manager or some tool, but here you will learn how to do it using VB.NET. Following is the function that will be created: CREATE FUNCTION udf_ShowProdAndCat (@UnitPriceParm money) RETURNS @ProdAndCatTab TABLE ( ProductID int, ProductName nvarchar(80), CategoryName nvarchar(80), UnitPrice int ) AS BEGIN INSERT @ProdAndCatTab SELECT P.ProductID, P.ProductName, C.CategoryName, P.UnitPrice FROM Products AS P INNER JOIN Categories AS C ON P.CategoryID = C.CategoryID WHERE P.UnitPrice > @UnitPriceParm RETURN END This function definitely looks a lot different from functions you have created in other languages, but it doesn't look as funky when you remember you are using T-SQL commands. Passing Parameters to SQLServer UDFs The parameter that is passed starts with the @ symbol, much like local variables that were discussed in How-To 6.1. You will also want to declare the data type. Returning Scalar or Table Types from SQLServer UDFs When returning values from a UDF, you will either pass back a scalar type, which is actually a single value of one of the standard data types, or pass back a new Table data type. The example for this How-To creates and returns a Table data type, specified with the following lines of code: RETURNS @ProdAndCatTab TABLE ( ProductID int, ProductName nvarchar(80), CategoryName nvarchar(80), UnitPrice int ) By including the opening and closing parentheses, you can specify and return an entire table's worth of data, but be careful not to because performance would not be good. This is the same as it would be using SQLServer data. You can then use this table that is returned in another T-SQL statement. After establishing the return value, in this case the table ProdAndCatTab, you need to create the body of code for the UDF. Note Although this return value has been called ProdAndCatTab, there is not going to be a table that you can access outside the function by that name. It will just be strictly for use in the calling statement. Formatting the Body of Code for SQLServer UDFs You can see from the block of code that follows that you need to have a BEGIN and END statement: AS BEGIN INSERT @ProdAndCatTab SELECT P.ProductID, P.ProductName, C.CategoryName, P.UnitPrice FROM Products AS P INNER JOIN Categories AS C ON P.CategoryID = C.CategoryID WHERE P.UnitPrice > @UnitPriceParm RETURN END Notice also that you will have INSERT @ProdAndCatTab and RETURN statements in there to create the Table return value. The rest of the code is much the same as other T- SQL statements. Calling SQLServer2000 UDFs You can call UDFs from other T-SQL Statements, as displayed here for this How-To: Select * From udf_ShowProdAndCat(" & Me.txtUnitPrice.Text & ")" There, the UDF is called in a SELECT statement, and the parameter is passed. Steps Open and run the VB.NET -Chapter 6 solution. From the main form, click on the button with the caption How-To 6.8 (see Figure 6.9). Figure 6.9. A common problem with inner joins is retrieving multiple records when you want to see only one per occurrence. You will see the UDF described in the "Technique" section in a label. Click the button labeled Create UDF. If the UDF already exists, then a message box will tell you so. Otherwise, the UDF is created. Next, click the button labeled Use UDF. The data grid is then filled and the data is displayed. You can change the value in the Products Greater Than text box. Then click Use UDF again to see the new data displayed. 1. Create a Windows Form. Then place the controls listed in Table 6.8 with the following properties set, as displayed in Figure 6.9. Table 6.8. Control Property Settings for This How-To Object Property Setting Label Text Report Products Greater Than: TextBox Name txtUnitPrice Label Text SQL Statement Creating Temporary Table Label Name lblCreateUDF Button Name btnCreateUDF Text Create UDF Label Text SQL Statement Using UDF Label Name lblUseUDF Button Name btnUseUDF Text Use UDF Label Text Results DataGrid Name dgResults 2. Add the code in Listing 6.18 to the Load event of the form. (Double-click on the form to bring up the code.) Listing 6.18 frmHowTo6_8.vb: Create the UDF Code, and Assign It to a Label for Display and Use Later Private Sub frmHowTo6_8_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load '-- Create the UDF string Dim strSQL As String strSQL = "CREATE FUNCTION udf_ShowProdAndCat ( @UnitPriceParm money)" strSQL &= "RETURNS @ProdAndCatTab TABLE" & vbCrLf strSQL &= "(" & vbCrLf strSQL &= " ProductID int," & vbCrLf strSQL &= " ProductName nvarchar(80)," & vbCrLf strSQL &= " CategoryName nvarchar(80)," & vbCrLf strSQL &= " UnitPrice int" & vbCrLf strSQL &= ")" & vbCrLf strSQL &= "AS" & vbCrLf strSQL &= "BEGIN" & vbCrLf strSQL &= " INSERT @ProdAndCatTab" & vbCrLf strSQL &= " SELECT P.ProductID, P.ProductName," & vbCrLf strSQL &= " C.CategoryName, P.UnitPrice" & vbCrLf strSQL &= " FROM Products AS P INNER JOIN Categories AS C" & _ vbCrLf strSQL &= " ON P.CategoryID = C.CategoryID" & vbCrLf strSQL &= " WHERE P.UnitPrice > @UnitPriceParm" & vbCrLf strSQL &= " RETURN" & vbCrLf strSQL &= "END" Me.lblCreateUDF.Text = strSQL '-- Create the SQL string that calls the UDF Me.lblUseUDF.Text = "Select * From udf_ShowProdAndCat(" & _ Me.txtUnitPrice.Text & ")" End Sub 3. Add the code in Listing 6.19 to the Click event of btnCreateUDF. This code uses Connection and Command objects to create the UDF based on the code that is provided. Listing 6.19 frmHowTo6_8.vb: Creating the New UDF in SQLServer Private Sub btnCreateUDF_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCreateUDF.Click Try Dim ocnn As New OleDb.OleDbConnection(BuildCnnStr("(local)", _ "Northwind")) Dim ocmd As New OleDb.OleDbCommand(Me.lblCreateUDF.Text) ocmd.Connection = ocnn ocnn.Open() ocmd.ExecuteNonQuery() ocnn.Close() Catch excp As Exception MessageBox.Show(excp.Message) Exit Sub End Try MessageBox.Show("UDF Created") End Sub 4. Add the code in Listing 6.20 to the TextChanged event of the button txtUnitPrice. Listing 6.20 frmHowTo6_8.vb: Updating the SELECT Statement That Is Calling the UDF Private Sub txtUnitPrice_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtUnitPrice.TextChanged Me.lblUseUDF.Text = "Select * From udf_ShowProdAndCat(" & _ Me.txtUnitPrice.Text & ")" End Sub 5. Add the code in Listing 6.21 to the Click event of the button btnUseUDF. This code fills a dataset based on the SELECT statement that calls the UDF. The code then assigns the dataset to the DataSource property of dgResults. Listing 6.21 Displaying Data Using the SELECT Statement in the Text Property of lblUseUDF Private Sub btnUseUDF_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnUseUDF.Click Dim dtResults As New DataTable() Try '-- Use the SQL String to build the data adapter ' and fill the data table. Dim odaResults As New OleDb.OleDbDataAdapter(Me.lblUseUDF.Text, BuildCnnStr("(local)", "Northwind")) odaResults.Fill(dtResults) Catch excp As Exception MessageBox.Show(excp.Message) Exit Sub End Try '-- Assign the data table to the data grid's DataSource property. Me.dgResults.DataSource = dtResults End Sub Comments When you have to use the same T-SQL statements repeatedly, it is handy to be able to store that code somewhere, just like you can do with UDFs you create in Visual Basic. When using UDFs, you can use the value inline and save a number of steps when creating your T-SQL routines. . 6.8 Create and Call SQL Server 2000 User-Defined Functions In SQL Server 2000, I have heard that you can create user-defined functions. create them in SQL Server 2000 as well. Creating SQL Server 2000 UDFs You can create UDFs in SQL Server 2000 by using the CREATE FUNCTION command. Normally,