Nielsen c38.tex V4 - 07/21/2009 2:15pm Page 872 Part V Data Connectivity When you link to a SQL Server table in Access, Access caches connection information and metadata. If you make schema changes in SQL Server, the cached metadata will be invalid, and subsequent attempts to open the linked table will fail. A common technique to avoid this fate is to delete all links when you close the Access application, and relink tables on startup. When writing VBA code in Access, ADO (ActiveX Data Objects) is the preferred object model for working with SQL Server. However, the DAO (Data Access Objects) object model is more efficient and full-featured for working with Access objects, and tables linked to SQL Server are Access objects. So although you could use ADOX code to create links, the code presented in this chapter uses DAO. The DAO object model enables you to manipulate tables using the DAO.Database and DAO.TableDef objects. The following VBA function takes input parameters for the name of the linked table as it will appear in Access (you can specify any legal Access object name here), the name of the source table in SQL Server, and an ODBC connection string. The code c hecks to see if the linked table already exists in the local database’s TableDefs collection; if it does, it deletes it and refreshes the collection. The code then c reates a new TableDef object, using the connection string to connect to SQL Server and specifying the source table. The code appends the new TableDef to the TableDefs collection: Public Function LinkTableDAO( _ LinkedTableName As String, _ SourceTableName As String, _ ConnectionString As String) As Boolean ‘ Links or re-links a single table. ‘ Returns True or False based on Err value. Dim db As DAO.Database Dim tdf As DAO.TableDef On Error Resume Next Set db = CurrentDb ‘ Check to see if the table link already exists; ‘ if so, delete it Set tdf = db.TableDefs(LinkedTableName) If Err.Number = 0 Then db.TableDefs.Delete LinkedTableName db.TableDefs.Refresh Else ‘ Ignore error and reset Err.Number = 0 End If Set tdf = db.CreateTableDef(LinkedTableName) ‘ Set the Connect and SourceTableName ‘ properties to establish the link tdf.Connect = ConnectionString 872 www.getcoolebook.com Nielsen c38.tex V4 - 07/21/2009 2:15pm Page 873 Access as a Front End to SQL Server 38 tdf.SourceTableName = SourceTableName ‘ Append to the database’s TableDefs collection db.TableDefs.Append tdf LinkTableDAO = (Err = 0) End Function Caching data in local tables using pass-through queries You can also easily create a routine to cache data in local tables that can be used as the source for combo boxes or other controls. Data can be refreshed when the application starts up, or on demand. A pass-through query is not parsed or processed by Access or ODBC. It is passed directly to SQL Server for processing, which means it must b e written using valid Transact-SQL syntax. Pass-through queries have a Returns Records property that you must set to Yes if you expect a result set. To create a pass-through query in the Access 2007 user interface, execute the following steps: 1. Select the Create tab on the Ribbon. 2. Click the Query Design option in the Other section on the far right of the Ribbon. 3. When the Query Designer loads, click close. 4. At the far left, click SQL and type in your Transact-SQL SELECT statement. You can also manipulate pass-through queries in code using a DAO.QueryDef object. The following procedure takes the name of the saved query that you want to modify, the SQL statement, the connec- tion string, and a Boolean indicating whether the QueryDef will return records or not. The code sets the various properties of the QueryDef object: Public Sub PassThroughFixup( _ strQdfName As String, _ strSQL As String, _ strConnect As String, _ fRetRecords As Boolean = True) Dim db As DAO.Database Dim qdf As DAO.QueryDef Set db = CurrentDb Set qdf = db.QueryDefs(strQdfName) If Len(strSQL) > 0 Then qdf.SQL = strSQL End If If Len(strConnect) > 0 Then qdf.Connect = strConnect End If qdf.ReturnsRecords = fRetRecords qdf.Close Set qdf = Nothing End Sub 873 www.getcoolebook.com Nielsen c38.tex V4 - 07/21/2009 2:15pm Page 874 Part V Data Connectivity Once you have specified the Transact-SQL statement for the pass-through query, it can be used as the record source for a form or report, or invoked from another query. To insert the result set from a pass- through query directly into a local table, create an Access append ( INSERT) query that uses the pass-through query as its data source: INSERT INTO [LocalTableName] ( ColumnName ) SELECT ColumnName FROM [NameOfPassThroughQuery]; You can invoke the whole process from VBA code, which can run on startup or on demand. The fol- lowing routine uses the Execute method of the DAO.Database object to delete data from an existing table and then execute an Access append query to insert the refreshed data: Public Sub RefreshLocal() Dim db As DAO.Database Set db = CurrentDb ‘ Delete existing data db.Execute "DELETE * FROM LocalTableName" ‘ Run the append query db.Execute "AppendFromPassthroughQuery" End Sub Extending the power of pass-through queries using table-valued parameters (TVPs) Table-valued parameters (TVPs) are useful for marshalling multiple rows of data from a client application to SQL Server without requiring multiple round-trips or special server-side logic for processing the data. Normally you would work with TVPs directly in Transact-SQL code, o r by using either ADO.NET or SQL Server Native Client objects. In ADO.NET, the SqlParameter class has been extended to take a DataTable object as a value. The SQL Server Native Client OLE DB API accomplishes the same thing by leveraging the COM IRowset interface along with a new implementation that allows buffering. The downside for Access developers is that the ADO API has not been updated to support TVPs directly through ADO Parameter objects. Unless you want to p rogram directly against the SQL Server Native Client API by declaring a nd calling API functions, that leaves you with a single option: pass-through queries running Transact-SQL, which you can modify programmatically using a DAO QueryDef object. You’ve seen how pass-through queries can return data, but that feature is not available with TVPs — you must set the ReturnsRecords property to No or Access will raise an error. Unfor- tunately, this means that you will be unable to return any information whatsoever through the pass-through query mechanism. You will thus be unable to determine whether a transaction succeeded, get error information, or retrieve new identity values for inserted data. You need to devise other methods of determining the success or failure of the operation. In addition, you need to test and debug your Transact-SQL syntax using SQL Server Management Studio. The following example is extracted from the white paper ‘‘Using SQL Server 2008 Table-valued Parameters in Access 2007.’’ See http://msdn.microsoft.com/en-us/library/dd721896.aspx. 874 www.getcoolebook.com Nielsen c38.tex V4 - 07/21/2009 2:15pm Page 875 Access as a Front End to SQL Server 38 The first step is to create the table-valued parameter type in SQL Server. This is the structure that holds the rows: Use Northwind GO CREATE TYPE dbo.CategoryTableType AS TABLE ( CategoryName nvarchar(15), CategoryDescription ntext ) GO Then you create the stored procedure that takes the new table type as an input parameter. Even though Access can’t process the output parameter shown here, the assumption is that you can use the same stored procedure with clients that can, such as SqlClient. Note also that SET NOCOUNT ON is the first statement in the body of the stored procedure (this is important for client applications that cannot process multiple result sets, such as Access): CREATE PROCEDURE dbo.usp_InsertCategory (@tvpNewCategories dbo.CategoryTableType READONLY, @ReturnMessage nvarchar(255) = NULL OUTPUT) AS SET NOCOUNT ON BEGIN TRY BEGIN TRAN INSERT INTO dbo.Categories (CategoryName, Description) SELECT CategoryName, CategoryDescription FROM @tvpNewCategories IF @@ROWCOUNT = 0 RAISERROR (’No Categories inserted.’, 16, 1) COMMIT SELECT @ReturnMessage=’Categories inserted.’; END TRY BEGIN CATCH IF @@TRANCOUNT > 0 ROLLBACK SELECT @ReturnMessage = ERROR_MESSAGE() + ‘ Severity=’ + CAST(ERROR_SEVERITY() AS nvarchar(2)) END CATCH GO In Access, create a pass-through query and set the ReturnsRecords property to No. You can test by pasting the following Transact-SQL statements into the SQL pane of the query window and setting the Connect property to a valid connection string or DSN: DECLARE @ReturnMessage nvarchar(255) DECLARE @catType CategoryTableType INSERT INTO @catType EXEC (’ SELECT ‘’Organic’’, ‘’Organically grown produce and grains’’ SELECT ‘’Conventional’’, ‘’Non-organically grown produce and grains’’ 875 www.getcoolebook.com Nielsen c38.tex V4 - 07/21/2009 2:15pm Page 876 Part V Data Connectivity SELECT ‘’Irish’’, ‘’Mrs. O’’’’Leary’’’’s creamery products’’ ’) EXEC dbo.usp_InsertCategory @catType, @ReturnMessage OUTPUT; SELECT @ReturnMessage as ReturnMessage You need to handle the string processing in your VBA code to avoid syntax errors with apostrophes and single quotes using the VBA Replace function. Packaging up the multiple rows in your VBA code requires a fair amount of work, but the added efficiency of processing multiple rows at once may be worth it for some scenarios. Monitoring and Troubleshooting A major cause of query performance degradation is that a query involving very large tables can require that all of the data from one or more tables be downloaded to the client. This occasionally happens, even when joins or criteria appear to limit the result set to a small number of records, if the Access database engine determines that it cannot submit the entire query to SQL Server in one call. Instead, it submits multiple queries which sometimes request all of the rows in a table, and then it combines or filters data on the client. If any of the criteria in a query require local processing, such as invoking Access expressions or VBA functions, then even single-call queries that should return only selected rows can require all of the rows in the table to be returned for local processing of the criteria. There are two tools you can use to mon- itor and troubleshoot the commands that Access is submitting to SQL Server: SQL Server Profiler and ODBC Trace. SQL Server Profiler is indispensable for understanding the interaction between your Access front end and SQL Server. Selecting a Profiler template that shows Transact-SQL statements being processed by the server enables you to analyze the commands that Access is submitting. SQL Server Profiler is described in detail in Chapter 56, ‘‘Tracing and Profiling.’’ You can also enable ODBC Trace to log queries submitted to any ODBC data source, which is useful for tracing Access database engine behavior. The most comprehensive information describing how Access interacts with SQL Server — and how to work with SQL Server Profiler and ODBC Trace — is contained in the white paper ‘‘Optimizing Microsoft Office Access Applications Linked to SQL Server,’’ which can be found at http://msdn.microsoft.com/en-us/library/bb188204.aspx. Ad Hoc Querying and Reporting If you are familiar only with earlier versions of Access, Access 2007 may come as a surprise. The user interface has been completely rewritten with the goal of making Access easier to use for business users who are not developers or database professionals. When you launch Access 2007 for the first time, you will see a link to the Guide to the Access 2007 User Interface, or you can launch it directly from http://office.microsoft.com/en-us/access/HA100398921033.aspx. The remainder of this section assumes that you are familiar with the basic features of the new user interface, and jumps directly into using them to access SQL Server data. 876 www.getcoolebook.com Nielsen c38.tex V4 - 07/21/2009 2:15pm Page 877 Access as a Front End to SQL Server 38 Access 2007 makes it extremely easy for power users to create their own queries and reports, and with a minimal amount of time and effort a developer can quickly cobble together forms and reports using the built-in wizards and toolbars. For more comprehensive solutions, download one of the Access templates from the Access download center. Although Access 2007 is optimized around the Access Database Engine (ACE), you can easily switch the data store to SQL Server, as discussed earlier in this chapter. Pre-aggregating data on the server In many situations it will not be desirable for users to link directly to tables. In those situations, you can create views or stored procedures to filter or pre-aggregate data so that users do not have to create queries involving joins or aggregate functions. If you have large tables, you can also create separate ‘‘reporting tables’’ and export data from the base tables at regular i ntervals. In some situations you might want to export data to an Access database engine table, which is easily done from Access by using append queries or by importing into new tables. If your database is locked down and the base tables are not directly accessible, then exporting data to a separate database or invoking stored procedures from pass-through queries are also options. Sorting and filtering data Access 2007 introduces context-sensitive sorting and filtering, which can be a powerful tool for users who are unaccustomed to writing queries. Once the tables or views are linked in Access, you can open them in datasheet view and work with the data interactively using the right-click menus and the Ribbon, which is shown in Figure 38-2. FIGURE 38-2 Filtering and sorting options are on the Home tab of the Ribbon. However, instead of using the Ribbon, it’s often easier to use the right-click menus to access sorting and filtering. Figure 38-3 shows how you can quickly sort the Sales.vSalesPersonSalesByFiscalYears view from AdventureWorks2008 in datasheet view after right-clicking on the column head SalesTerritory. When filtering text data, the actual value is loaded into the filter options, as shown in Figure 38-4. You can further refine the filter with partial string values. For example, you could specify ‘‘Tool’’ in the Does Not Begin With dialog, which loads if that option is selected in the far-right fly-out menu. Filtering on numbers enables you to specify several different operators, as shown in Figure 38-5. Operators such as Not Equals are different in Access and SQL Server, although these differences are transparent to the user querying the data. 877 www.getcoolebook.com Nielsen c38.tex V4 - 07/21/2009 2:15pm Page 878 Part V Data Connectivity FIGURE 38-3 Right-clicking on a column shows options for sorting as well as formatting columns. You can also drag the vertical lines separating the columns to resize or hide them. FIGURE 38-4 Filtering options for text fields include being able to specify parts of strings, not just whole words. 878 www.getcoolebook.com Nielsen c38.tex V4 - 07/21/2009 2:15pm Page 879 Access as a Front End to SQL Server 38 FIGURE 38-5 Specifying numeric filters in the Access UI masks syntax differences between Access and Transact-SQL. Filtering on dates is especially powerful. Not only do you get the usual operators, but you also can spec- ify quarters or months, as shown in Figure 38-6. FIGURE 38-6 Filtering on date values is simple, flexible, and powerful. 879 www.getcoolebook.com Nielsen c38.tex V4 - 07/21/2009 2:15pm Page 880 Part V Data Connectivity Creating forms and reports Access makes it easy for users to create forms and reports based on linked tables or views by selecting the table or view in the Access database window and selecting one of the wizards or templates on the Create toolbar Ribbon. You can also expose read-only data returned by stored procedures by creating pass-through queries that call them, as described earlier. Once the form or report is created, the For- mat Ribbon automatically loads, enabling you to format controls manually or choose from a variety of AutoFormats. Exporting and publishing data Another powerful feature in Access 2007 is the ease with which you can export data, not only from datasheet view but also from reports. The External Data Ribbon provides a graphical user interface to save or export reports to f ormats such as Excel, PDF, XPS, .RTF, XML, text files, and HTML. You can also move the data to SharePoint lists. Managing your SQL Server databases Even if you choose not to expose Access f unctionality and features to your end users for security or performance reasons, Access can be tremendously useful as an administrative tool for managing the databases on a SQL Server instance. A single Access front end can contain links to tables, views, information schema views, a nd other objects in multiple databases. Behind a firewall or on a secured share where there is little risk of penetration, Access can provide a handy supplement to the SQL Server UI tools. Summary For DBAs and line-of-business users who simply want to create their own ad hoc queries and reports, Access 2007 can provide a quick, low-cost alternative to expensive, end-to-end programmed applications that could take months or years to develop. Such solutions can augment existing .NET or Reporting Ser- vices applications, or they can empower users to work with the intuitive, built-in Access Ribbon features for sorting, filtering, and manipulating data. For scenarios that require more control over user behavior and increased scalability, VBA code and pass-though queries enable developers to create secure, efficient Access applications, often in much less time than would be required using Visual Studio. Access has long been wrongly maligned as a ‘‘toy,’’ when the reality is that, correctly used, it is potentially one of the most powerful and useful tools i n any developer or DBA’s toolbox. 880 www.getcoolebook.com Nielsen p06.tex V4 - 07/23/2009 7:39pm Page 881 Enterprise Data Management IN THIS PART Chapter 39 Configuring SQL Server Chapter 40 Policy-based Management Chapter 41 Recovery Planning Chapter 42 Maintaining the Database Chapter 43 Automating Database Maintenance with SQL Server Agent Chapter 44 Transferring Databases Chapter 45 Database Snapshots Chapter 46 Log Shipping Chapter 47 Mirroring Chapter 48 Clustering T his part is about the enterprise DBA role. The project isn’t done when the production database goes live. A successful database requires preventive maintenance (tune-ups) and corrective maintenance (diligent recovery planning). The Information Architecture Principle introduced in Chapter 1 presented the idea that information must be secured and made readily available for daily operations by individuals, groups, and processes, both today and in the future. While SQL Server is more automated than ever before, and Microsoft sometimes makes the error of presenting SQL Server as the database that doesn’t require a DBA, the truth is that it takes diligent work to keep a production database up 24 hours a day, 7 days a week, 365 days a year. If SQL Server is the box, Part VI is about making sure the box holds its shape, day after day. www.getcoolebook.com . Access is submitting to SQL Server: SQL Server Profiler and ODBC Trace. SQL Server Profiler is indispensable for understanding the interaction between your Access front end and SQL Server. Selecting. Transact -SQL syntax using SQL Server Management Studio. The following example is extracted from the white paper ‘‘Using SQL Server 2008 Table-valued Parameters in Access 2007.’’ See http://msdn .microsoft. com/en-us/library/dd721896.aspx. 874 www.getcoolebook.com Nielsen. interacts with SQL Server — and how to work with SQL Server Profiler and ODBC Trace — is contained in the white paper ‘‘Optimizing Microsoft Office Access Applications Linked to SQL Server, ’’ which