M0194 Web-based Programming Lanjut Session 7 2004 Tau Yenny, SI - Binus 2 Connection, Command dan Procedure The Connection Object The Command Object Stored Procedure Optimization Data Shaping 2004 Tau Yenny, SI - Binus 3 The Connection Object Connection object Gives us connection to the data store Run the commands action queries (updates, inserts, deletes) return a recordset Returning a Recordset To return a recordset use the ‘Execute’ method The syntax is: Connection.Execute CommandText, [RecordsAffected], [Options] 2004 Tau Yenny, SI - Binus 4 The Connection Object Argument Description CommandText The text of the command to execute. This is the same as the ‘Source’ of the Recordset ‘Open’ method, and can also represent an existing Command object. RecordsAffected A variable into which is placed the number of records affected by the command. Options The command options, which can be one or more of the values from the CommandTypeEnum or ExecuteOptionEnum constants, as detailed in session 6. Set conPubs = Server.CreateObject(“ADODB.Connection”) conPubs.Open strConn Set rsAuthors = conPubs.Execute (“Authors”) The difference between Execute and Open method: • Open method have the ability to change the cursor type and lock type • Execute method always get a forward-only cursor and read-only recordset. 2004 Tau Yenny, SI - Binus 5 The Connection Object Action Commands You can use the RecordsAffected argument to find out how many records were affected by the command. Dim strSQL as String Dim lngRecs as Long strSQL = “UPDATE Titles SET Price = Price * 1.10 WHERE Type=‘Business’” conPubs.Execute strSQL, lngRecs, adCmdText Response.Write lngRecs & “ records were updated.” No Recordset Returned If no recordset is being returned, then it’s also best to add another option to the Execute statement : conPubs.Execute strSQL, lngRecs, adCmdText + adExecuteNoRecords 2004 Tau Yenny, SI - Binus 6 The Command Object Command Object Deal with commands of any sort, especially that require parameters. Can run both commands that return recordsets and not return recordsets. If your command doesn’t have parameters, then it doesn’t matter whether you use a Connection, a Command, or a Recordset. Returning Recordsets use the Execute method and the CommandText property. Set cmdAuthors = Server.CreateObject(“ADODB.Command”) cmdAuthors.CommandText = “Authors” Set rsAuthors = cmdAuthors.Execute 2004 Tau Yenny, SI - Binus 7 The Command Object The Execute method also has some optional arguments: Argument Description RecordsAffected A variable into which is placed the number of records affected by the command. Parameters An array of parameter values. Options The command options. This is similar to the ‘Options’ of the Recordset ‘Open’ method. Set cmdAuthors = Server.CreateObject(“ADODB.Command”) cmdAuthors.CommandText = “Authors” cmdAuthors.CommandType = adCmdTable Set rsAuthors = cmdAuthors.Execute Or Set rsAuthors = cmdAuthors.Execute (, , adCmdTable) 2004 Tau Yenny, SI - Binus 8 The Command Object Changing the Cursor Type If require a different cursor or lock type, use the Open method. cmdAuthors.ActiveConnection = strConn cmdAuthors.CommandText = “Authors” cmdAuthors.CommandType = adCmdTable rsAuthors.Open cmdAuthors, , adOpenDynamic, adLockOptimistic Action Command For action commands, such as update data without returning any records: Set cmdUpdate = Server.CreateObject(“ADODB.Command”) StrSQL = “UPDATE Titles SET Price = Proce * 1.10 WHERE Type = ‘Business’” cmdUpdate.ActiveConnection = strConn cmdUpdate.CommandText = strSQL cmdUpdate.CommandType = adCmdText cmdUpdate.Execute , , adExecuteNoRecords 2004 Tau Yenny, SI - Binus 9 Stored Procedures A stored procedures (stored query) is a predefined SQL query stored on the database. The reasons why we create and use a stored procedure: Compiled by database. Produces an execution plan, so the database knows exactly what it’s going to do. This makes the execution of the procedure faster. Stored procedures are often cached by the database, thus making them faster to run. Not all databases support this caching mechanism – Microsoft Access doesn’t, but SQL Server does. More secure by specifying that your database tables can be modified only by stored procedures. Avoid cluttering ASP code with lengthy SQL statements. This makes the ASP code easier to maintain. Keep all the SQL code together, on the server. Can use output parameters, which allows to return both a recordset and other values. 2004 Tau Yenny, SI - Binus 10 Stored Procedures A stored procedure on SQL Server CREATE PROCEDURE usp_UpdatePrices AS UPDATE Titles SET Price = Price * 1.10 WHERE Type = ‘Business’ For a Microsoft Access database, you can create a simple update query to do the same task 2004 Tau Yenny, SI - Binus 11 Stored Procedures To run this stored procedure from an ASP page, you’d simply use the following code: Set cmdUpdate = Server.CreateObject (“ADODB.COmmand”) cmdUpdate.ActiveConnection = strConn cmdUpdate.CommandText = “usp_UpdatePrices” cmdUpdate.CommandType = adCmdStoredProc cmdUpdate.Execute , , adExecuteNoRecords 2004 Tau Yenny, SI - Binus 12 Stored Procedures Parameters Must follow the naming convention for SQL variables, which means they must start with an @ symbol. CREATE PROCEDURE usp_UpdatePrices @Type Char(12), @Percent Money AS UPDATE Titles SET Price = Price * ( 1 + @Percent / 100 ) WHERE Type = @Type 2004 Tau Yenny, SI - Binus 13 Stored Procedures The Parameters Collection Set Parameter = Command.CreateParameter (Name, [Type], [Direction], [Size], [Value]) Argument Description Name The name of the parameter. This isn’t the name of the parameter in the stored procedure, but the name of the parameter in the Parameters collection. It is however, a good idea to use the same names. Type The data type of the parameter. This can be one of the adDataType constants, which are detailed in the appendices. Direction The direction of the parameter, indicating whether the parameter supplies information to the stored procedure, or whether the procedure supplies the information back to ADO. The value can be one of: adParamInput (1), is an input parameter, being sent to the stored procedure. adParamOutput (2), is an output parameter, being retrieved from the stored procedure. adParamInputOutput (3), is both an input and an output parameter. adParamReturnValue (4), holds the return status of the stored procedure. Size The size of the parameter. For fixed length types, such as numbers, this can be omitted. Value The value of the parameter. 2004 Tau Yenny, SI - Binus 14 Stored Procedures Once the parameter is created it can be appended to the Parameters collection. Set parValue = cmdUpdate.CreateParameter (“@Type”, adVarWChar, adParamInput, 12, “Business”) cmdUpdate.Parameters.Append parValue Set parValue = cmdUpdate.CreateParameter (“@Percent”, adCurrency, adParamInput, ,10) cmdUpdate.Parameters.Append parValue cmdUpdate.Parameters(“@Percent”) = 10 If you don’t want to create a variable, you can also take a shortcut : cmdUpdate.Parameters.Append = _ cmdUpdate.CreateParameter (“@Type”, adVarWChar, adParamInput, 12, “Business”) cmdUpdate.Parameters.Append = _ cmdUpdate.CreateParameter (“@Percent”, adCurrency, adParamInput, ,10) cmdUpdate.Parameters(“@Percent”) = 10 The Parameters in the Parameters collection must match the order of the parameters in the stored procedure. 2004 Tau Yenny, SI - Binus 15 Stored Procedures 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. <HTML><HEAD><TITLE>Stored Procedure with Parameter</TITLE></HEAD><!-- UpdatePrices.asp --> <BODY> <!-- #include file="dataconn.inc" --> <FORM NAME="UpdatePrices" Method="Post" ACTION="StoredProcedure.asp"> <TABLE> <TR><TD>Book Type:</TD> <TD><SELECT NAME="lstTypes"> <% Dim rsTypes Dim strSQL Dim strQuote 12. 13. 14. 15. strQuote = Chr(34) 'Predefined the quote character Set rsTypes = Server.CreateObject("ADODB.Recordset") strSQL = "SELECT DISTINCT type FROM titles" rsTypes.Open strSQL, Conn 16. 17. 18. 19. While Not rsTypes.EOF Response.Write "<OPTION VALUE=" & strQuote & rsTypes("Type") & strQuote & ">" & rsTypes("Type") rsTypes.MoveNext Wend 20. 21. 22. 23. 24. 25. 26. 27. rsTypes.Close Set rsTypes = Nothing %></SELECT></TD></TR> <TR><TD>Percent Value</TD> <TD><INPUT NAME="txtPercent" TYPE="TEXT"></TD></TR> </TABLE> <P><INPUT TYPE="Submit" VALUE="Run Query"> </FORM></BODY></HTML> 2004 Tau Yenny, SI - Binus 16 Stored Procedures 1. 2. 3. 4. 5. 6. 7. <!-- #include file="dataconn.inc" --> <!-- StoredProcedure.asp --> <% Dim cmdUpdate Dim lngRecs Dim strType Dim curPercent 8. 9. 10. 'get from the values strType = Request.Form("lstTypes") curPercent = Request.Form("txtPercent") 11. 12. 'Tell the user what's being done Response.Write "Updating all books of type <B>" & strType & "</B> by " & curPercent & "%<P>" 13. Set cmdUpdate = Server.CreateObject("ADODB.Command") 14. 15. 16. 17. 18. 19. 20. 21. 22. ' Set the properties of the command With cmdUpdate .ActiveConnection = conn .CommandText = "usp_UpdatePrices" .CommandType = 4 ‘adCmdStoredProc = 4 .Parameters.Append .CreateParameter("@Type", 202, 1, 12, strType) ‘adVarWChar = 202, adParamInput=1 .Parameters.Append .CreateParameter("@Percent", 6, 1,, curPercent) ‘adCurrency = 6 .Execute lngRecs,,128 ‘adExecuteNoRecords=128 End With 23. 24. 25. 26. 'And finally tell the user what's happened Response.Write "Procedure complete. " & lngRecs & " records were updated." Set cmdUpdate = Nothing %> 2004 Tau Yenny, SI - Binus 17 Stored Procedures 2004 Tau Yenny, SI - Binus 18 Stored Procedures Passing Parameters as an Array Utilizes the Array function, which turns individual variables into an array, suitable for passing into this method call. Some disadvantages to this method: You can only use input parameters. This method is slower if you intend to call the stored procedure several times, since ADO will ask the data store what parameters are, and what data types they use. Set cmdUpdate = Server.CreateObject(“ADODB.Command”) With cmdUpdate .ActiveConnection = conn .CommandText = “usp_UpdatePrices” .CommandType = adCmdStoredProc ‘Execute the command .Execute lngRecs, Array(strType, curPercent), adExecuteNoRecords End With 2004 Tau Yenny, SI - Binus 19 Stored Procedures Output Parameters If you want more information, but still don’t want to return a recordset, you can define a parameter as an output parameter. CREATE PROCEDURE usp_UpdatePricesMax @Type Char(12), @Percent Money, @Max Money OUTPUT AS UPDATE Titles SET Price = Price * ( 1 + @Percent / 100 ) WHERE Type = @Type SELECT @Max = MAX(Price) FROM Titles 2004 Tau Yenny, SI - Binus 20 Stored Procedures 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. <!-- #include file="dataconn.inc" --> <!-- StoredProcedureMax.asp --> <% Dim cmdUpdate Dim lngRecs Dim strType Dim curPercent Dim curMax 'get from the values strType = Request.Form("lstTypes") curPercent = Request.Form("txtPercent") 11. 12. 'Tell the user what's being done Response.Write "Updating all books of type <B>" & strType & "</B> by " & curPercent & "%<P>" 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. Set cmdUpdate = Server.CreateObject("ADODB.Command") ' Set the properties of the command With cmdUpdate .ActiveConnection = conn .CommandText = "usp_UpdatePricesMax" .CommandType = 4 ‘adCmdStoredProc = 4 .Parameters.Append .CreateParameter("@Type", 202, 1, 12, strType) ‘adVarWChar = 202, adParamInput=1 .Parameters.Append .CreateParameter("@Percent", 6, 1,, curPercent) ‘adCurrency = 6 .Parameters.Append .CreateParameter("@Max", 6, 2) ‘adCurrency = 6, adParamOutput=2 .Execute lngRecs,,128 ‘adExecuteNoRecords=128 curmax = .Parameters(“@Max”) ‘Extract the OUTPUT parameter End With 'And finally tell the user what's happened Response.Write "Procedure complete. " & lngRecs & " records were updated.“ Response.Write "The highest price book is now " & FormatCurrency(curMax) Set cmdUpdate = Nothing %> 2004 Tau Yenny, SI - Binus 21 Stored Procedures 2004 Tau Yenny, SI - Binus 22 Stored Procedures Return Values Return values from functions are handled differently from the way return values from stored procedures. In user functions, we often return a Boolean value to indicate the success or failure of a function When calling a stored procedure though, we can’t use the same method. The stored procedure are run using the Execute method, and this returns a recordset. For example, consider adding a new employee to the employee table. You don’t want to stop two people with the same name being added, but you might want this situation flagged. Here we can use a return value, to indicate whether an employee wuth the same name already exists. 2004 Tau Yenny, SI - Binus 23 Stored Procedures CREATE PROCEDURE usp_AddEmployee @Emp_ID Char(9), @FName Varchar(20), @MInit Char(1), @LName Varchar(30), @Job_Id SmallInt, @Job_Lvl TinyInt, @Pub_ID Char(4), @Hire_Date Datetime AS BEGIN DECLARE @Exists Int -- Return Value -- See if an employee with the same name exists IF EXISTS (SELECT * FROM Employee WHERE FName = @FName AND MInit = @MInit AND LName = @LName) SELECT @Exists = 1 ELSE SELECT @Exists = 0 INSERT INTO Employee (emp_id, fname, minit, lname, job_id, job_lvl, pub_id, hire_date) VALUES (@Emp_ID, @FName, @MInit, @LName, @Job_Id, @Job_Lvl, @Pub_ID, @Hire_Date) RETURN @Exists END GO 2004 Tau Yenny, SI - Binus 24 Stored Procedures 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. <HTML><HEAD><TITLE>Stored Procedure with Return Values</TITLE></HEAD><!-- ReturnValues.asp --> <BODY><!-- #include file="dataconn.inc" --> <H1>Retuen Values from stored procedures<HR></H1> <FORM NAME="ReturnValues" Method="Post" ACTION="StoredProcedureAdd.asp"> <TABLE> <TR><TD>Employee ID:</TD> <TD><INPUT NAME="txtEmp_ID" TYPE="TEXT"></TD></TR> <TR><TD>First Name:</TD> <TD><INPUT NAME="txtFName" TYPE="TEXT"></TD></TR> <TR><TD>Initial:</TD> <TD><INPUT NAME="txtMInit" TYPE="TEXT"></TD></TR> <TR><TD>Last Name:</TD> <TD><INPUT NAME="txtLName" TYPE="TEXT"></TD></TR> <TR><TD>Job:</TD><TD> <SELECT NAME="lstJob"> <% Dim rsJobs Dim strSQL Dim strQuote 15. 16. 17. 18. strQuote = Chr(34) 'Predefined the quote character Set rsJobs = Server.CreateObject("ADODB.Recordset") strSQL = "SELECT DISTINCT job_id, job_desc FROM jobs" rsJobs.Open strSQL, Conn 19. 20. 21. 22. 23. While Not rsJobs.EOF Response.Write "<OPTION VALUE=" & strQuote & _ rsJobs("job_id") & strQuote & ">" & rsJobs("job_desc") rsJobs.MoveNext Wend 24. 25. 26. rsJobs.Close Set rsJobs = Nothing %></SELECT></TD></TR> 2004 Tau Yenny, SI - Binus 25 Stored Procedures 27. <TR><TD>Job Level: </TD><TD><INPUT NAME="txtJob_Lvl" TYPE="TEXT"></TD></TR> 28. <TR><TD>Publisher: </TD><TD><SELECT NAME="lstPub"> 29. <% 30. Dim rsPub 31. 32. 33. Set rsPub = Server.CreateObject("ADODB.Recordset") strSQL = "SELECT DISTINCT pub_id, pub_name FROM publishers" rsPub.Open strSQL, Conn 34. 35. 36. 37. 38. While Not rsPub.EOF Response.Write "<OPTION VALUE=" & strQuote & _ rsPub("pub_id") & strQuote & ">" & rsPub("pub_name") rsPub.MoveNext Wend 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. rsPub.Close Set rsPub = Nothing %></SELECT></TD></TR> <TR><TD>Hire Date: </TD> <TD><INPUT NAME="txtHire_Date" TYPE="TEXT" Value="<%= FormatDateTime(date()) %>"></TD> </TR> </TABLE> <P> <INPUT TYPE="Submit" VALUE="Run Query"> </FORM> </BODY> </HTML> 2004 Tau Yenny, SI - Binus 26 Stored Procedures 2004 Tau Yenny, SI - Binus 1. 2. 3. 4. 5. 6. 7. 8. 9. 27 <!-- #include file="dataconn.inc" --><!-- StoredProcedureAdd.asp --> <% Dim cmdEmployee Dim lngRecs Dim lngAdded Set cmdEmployee = Server.CreateObject("ADODB.Command") With cmdEmployee .ActiveConnection = conn .CommandText = "usp_AddEmployee" .CommandType = 4 10. 11. 12. 13. 14. 15. 16. 17. 18. .Parameters.Append .CreateParameter("RETURN_VALUE", 3, 4) .Parameters.Append .CreateParameter("@Emp_ID", 129, 1, 9) .Parameters.Append .CreateParameter("@FName", 202, 1,20) .Parameters.Append .CreateParameter("@MInit", 129, 1, 1) .Parameters.Append .CreateParameter("@LName", 202, 1,30) .Parameters.Append .CreateParameter("@Job_Id", 2, 1) .Parameters.Append .CreateParameter("@Job_Lvl", 17, 1) .Parameters.Append .CreateParameter("@Pub_ID", 129, 1, 4) .Parameters.Append .CreateParameter("@Hire_Date", 135, 1,8) 19. 20. 21. 22. 23. 24. 25. 26. .Parameters("@Emp_ID") = Request.Form("txtEmp_ID") .Parameters("@FName") = Request.Form("txtFName") .Parameters("@MInit") = Request.Form("txtMInit") .Parameters("@LName") = Request.Form("txtLName") .Parameters("@Job_Id") = Request.Form("lstJob") .Parameters("@Job_Lvl") = Request.Form("txtJob_Lvl") .Parameters("@Pub_ID") = Request.Form("lstPub") .Parameters("@Hire_Date") = Request.Form("txtHire_Date") 27. 28. 29. 30. 31. 32. 33. 34. 35. %> .Execute lngRecs,,128 lngAdded = .Parameters("RETURN_VALUE") End With Response.Write "New Employee added.<P> " If lngAdded = 1 Then Response.Write "An Employee with the same name already exists." End If Set cmdEmployee = Nothing 2004 Tau Yenny, SI - Binus 28 Stored Procedures 2004 Tau Yenny, SI - Binus 29 Stored Procedures Refreshing Parameters Instead of typing in all of the parameter details yourself, ADO can do it for you, simply by calling the Refresh method . But be aware that it imposes a performance penalty, since ADO must query the provider for the details of the parameters for the stored procedure. 1. 2. 3. 4. With cmdEmployee .ActiveConnection = conn .CommandText = "usp_AddEmployee" .CommandType = 4 5. .Parameters.Refresh 6. 7. 8. 9. 10. 11. 12. 13. .Parameters("@Emp_ID") = Request.Form("txtEmp_ID") .Parameters("@FName") = Request.Form("txtFName") .Parameters("@MInit") = Request.Form("txtMInit") .Parameters("@LName") = Request.Form("txtLName") .Parameters("@Job_Id") = Request.Form("lstJob") .Parameters("@Job_Lvl") = Request.Form("txtJob_Lvl") .Parameters("@Pub_ID") = Request.Form("lstPub") .Parameters("@Hire_Date") = Request.Form("txtHire_Date") 14. 15. 16. .Execute lngRecs,,128 lngAdded = .Parameters("RETURN_VALUE") End With 2004 Tau Yenny, SI - Binus 30 Optimization General ADO Tips Pick only the columns you need Use stored procedures as much as possible Use stored procedures for data changes Don’t create a recordset unless it’s required Use the appropriate cursor and lock modes Object Variables One guaranteed way to improve performance whilst looping through recordset is to use object variables 2004 Tau Yenny, SI - Binus 31 Optimization Cache Size Cache size is the number of records that ADO reads at a time from the data sore, and it defaults to 1. The size 1 means, every time you move to another record, the record must be fetched from the data store. Increasing the size of the cache to 10, for example, would mean that records are read into the ADO buffer 10 at a time. Set the size of the cache by using the CacheSize property : rsAuthors.CacheSize = 10 2004 Tau Yenny, SI - Binus 32 Data Shaping Allows to represent a tree-like structure or related recordset. Reasons why this is useful: Performance : When used correctly, data shaping can improve performance Convenience : It’s extremely easy to map the parent/child relationship in data shaping. Using data shaping Use the MSDataShape OLEDB Provider Use a special Shape language, a superset of SQL, that allows you to construct the hierarchies 2004 Tau Yenny, SI - Binus 33 Data Shaping The Connection String Provider=MSDataShape; Data Provider = SQLOLEDB; Data Source=… The Shape Language SHAPE {parent command} [AS parent alias] APPEND ({child command} [AS child alias] RELATE parent_column TO child_column) [AS parent_column_name] For Example: SHAPE {SELECT * FROM Publishers } APPEND ({SELECT * FROM Titles} RELATE Pub_ID TO Pub_ID) AS rsTitles 2004 Tau Yenny, SI - Binus 1. 2. 3. 4. 5. 6. 34 <!-- #include file="dataconn.inc" --><!-- DataShape.asp --> <% Dim rsPublishers Dim rsTitles Dim strShapeConn Dim strShape Data Shaping 7. Set rsPublishers = Server.CreateObject("ADODB.Recordset") 8. 9. strShapeConn = "Provider = MSDataShape; Data Provider = SQLOLEDB; Data Source= Hogwartz; " & _ " Initial Catalog= pubs; User ID= sa; Password= letmein" 10. 11. strShape = "SHAPE {SELECT * FROM Publishers } APPEND ({SELECT * FROM Titles} " & _ " RELATE Pub_ID TO Pub_ID) AS rsTitles " 12. rsPublishers.Open strShape, strShapeConn 13. 14. 15. 16. 'Loop through the publishers Response.Write "<UL>" While Not rsPublishers.EOF Response.Write "<LI>" & rsPublishers("Pub_Name") 17. 18. 19. 'Now the titles Response.Write "<UL>" Set RsTitles = rsPublishers("rsTitles").Value 20. 21. 22. 23. 24. 25. 'Loop through the titles While Not rsTitles.EOF Response.Write "<LI>" & rsTitles("title") rsTitles.MoveNext Wend Response.Write "</UL>" 26. 27. 28. 29. 'Move to the next publishers rsPublishers.MoveNext 30. 31. 32. 33. Wend Response.Write "</UL>" rsPublishers.Close Set rsPublishers = Nothing Set rsTitles = Nothing %> 2004 Tau Yenny, SI - Binus 35 Data Shaping 2004 Tau Yenny, SI - Binus