Beginning Access 1002002 Vba [Electronic resources]

Robert Smith; Dave Sussman Et al

نسخه متنی -صفحه : 256/ 170
نمايش فراداده

Fixing the Queries

As we have said, some of the queries in the Access database no longer work, mainly due to the use of the

Format function, which is not supported by SQL Server. In this section, we will look at the T-SQL required to repair the queries. This is where the upsizing report comes in handy. Instead of having to check each and every form/report, we simply check the upsizing report for failed queries.

qryxSS

This query failed to upsize because T-SQL does not support the Access

TRANSFORM ,

PIVOT, or

FORMAT syntax. SQL Server does not support Access Crosstab queries. The highlighted keywords cause the problem here as they are not supported by SQL Server.

TRANSFORM Sum(tblSales.Quantity) AS SumOfQuantity
SELECT tblCompany.CompanyName
FROM tblCompany INNER JOIN tblSales ON tblCompany.CompanyID = tblSales.fkCompanyID
GROUP BY tblCompany.CompanyName
PIVOT Format([DateOrdered],"mmmm") In ("January","February","March",
"April","May","June","July","August",
"September","October","November","December");

Before we look at the solutions to the above problems, let''s look quickly at some other problems you may face when upsizing. In general, the following will always fail to upsize:

    Queries containing

    DISTINCTROW

    Crosstab queries

    Pass-through queries

    DDL queries

    Queries that reference forms controls will also cause problems. It is common practice to pass parameters to queries from forms, for example, many developers use forms to collect dates for reports. When such a query is upsized, your Access SQL is replaced by T-SQL.

    For example, consider the following query, which collects a company''s name using a form and filters the results:

    SELECT tblCompany.CompanyName, tblCompany.Address, tblCompany.City
    FROM tblCompany
    WHERE (((tblCompany.CompanyName)=[forms]![frmcompany]![txtname]));

    When upsized the form reference parameter will be changed to:

    @forms_frmcompany

    As you can see, this will not work, as you have lost the reference to the form value.

    Fixing qrySalesSummary

    We will use the same technique to fix both

    qrySalesSummary and

    qryxSS . This involves the use of the T-SQL

    CASE structure.

    qryxSS

    This is aSummary .

    Try It Out—Replacing qryxSS with a Stored Procedure

    Because this stored procedure is fairly complex, we are unable to use the graphical tools to create it. The graphical tools allow you to create basic SQL procedures via the interface. In this case, we will be using conditional logic including the

    CASE statement. As the graphical tools are just not smart enough to do this for us, we will have to enter the SQL manually into the procedure window. Using SQL, this is as close as you will get to re-creating a "crosstab query" in SQL Server. Third-party products are available that use complex stored procedures to produce output very similar to that of Access.

      To create the procedure, click

      Queries |

      New.

      Select

      Create Text Stored Procedure.

      Enter the following SQL into the Stored Procedure:

      Create Procedure usp_qryss

      AS

      SELECT tblCompany.CompanyName,

      CASE Month(DateOrdered) WHEN 1 THEN SUM(tblSales.Quantity)

      ELSE 0 END AS ''January'',

      CASE Month(DateOrdered) WHEN 2 THEN SUM(tblSales.Quantity)

      ELSE 0 END AS ''February'',

      CASE Month(DateOrdered) WHEN 3 THEN SUM(tblSales.Quantity)

      ELSE 0 END AS ''March'',

      CASE Month(DateOrdered) WHEN 4 THEN SUM(tblSales.Quantity)

      ELSE 0 END AS ''April'',

      CASE Month(DateOrdered) WHEN 5 THEN SUM(tblSales.Quantity)

      ELSE 0 END AS ''May'',

      CASE Month(DateOrdered) WHEN 6 THEN SUM(tblSales.Quantity)

      ELSE 0 END AS ''June'',

      CASE Month(DateOrdered) WHEN 7 THEN SUM(tblSales.Quantity)

      ELSE 0 END AS ''July'',

      CASE Month(DateOrdered) WHEN 8 THEN SUM(tblSales.Quantity)

      ELSE 0 END AS ''August'',

      CASE Month(DateOrdered) WHEN 9 THEN SUM(tblSales.Quantity)

      ELSE 0 END AS ''September'',

      CASE Month(DateOrdered) WHEN 10 THEN SUM(tblSales.Quantity)

      ELSE 0 END AS ''October'',

      CASE Month(DateOrdered) WHEN 11 THEN SUM(tblSales.Quantity)

      ELSE 0 END AS ''November'',

      CASE Month(DateOrdered) WHEN 12 THEN SUM(tblSales.Quantity)

      ELSE 0 END AS ''December''

      FROM tblCompany INNER JOIN

      tblSales ON tblCompany.CompanyID =tblSales.fkCompanyID

      GROUP BY tblCompany.CompanyName,month(DateOrdered)

    How It Works

    There is a lot of SQL here, and it demonstrates one or two areas of T-SQL. Note the use of the

    CASE structure within the SQL statement. The

    CASE statement checks the value of the

    DateOrdered field. If the field contains a quantity the value is summed using the

    SUM(Quantity) statement, otherwise it is set to

    0 or

    NULL . Finally, we use an alias for the result based on the month concerned. The output from the procedure can be seen below:

    As we can see, it''s not as compact as the Access Crosstab, but not too shabby at all. The failure of SQL Server to support native Crosstabs has been a major complaint from Access developers. For some reason the SQL Server development team have so far refused to add

    PIVOT and

    TRANSFORM to T-SQL.

    qrySalesSummary

    This query uses the Access

    FORMAT function and thus fails to upsize to SQL Server.

    SELECT tblCompany.CompanyName, Format([DateOrdered],"mmmm") AS MonthName, Sum(tblSales.Quantity) AS SumOfQuantity, DatePart("m",[DateOrdered]) AS MonthNumber

    FROM tblCompany INNER JOIN tblSales ON tblCompany.CompanyID = tblSales.fkCompanyID

    GROUP BY tblCompany.CompanyName, Format([DateOrdered],"mmmm"), DatePart("m",[DateOrdered])

    ORDER BY tblCompany.CompanyName, DatePart("m",[DateOrdered]);

    In order to reproduce this query as a SQL Server stored procedure, we must replace the Access-specific functions and add one or two SQL Server functions. We are going to use the

    Datepart ,

    DateName, and

    Month functions to recreate this query. Once we have recreated the query as a stored procedure, we will repair the

    Sales

    Summary Report. In order to repair the query, we need to look as some SQL Server functions.

    DATENAME

    In the original query,

    MonthName:

    Format([DateOrdered],"mmmm") is the Access function used to return the month. We change this when using SQL Server and instead use the

    DATENAME(MONTH, dbo.tblSales.DateOrdered) function. The

    DATENAME function returns the part of the date specified as the first parameter to the function call. The following options are available using

    DateName :

    Function

    Result

    DATENAME(MONTH, DateOrdered)

    Returns the Month

    DATENAME(Quarter, DateOrdered)

    Returns the quarter

    DATENAME(week, DateOrdered)

    Returns the week number

    DATENAME(day, DateOrdered)

    Returns the day

    DATENAME(year, DateOrdered)

    Returns the year

    MONTH

    We then use the

    MONTH function to return the month number of the

    DateOrdered field. The

    MONTH function simply returns an integer representing the month passed to the function. For example, January will be 1, February 2, and so on. This is equivalent to

    DatePart(mm,dateordered) , but we are using it to illustrate the functions available to you in SQL Server. The rest of the procedure is standard, as in Microsoft Access SQL, and should pose no problem to you.

    Try It Out—Recreating QrySalesSummary as a Stored Procedure

      From the database window, click

      Queries |

      New.

      Click

      Design Stored Procedure .

      Select

      tblCompany and

      tblSales from the

      Add Table dialog.

      As we shall be using SQL Server functions, we will enter the field information manually.

      Click in the column pane (bottom half of the Query window).

      Use the drop-down list to select the

      CompanyName field.

      In the next row, enter the following:

      DATENAME(MONTH, dbo.tblSales.DateOrdered) .

      T he alias is entered as

      MonthName .

      In row three, select

      Quantity using the dropdown.

      In the row for

      Quantity , select

      SUM in the

      Group By column.

      In the next free row, enter

      MONTH(dbo.tblSales.DateOrdered) with an alias of

      MonthName.

      In the final row enter

      DATEPART(m, dbo.tblSales.DateOrdered) .

      At this point your stored procedure should look like that shown next:

      Close and save the procedure as

      usp_qrySalesSummary .

    Execute the query. The results are shown below:

    How It Works

    Most of what you have just completed is no different from creating a standard Access query. The main difference here is the use of SQL Server functions to replace non-supported Access functions.

    The SQL for the

    usp_qrySalesSummary stored procedure is also shown below for information:

    PROCEDURE dbo.usp_qrySalesSummary

    AS

    SELECT

    dbo.tblCompany.CompanyName, DATENAME(MONTH,

    dbo.tblSales.DateOrdered) AS MonthName,

    SUM(dbo.tblSales.Quantity) AS Quantity,

    MONTH(dbo.tblSales.DateOrdered) AS MonthNumber

    FROM

    dbo.tblCompany INNER JOIN

    dbo.tblSales ON dbo.tblCompany.CompanyID = dbo.tblSales.fkCompanyID

    GROUP BY dbo.tblCompany.CompanyName,

    DATENAME(MONTH, dbo.tblSales.DateOrdered),

    MONTH(dbo.tblSales.DateOrdered)

    ORDER BY dbo.tblCompany.CompanyName,

    DATEPART(m, dbo.tblSales.DateOrdered)

    The next step in the process, once we have written the stored procedure and tested its output using our original database for comparison, is to repair the

    Sales Summary Report by changing the record source of the report to the stored procedure created. Once we do this, there will be one or two other items that require tweaking.

    Try It Out—Changing Report Sales Summary Record Source

    Because the query

    QrySalesSummary was not upsized, this report will have lost its record source. We are now going to replace it with the Stored Procedure just created:

      Open the

      Sales Summary report in

      Design View

      .

      Open the reports

      Property Sheet.

      Click on the

      Data tab.

      Click in the

      Record Source property.

      Select

      usp _

      qrySalesSummary from the drop-down list. This is the Stored Procedure created in the earlier example.

      Switch to standard report view. Now we get some errors. The first error message we receive informs us that a field does not exist. This is because the report is looking for a field named

      SumOfQuantity . This happens because when the original query was written no alias was used for the field. We have to create an alias called

      Quantity using the line

      SUM(dbo.tblSales.Quantity)

      AS

      Quantity:

      Open the textbox

      SumOfQuantity.

      Open the

      Controls properties sheet.

      Click the

      Data tab.

      Click in the

      Control Source and using the drop-down list select

      Quantity.

      Close and Save the Report.

    That''s it, you''re done! View the report and you should find that it is identical to its Access counterpart.

    So, we''re dealt with the queries. Is there anything else causing problems? Let''s look at each object in turn.