Parameterized Query in Access SQL

Posted on

Problem

I am a beginner in Access SQL. I am in need of writing a parameter query for Access SQL and found a few tutorials and links for that but that wouldn’t satisfy my requirement.

DB: Access DB

This updates a ‘PD’ column based on the values of ‘OG’, ‘CPTY-BA’ in an INPUT table. I need to calculate PD values from other reference tables ‘PD’, ‘PD_MASTER_CPTY’ and ‘PD_MASTER_BG’.

Below is the VBA code with Access SQL with provided parameters. Is there any other way to write it in a single SELECT statement?

ElseIf (outputColumn = "PD") Then

strSQL = "SELECT [OG], CIF,[CPTY-BA], CIF_2 FROM INPUT   WHERE RUN_NUMBER='" + runNumber + "' ORDER BY CIF"
Set rs = CurrentDb.OpenRecordset(strSQL)

If Not (rs.EOF And rs.BOF) Then

     Do Until rs.EOF

        strOrigGroup = rs![Original Group]
        strCIF = rs![CIF]
        strCIF2 = rs![CIF_2]
        strBaselAsset = rs![CPTY-BA]


        If (strOrigGroup = "CB" Or strOrigGroup = "FID" Or strOrigGroup = "PB") Then

                strSQL1 = " SELECT DISTINCT  [INPUT].RUN_NUMBER, [INPUT].CIF, INPUT.CIF_2,[PD].[MID_PD] FROM [PD] INNER JOIN [INPUT] " + _
                          "ON [PD].CIF=[INPUT].CIF_2  WHERE [PD].[CIF]='" + strCIF2 + "' and [INPUT].RUN_NUMBER='" + runNumber + "'"
                Debug.Print strSQL1
                Set rs1 = CurrentDb.OpenRecordset(strSQL1)

                If Not (rs1.EOF And rs1.BOF) Then
                    strPD = CDbl(rs1![MID_PD])
                Else
                    strPD = "0.0229"
                End If

                strSQL = "update output set [PD] = '" + Format(strPD, "#.0000000000000") + "'  WHERE [OUTPUT].[CIF]='" + CStr(strCIF) + "' AND [OUTPUT].RUN_NUMBER='" + runNumber + "'"
                Debug.Print strSQL
                CurrentDb.Execute (strSQL)                    


        ElseIf (strBaselAsset = "BK" Or strBaselAsset = "BO" Or strBaselAsset = "SK") Then

                strSQL1 = "SELECT DISTINCT [INPUT].RUN_NUMBER,  [INPUT].CIF, [PD_MASTER_CPTY].[PD] FROM PD_MASTER_CPTY INNER JOIN INPUT ON [PD_MASTER_CPTY].COUNTERPARTY=INPUT.[CPTY-BA] WHERE [PD_MASTER_CPTY].[COUNTERPARTY]='" + strBaselAsset + "'AND [INPUT].CIF_2='" + CStr(strCIF2) + "' and [INPUT].RUN_NUMBER='" + runNumber + "'"
                Debug.Print strSQL1
                Set rs1 = CurrentDb.OpenRecordset(strSQL1)

                If Not (rs1.EOF And rs1.BOF) Then
                    strPD = CDbl(rs1![PD])
                Else
                    strPD = "0.0229"
                End If


                strSQL = "update output set [PD] = '" + Format(strPD, "#.0000000000000") + "'  WHERE [OUTPUT].[CIF]='" + CStr(strCIF) + "' AND [OUTPUT].RUN_NUMBER='" + runNumber + "'"
                Debug.Print strSQL
                CurrentDb.Execute (strSQL)

        Else
                strSQL1 = "SELECT [INPUT].RUN_NUMBER, [INPUT].CIF,[PD_MASTER_BG].[PD] FROM [PD_MASTER_BG] INNER JOIN INPUT ON [PD_MASTER_BG].[BUSINESS_GROUP]=INPUT.[ORIGINAL GROUP] WHERE [PD_MASTER_BG].[BUSINESS_GROUP]='" + strOrigGroup + "'AND [INPUT].CIF_2='" + CStr(strCIF2) + "' and [INPUT].RUN_NUMBER='" + runNumber + "'"
                Debug.Print strSQL1
                Set rs1 = CurrentDb.OpenRecordset(strSQL1)

                If Not (rs1.EOF And rs1.BOF) Then
                    strPD = CDbl(rs1![PD])
                Else
                    strPD = "0.0229"
                End If

                strSQL = "update output set [PD] = '" + Format(strPD, "#.0000000000000") + "'  WHERE [OUTPUT].[CIF]='" + CStr(strCIF) + "' AND [OUTPUT].RUN_NUMBER='" + runNumber + "'"
                Debug.Print strSQL
                CurrentDb.Execute (strSQL)


        End If

        rs.MoveNext
        Loop

End If

Solution

Before we can do anything here really, we need to clean this up so we can understand exactly what’s going on.

To start with, let’s remove some duplication. This code is copy/pasted all over the place, but no matter what happens, it executes.

If Not (rs1.EOF And rs1.BOF) Then
    strPD = CDbl(rs1![PD])
Else
    strPD = "0.0229"
End If

strSQL = "update output set [PD] = '" + Format(strPD, "#.0000000000000") + "'  WHERE [OUTPUT].[CIF]='" + CStr(strCIF) + "' AND [OUTPUT].RUN_NUMBER='" + runNumber + "'"
Debug.Print strSQL
CurrentDb.Execute (strSQL)

    If (strOrigGroup = "CB" Or strOrigGroup = "FID" Or strOrigGroup = "PB") Then

            strSQL1 = " SELECT DISTINCT  [INPUT].RUN_NUMBER, [INPUT].CIF, INPUT.CIF_2,[PD].[MID_PD] FROM [PD] INNER JOIN [INPUT] " + _
                      "ON [PD].CIF=[INPUT].CIF_2  WHERE [PD].[CIF]='" + strCIF2 + "' and [INPUT].RUN_NUMBER='" + runNumber + "'"
            Debug.Print strSQL1
            Set rs1 = CurrentDb.OpenRecordset(strSQL1)

    ElseIf (strBaselAsset = "BK" Or strBaselAsset = "BO" Or strBaselAsset = "SK") Then

         strSQL1 = "SELECT DISTINCT [INPUT].RUN_NUMBER,  [INPUT].CIF, [PD_MASTER_CPTY].[PD] FROM PD_MASTER_CPTY INNER JOIN INPUT ON [PD_MASTER_CPTY].COUNTERPARTY=INPUT.[CPTY-BA] WHERE [PD_MASTER_CPTY].[COUNTERPARTY]='" + strBaselAsset + "'AND [INPUT].CIF_2='" + CStr(strCIF2) + "' and [INPUT].RUN_NUMBER='" + runNumber + "'"
         Debug.Print strSQL1
         Set rs1 = CurrentDb.OpenRecordset(strSQL1)
    Else
        strSQL1 = "SELECT [INPUT].RUN_NUMBER, [INPUT].CIF,[PD_MASTER_BG].[PD] FROM [PD_MASTER_BG] INNER JOIN INPUT ON [PD_MASTER_BG].[BUSINESS_GROUP]=INPUT.[ORIGINAL GROUP] WHERE [PD_MASTER_BG].[BUSINESS_GROUP]='" + strOrigGroup + "'AND [INPUT].CIF_2='" + CStr(strCIF2) + "' and [INPUT].RUN_NUMBER='" + runNumber + "'"
        Debug.Print strSQL1
        Set rs1 = CurrentDb.OpenRecordset(strSQL1)
    End If

    If Not (rs1.EOF And rs1.BOF) Then
        strPD = CDbl(rs1![PD])
    Else
        strPD = "0.0229"
    End If

    strSQL = "update output set [PD] = '" + Format(strPD, "#.0000000000000") + "'  WHERE [OUTPUT].[CIF]='" + CStr(strCIF) + "' AND [OUTPUT].RUN_NUMBER='" + runNumber + "'"
    Debug.Print strSQL
    CurrentDb.Execute (strSQL)

    rs.MoveNext
Loop

Next, give your SQL statement variables some meaningful names. I shouldn’t have to keep reminding myself that strSQL1 is the select statement and strSQL is the update. Try selectSQL and updateSQL respectively.

Next, I would separate the messy business of creating the string to be executed from the business of actually executing.

Private Function BuildSelectStatement(byval cif as string, byval runNumber as integer, Optional byval baselAsset as String) As String
    ...
End Function

....

selectSQL = BuildSelectStatement(strCIF2, runNumber)

Which brings me to recommending that you use ADODB for this. The only time it’s really important to stick with DAO is when you intend on binding a form to the resulting Recordset. Instead of concatenating all of these parameters into strings, you could instead be passing parameter into parameterized queries. It looks and reads much better than this.

Leave a Reply

Your email address will not be published. Required fields are marked *