Results 1 to 31 of 31

Thread: How I build my SQL strings

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Oct 2006
    Location
    USA
    Posts
    476

    How I build my SQL strings

    This is the entire module I wrote for building SQL strings for my application. All of this was previously contained in a single sub so I broke it up into individual 'tasks', if that makes any sense. Since I'm still pretty new at this I don't know if that's good or bad practice.

    Good, bad, inefficient, maintainable? Do your worst; I'm prepared to take it! There are several functions so if you have any questions about how they work or if I've left anything out please let me know.

    TIA.

    VB Code:
    1. ' This function fetches the subfilter condition from the Conditions table
    2. ' on SQL Server and returns it to the calling sub only if there is a selected
    3. ' value on the subfilter.  If there is no selected value or the selected
    4. ' value is 'All', the function returns nothing.  The sub-filter is the combo
    5. ' box on Criteria Selection where the user can choose values for Application
    6. ' Type, Critical Illness, Missing Items, or Sum Assured.
    7.  
    8. Public Function GetCondition(strSubFilterValue As String, strSQL As String) As String
    9.  
    10. ' Check to make sure connection still exists.  If it doesn't, set it up.  If connection
    11. ' is closed then open it.
    12. ' Call CheckConnection
    13.  
    14. Dim strCondition As String
    15.  
    16. ' // If the LENGTH of the subfilter value is 0 then nothing is selected, strCondition
    17. ' is set to empty; if the value is 'ALL' then no filtering needs to be applied and
    18. ' strCondition is likewise set to empty.
    19. If Len(strSubFilterValue) = 0 Then
    20.     strCondition = ""
    21. ElseIf strSubFilterValue = "All" Then
    22.     strCondition = ""
    23.    
    24. ' // If the LENGTH of the subfilter value is greater than zero this indicates the user
    25. ' has selected something, so a recordset is opened and the SQL source passed to the function
    26. ' is executed.
    27. ElseIf Len(strSubFilterValue) > 0 Then
    28.     Dim rst As ADODB.Recordset
    29.     Set rst = New ADODB.Recordset
    30.     rst.Open strSQL, cnConn, adOpenForwardOnly, adLockReadOnly, adCmdText
    31.     strCondition = rst.GetString
    32.     rst.Close
    33.     Set rst = Nothing
    34. End If
    35.  
    36. GetCondition = strCondition
    37.  
    38. End Function

    VB Code:
    1. ' This function uses the tab the user is on and the value of the filter they've
    2. ' selected to construct part of the 'WHERE' clause SQL Server will need to return
    3. ' the appropriate data.  Example 'filter' values are York, Bankhall, CONTROL, etc.
    4. ' This function does not actually include 'WHERE' or 'AND'; that part of the string
    5. ' is constructed by another function.
    6.  
    7. Public Function GetClause(strTabValue As String, strFilterValue As String) As String
    8.  
    9. ' Check to make sure connection still exists.  If it doesn't, set it up.  If connection
    10. ' is closed then open it.
    11. ' Call CheckConnection
    12.  
    13.     Dim strClause As String
    14.  
    15.     ' Builds a SQL clause based on what tab the user is currently using; if the tab value
    16.     ' is "Headof" then no clause is built as no filter is actually being used.
    17.     Select Case strTabValue
    18.         Case Is = "HeadOf"
    19.             strClause = ""
    20.         Case Is = "Distributor"
    21.             strClause = "Distributor = " & "'" & "'" & strFilterValue & "'" & "'"
    22.         Case Is = "Site"
    23.             strClause = "Site = " & "'" & "'" & strFilterValue & "'" & "'"
    24.         Case Is = "Team"
    25.             strClause = "Team = " & "'" & "'" & strFilterValue & "'" & "'"
    26.         Case Is = "Parent"
    27.             strClause = "ParentCompany = " & "'" & "'" & strFilterValue & "'" & "'"
    28.         Case Else
    29.             strClause = ""
    30.     End Select
    31.    
    32.     GetClause = strClause
    33.  
    34. End Function

    VB Code:
    1. ' This function uses the values of strCondition and strClause plus
    2. ' what tab the user is on to determine how to build the parameter string.
    3. ' On the HeadOf tab, the only time there will be a WHERE clause is if
    4. ' a sub-filter value is selected; otherwise there is no WHERE clause.
    5. '
    6. ' On other tabs if a sub-filter value is selected it must be preceded by AND,
    7. ' not WHERE, as you can only use the WHERE keyword once in a normal query
    8. ' and we'll already be using WHERE for Distributor, Site, Team, or ParentCompany.
    9.  
    10. Public Function GetParameter(strCondition As String, strTabValue As String _
    11.     , strClause As String) As String
    12.  
    13.     ' Check to make sure connection still exists.  If it doesn't, set it up.  If connection
    14.     ' is closed then open it.
    15.     'Call CheckConnection
    16.    
    17.     Dim strParameter As String
    18.    
    19.     Select Case strTabValue
    20.         ' If the user is on HeadOf and no condition is selected then no WHERE clause is built
    21.         ' If a condition (subfilter) is selected then a WHERE clause is constructed
    22.         Case Is = "HeadOf"
    23.             If strCondition = "" Then
    24.                 strParameter = ""
    25.             Else:
    26.                 strParameter = " WHERE " & strCondition
    27.             End If
    28.         ' If the user is on any other tab and no condition (subfilter) is selected then the
    29.         ' WHERE clause is constructed using only the selected distributor, site, etc.
    30.         ' If a condition (subfilter) is selected then an AND clause is tacked onto the
    31.         ' end of the WHERE clause
    32.         Case Is = "Distributor", "Site", "Team", "Parent"
    33.             If strCondition = "" Then
    34.                 strParameter = " WHERE " & strClause
    35.             Else: If Len(strCondition) > 0 Then strParameter = " WHERE " & strClause & " AND " & strCondition
    36.             End If
    37.         ' This should never happen, but in case it does GetParameter returns a zero-length string
    38.         Case Else
    39.             strParameter = ""
    40.     End Select
    41.    
    42.     GetParameter = strParameter
    43.  
    44. End Function

    VB Code:
    1. ' Executes GetClause, GetCondition, and GetParameter to build an appropriate
    2. ' SQL string based on the user's selections on the CriteriaSelection form.
    3. ' This is the string that will be passed to the appropriate stored procedure
    4. ' as its parameter.
    5.  
    6. Public Function DeriveWhereClause() As String
    7.  
    8. ' Check to make sure connection still exists.  If it doesn't, set it up.  If connection
    9. ' is closed then open it.
    10.  Call CheckConnection
    11.  
    12. Dim strParameter As String          ' Holds value of parameter
    13. Dim strCondition As String          ' Holds value of condition
    14. Dim strClause As String             ' Holds value of clause
    15. Dim strTabValue As String           ' Holds what tab user is currently on
    16. Dim strFilterValue As String        ' Holds value of filter, i.e. 'York', 'Bankhall', etc
    17. Dim strSubFilterValue As String     ' Holds value of subfilter, i.e. 'paper', 'dirty', etc
    18. Dim strAddInfoType As String        ' Holds value of subfilter type, i.e. 'Missing Items', 'Critical Illness', etc
    19. Dim strSQL As String                ' Source SQL
    20.  
    21. ' Call global variable functions and assign results to local variables
    22. strTabValue = GetgVarActiveTab()
    23. strFilterValue = GetgVarPrimInfoValue()
    24. strSubFilterValue = GetgVarAddInfoValue()
    25. strAddInfoType = GetgVarAddInfoType()
    26.  
    27. ' Initialize strSQL
    28. strSQL = "SELECT SQLResult FROM Conditions WHERE QueryField = " _
    29.     & "'" & strAddInfoType & "'" & " AND Value = " & "'" & strSubFilterValue & "'"
    30.  
    31. ' Call GetCondition function and assign result to strCondition variable
    32. If Len(strSubFilterValue) > 0 Then
    33.     strCondition = GetCondition(strSubFilterValue, strSQL)
    34. Else
    35.     strCondition = ""
    36. End If
    37.  
    38. ' Call GetClause function and assign result to strClause variable
    39. If Len(strTabValue) > 0 Then
    40.     strClause = GetClause(strTabValue, strFilterValue)
    41. Else
    42.     strClause = ""
    43. End If
    44.  
    45. ' Call GetParameter function and assign result to strParameter variable
    46. strParameter = GetParameter(strCondition, strTabValue, strClause)
    47.  
    48. DeriveWhereClause = strParameter
    49.  
    50. End Function

    VB Code:
    1. Public Function MakeSQLString() As String
    2.  
    3.     ' Check to make sure connection still exists/is open.
    4.     Call CheckConnection
    5.  
    6.     Dim strSQL As String
    7.     Dim strSQLObject As String
    8.     Dim strSource As String
    9.    
    10.     Dim rst As ADODB.Recordset
    11.    
    12.     strSource = "SELECT SQLObject FROM tblReports WHERE ReportName = " & _
    13.         "'" & GetgVarReportSelected() & "'"
    14.    
    15.     Set rst = cnConn.Execute(strSource)
    16.     strSQLObject = rst.GetString
    17.    
    18.     ' Status History and CELT Data Summary cannot be filtered in any
    19.     ' way so their SQL strings are hard-coded here.  Weekly Summary
    20.     ' is not handled by this function at all.
    21.     Select Case GetgVarReportSelected()
    22.         Case Is = "Status History"
    23.             strSQL = "EXEC sp_StatusPositionSummary"
    24.         Case Is = "CELT Data Summary"
    25.             strSQL = "EXEC sp_FEWATCELT"
    26.         Case Else
    27.             strSQL = "EXEC " & strSQLObject & " @Filter = " _
    28.                 & "'" & DeriveWhereClause & "'"
    29.     End Select
    30.      
    31.     MakeSQLString = strSQL
    32.    
    33.     rst.Close
    34.     Set rst = Nothing
    35.    
    36. End Function

  2. #2
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: How I build my SQL strings

    Why are you using in-line SQL statements?

    Have you considered doing everything with STORED PROCEDURES?

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  3. #3

    Thread Starter
    Hyperactive Member
    Join Date
    Oct 2006
    Location
    USA
    Posts
    476

    Re: How I build my SQL strings

    Quote Originally Posted by szlamany
    Why are you using in-line SQL statements?

    Have you considered doing everything with STORED PROCEDURES?
    That's what we use. MakeSQLString() builds a where clause which is passed to the stored procedure as a parameter.

  4. #4
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: How I build my SQL strings

    So - it's dynamic SQL in the SPROC - right?

    Looks at this thread - post #2 and post #16 are the main points I wanted to demonstrate.

    http://www.vbforums.com/showthread.p...40idlist+table

    It's an alternative to building dynamic WHERE clauses.

    We use both techniques - probably #2 more often. But when speed becomes an issue we go with #16.

    We have never yet used dynamic SQL in a SPROC (well over 1500 SPROCS in 6 years now!). Probably one of the most deciding reasons for that is we like to put all the business logic in the SPROC - we consider it our middle-tier (business layer). Our SPROCS self-bind at run-time to textboxes or flexgrid columns - based on matching the name of the parameter to the UI objects.

    So adding a new "feature" to the app means only putting the textbox, for example, on the form. The SPROC self-binds and all our IF/WHERE business-logic sits in the SPROC. Effectively we add new BL requirements to the app without ever releasing a new .exe...

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  5. #5

    Thread Starter
    Hyperactive Member
    Join Date
    Oct 2006
    Location
    USA
    Posts
    476

    Re: How I build my SQL strings

    Quote Originally Posted by szlamany
    So - it's dynamic SQL in the SPROC - right?

    Looks at this thread - post #2 and post #16 are the main points I wanted to demonstrate.

    http://www.vbforums.com/showthread.p...40idlist+table

    It's an alternative to building dynamic WHERE clauses.

    We use both techniques - probably #2 more often. But when speed becomes an issue we go with #16.

    We have never yet used dynamic SQL in a SPROC (well over 1500 SPROCS in 6 years now!). Probably one of the most deciding reasons for that is we like to put all the business logic in the SPROC - we consider it our middle-tier (business layer). Our SPROCS self-bind at run-time to textboxes or flexgrid columns - based on matching the name of the parameter to the UI objects.

    So adding a new "feature" to the app means only putting the textbox, for example, on the form. The SPROC self-binds and all our IF/WHERE business-logic sits in the SPROC. Effectively we add new BL requirements to the app without ever releasing a new .exe...
    We can't use simple filters like that because the where clause could be absent, it could be followed by an AND clause, or it could not be. It could be 'WHERE Distributor = 'Blah'' or 'WHERE Site = 'India' AND EDI = 'Y'' or it could be ''. We just never know. Since it's so changeable we decided that passing the entire where clause as a parameter was the easiest way to go.

    Here is a sample stored procedure that we use:

    Code:
    CREATE PROCEDURE dbo.sp_FEVBWeeklySummary_Res(@Filter nvarchar(200) = NULL)
    AS
    
    DECLARE @strSQL nvarchar(3000)
    
    SET @strSQL = N'SELECT WeekStart
    , SUM(CASE [Grouping] WHEN ''Term'' THEN Cases ELSE NULL END) AS ''Term''
    , SUM(CASE [Grouping] WHEN ''MLI'' THEN Cases ELSE NULL END) AS ''MLI''
    , SUM(CASE [Grouping] WHEN ''PTA'' THEN Cases ELSE NULL END) AS ''PTA''
    , SUM(CASE [Grouping] WHEN ''Other Protection'' THEN Cases ELSE NULL END) AS ''Other Protection''
    , SUM(CASE [Grouping] WHEN ''NTU'' THEN Cases ELSE NULL END) AS ''NTU''
    , SUM(CASE [Grouping] WHEN ''Decline-Defer'' THEN Cases ELSE NULL END) AS ''Decline-Defer''
    FROM vwFEWeeklySummary_Res'
    + @Filter + 
    ' GROUP BY WeekStart'
    	
    
    EXEC sp_executesql @strSQL
    
    
    GO

  6. #6
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: How I build my SQL strings

    I appreciate the approach you are taking - it seems robust.

    Since we live with a 0%-BL-requirement in the vb client we need to come up with ways to do that same in the SPROC itself.

    Our SPROCS end up with lots of IF/BEGIN/END blocks - lots of different paths to follow based on the parameters.

    It's not a lot different then what you are doing in the long run.

    You could probably do all the VB WHERE clause building in the T-SQL SPROC, and still use the dynamic execute...

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  7. #7

    Thread Starter
    Hyperactive Member
    Join Date
    Oct 2006
    Location
    USA
    Posts
    476

    Re: How I build my SQL strings

    Quote Originally Posted by szlamany
    I appreciate the approach you are taking - it seems robust.

    Since we live with a 0%-BL in the vb client we need to come up with ways to do that same in the SPROC itself.

    Our SPROCS end up with lots of IF/BEGIN/END blocks - lots of different paths to follow based on the parameters.

    It's not a lot different then what you are doing in the long run.

    You could probably do all the VB WHERE clause building in the T-SQL SPROC, and still use the dynamic execute...
    We probably could, but when we did this we were running Access 97 as a front end on SQL and this seemed the better option. Plus we think this is a much more simple option than having to code all of it in VB.

    I appreciate that you think it's robust; our DBAs hate it and are threatening to disallow it after 8 months of rubber-stamping my code.

  8. #8
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: How I build my SQL strings

    Is the DBA argument against the use of dynamic SQL?

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  9. #9

    Thread Starter
    Hyperactive Member
    Join Date
    Oct 2006
    Location
    USA
    Posts
    476

    Re: How I build my SQL strings

    Quote Originally Posted by szlamany
    Is the DBA argument against the use of dynamic SQL?
    Nope, we already went round and round on that when I tried to use EXEC(), which they let slip past for several months before they griped about it. I could see their point there though I thought their fears about injection attacks were slightly silly since we're not using web apps and our users are so thick I had to add a special Print button...I doubt injection attacks were ever really a risk but hey, it's their DB server...so I changed my stored procedures without complaining.

    Their objection here is that I'm using stored procedures at all; they think I should build all my SQL in the VB app which I think is a stupid idea since many of the dynamic queries are complex. They got this idea because the sproc I sent to them to promote to production is concatenating a simple select statement with a where clause. Now they're being snarky about my table's indexes, but one of them did an analysis and said there wasn't any point in adding more indexes. There are six of them and you can ask them all the same question and get six wildly different answers. This has happened before and it will happen again. They're fearful of being outsourced and at this moment I can't really say that I think it's a bad idea. I think as individuals they're good guys, but as a team they STINK.

  10. #10
    PowerPoster RhinoBull's Avatar
    Join Date
    Mar 2004
    Location
    New Amsterdam
    Posts
    24,132

    Re: How I build my SQL strings

    Quote Originally Posted by disruptivehair
    We can't use simple filters like that because the where clause could be absent, it could be followed by an AND clause, or it could not be...
    That sin't a problem though... One trick you can use is to permanently add to your select statement the following where clause:

    Select...
    From...
    Where 1=1

    All you have to do now is add as many additional ANDs as you can possibly need.
    You can build all of your filters in the fron end and pass it to SP and then append it at the end of sql (after 1=1).

    I actually agree with your DBA - multiple if-else make SP run slower. Just instead of "disallowing" he should help you to tune it up.

  11. #11

    Thread Starter
    Hyperactive Member
    Join Date
    Oct 2006
    Location
    USA
    Posts
    476

    Re: How I build my SQL strings

    Quote Originally Posted by RhinoBull
    That sin't a problem though... One trick you can use is to permanently add to your select statement the following where clause:

    Select...
    From...
    Where 1=1

    All you have to do now is add as many additional ANDs as you can possibly need.
    You can build all of your filters in the fron end and pass it to SP and then append it at the end of sql (after 1=1).

    I actually agree with your DBA - multiple if-else make SP run slower. Just instead of "disallowing" he should help you to tune it up.

    Thanks RB, I'll try that.

    And I agree...they SHOULD help. But they don't...they think it is not their job to help anyone.

  12. #12

    Thread Starter
    Hyperactive Member
    Join Date
    Oct 2006
    Location
    USA
    Posts
    476

    Re: How I build my SQL strings

    I should add that I don't feel the problem is on my end; the DBAs not only do not like the fact that we're using stored procedures but they think the performance of my queries is suffering. They keep telling me that my queries are doing 'complete table scans' but when I display the execution plan in SQL Server, I NEVER EVER EVER see a table scan of any kind. The only bits I see are:

    Select
    Compute Scalar
    Hash Match/Left Outer Join
    Computer Scalar
    Nested Loops/Inner Join
    Clustered Index Scan x 3
    Table Spool/Lazy Spool

    This is what *I* saw on a stored procedure where they CLAIM they saw three table scans. I've seen table scans show up on execution plans before and they say 'TABLE SCAN' right underneath them. I asked the DBAs if perhaps they're referring to something else and of course they never responded. Now, these names and icons don't mean very much to me; they are not covered in any SQL book I own nor do the books online tell me anything about them. I don't know what a 'table spool/lazy spool' is and I don't know what in my SQL is triggering it. I have no idea. The DBAs won't tell me. All they do is claim they're seeing table scans when I don't see table scans and have not since we indexed our tables. If I create a table with dummy data and no indexes then query it I can see the 'table scan' icon in the execution plan. I NEVER see this icon when running execution plans for my application's stored procedures, so why are THEY telling me that they're seeing it?

    What are they getting at? I'm tired of shooting for a moving target. We have researched our DB design and have indexed the most frequently accessed columns. We re-examine our DB's indexes and performance periodically and we asked the DBAs to run an index analysis after which they told us our DB was FINE. Now they're essentially claiming that we have NO indexes in our main data table when in fact we have several. Who here is full of bunk...us, them, or all of us? We're busting our butts trying to make our DB as efficient and fast as possible and they keep changing the rules on us and feeding us contradictory information. How can we work together when they don't even believe us when we tell them we're not seeing table scans?

  13. #13
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: How I build my SQL strings

    Can you post the picture image from the execution plan - so I can see rowcounts and percentanges associated with steps...

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  14. #14

    Thread Starter
    Hyperactive Member
    Join Date
    Oct 2006
    Location
    USA
    Posts
    476

    Re: How I build my SQL strings

    Quote Originally Posted by szlamany
    Can you post the picture image from the execution plan - so I can see rowcounts and percentanges associated with steps...
    You can't see the rowcounts here unless I hover over the icons, but you can see the percentages.

    http://i16.photobucket.com/albums/b2...cutionplan.jpg

  15. #15
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: How I build my SQL strings

    Where CITYPE is NOT NULL

    Is CITYPE an INDEX? And it allows NULL's? I'm not so sure how NULL's are handled in INDEX SCANS - I'm not sure I have ever indexed a column that allows null's...

    I did find this:

    Typically, spooling operations (such as Lazy Spool or Eager Spool) occur
    when an input rowset to a join or some other operation is too large for storage
    in RAM. When this happens, the DBMS will write (or spool) the large rowset
    onto hard disk storage in tempdb - this is kind of like the Windows swapfile.
    how many rows in that table?

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  16. #16

    Thread Starter
    Hyperactive Member
    Join Date
    Oct 2006
    Location
    USA
    Posts
    476

    Re: How I build my SQL strings

    Quote Originally Posted by szlamany
    Where CITYPE is NOT NULL

    Is CITYPE an INDEX? And it allows NULL's? I'm not so sure how NULL's are handled in INDEX SCANS - I'm not sure I have ever indexed a column that allows null's...
    CI_Type is not indexed.

    I did find this:
    how many rows in that table?
    In the table where all the data is actually held there are 528,643 rows.

  17. #17
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: How I build my SQL strings

    So a table scan is being done for that query.

    Is the PRIMARY KEY a CLUSTERED INDEX?

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  18. #18

    Thread Starter
    Hyperactive Member
    Join Date
    Oct 2006
    Location
    USA
    Posts
    476

    Re: How I build my SQL strings

    Quote Originally Posted by szlamany
    So a table scan is being done for that query.
    It doesn't say a table scan is being done. I hate computers sometimes. I mean what am I, psychic?

    Is the PRIMARY KEY a CLUSTERED INDEX?
    Yes.

  19. #19
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: How I build my SQL strings

    Quote Originally Posted by disruptivehair
    ...what am I, psychic?
    I am

    Actually, since you told me that the WHERE column was not an INDEX...

    but I can see that 87% of the time was spent on something appearing to be named "PPEKBaseData.PK..."

    that means you have a CLUSTERED PRIMARY KEY.

    So your DATA LEAVES are in physically stored in with your PRIMARY INDEX LEAVES. You have no DATA section - so the PRIMARY KEY section was used.

    It has no relationship with CI_Type so it was "table scanned"...

    I'm guessing based on the number of rows+size of row data returned that the LAZY spooler was used to store the working resultset on disk - not enough memory space...

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  20. #20
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: How I build my SQL strings

    [edit]Change it to:

    Code:
    Select * From dbo.vwfSpecialIssued
    	Where PRIMARYKEYCOLUMN is in (Select PRIMARYKEYCOLUMN
    					From dbo.vwfSpecialIssued
    					Where CI_Type is not null)
    and tell me if performance changes

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  21. #21

    Thread Starter
    Hyperactive Member
    Join Date
    Oct 2006
    Location
    USA
    Posts
    476

    Re: How I build my SQL strings

    Quote Originally Posted by szlamany
    [edit]Change it to:

    Code:
    Select * From dbo.vwfSpecialIssued
    	Where PRIMARYKEYCOLUMN is in (Select PRIMARYKEYCOLUMN
    					From dbo.vwfSpecialIssued
    					Where CI_Type is not null)
    and tell me if performance changes
    Nope, no change.

    This:
    Code:
    Select * From dbo.vwfeSpecialIssued
    	Where Pol_no in (Select Pol_no
    			From dbo.vwfeSpecialIssued
    			Where CI_Type is not null)
    and this:

    Code:
    SELECT * FROM dbo.vwFESpecialIssued
    WHERE CI_Type IS NOT NULL
    took exactly the same amount of time to run though their execution plans look different. The one you wrote contains a clustered index seek and an index scan as well as three clustered index scans; the simple one below just has three clustered index scans.

  22. #22
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: How I build my SQL strings

    You did see my post #19 - right?

    At any rate - I was trying to avoid the spool to disk by using the subquery to generate a "primary key list" - being smaller than SELECT *...

    So that the final resultset would be served by an index scan.

    But "IN (subquery)" is a stinky construct.

    What's the goal here anyway? There is no way to really avoid a table scan when the WHERE clause is on some un-keyed column of data. Do you have the option of temporarily adding an INDEX for ci_type to see the difference - or do you need DBA blessing for that

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  23. #23

    Thread Starter
    Hyperactive Member
    Join Date
    Oct 2006
    Location
    USA
    Posts
    476

    Re: How I build my SQL strings

    Quote Originally Posted by szlamany
    You did see my post #19 - right?
    A better question to ask would be 'did you understand my post #19,' the answer to which is a resounding NO!

    At any rate - I was trying to avoid the spool to disk by using the subquery to generate a "primary key list" - being smaller than SELECT *...

    So that the final resultset would be served by an index scan.
    Buuuuh ok.

    But "IN (subquery)" is a stinky construct.
    Er...if you say so.

    What's the goal here anyway? There is no way to really avoid a table scan when the WHERE clause is on some un-keyed column of data. Do you have the option of temporarily adding an INDEX for ci_type to see the difference - or do you need DBA blessing for that
    No, in the dev DBs I can do pretty much whatever I want. I tried the query with and without an index on CI_Type and the performance was identical.

    Maybe my DB just sucks.

  24. #24
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: How I build my SQL strings

    "Where ... IN (subquery)" stinks because each and every row in the FROM table is checked against existence in a subquery. This is not a very natural way to JOIN things together. I do use it myself sometimes - but avoid it if possible. Sub-queries in general are poor performer's...

    I believe a point was made by Kaffenils in a post last week that putting an INDEX in for a WHERE column really won't help if doing a SELECT * since it's got to use the DATA section itself for so much of the work - so it ends up going there instead and potentially ignoring the INDEX you put for the WHERE column.

    I'm not sure that an INDEX with NULL's involved and a WHERE COLX IS NOT NULL would ever work anyway - NULL's being equal to nothing type issue.

    My point from back in #19 was that you have no PRIMARY KEY that sits by itself. When you CLUSTER your primary key you are actually taking the DATA portion - the actual data rows - and ordering them in PRIMARY KEY order. So your PRIMARY KEY section physically resides on disk, in the database, with you physical DATA portion. So every access to a table that has as PRIMARY KEY that is CLUSTERED is against the PK section of the table - since that's where the data resides.

    Since your column of WHERE (ci_type) is not in order - not being ordered by the primary key - a "full scan" of the data is done to find rows matching your where clause. Since the "data" resides in the primary key (because it's clustered) then it might appear in the execution plan that it used the PK, but not in an "index" scan kind of way - but really in a table scan kind of way.

    Hope that makes more sense.

    Try this:

    Code:
    Create View dbo.MyKeys_V as Select Pol_no
    			From dbo.vwfeSpecialIssued
    			Where CI_Type is not null
    Then do:

    Code:
    Select * From dbo.MyKeys_V MK
          Left Join dbo.vwfeSpecialIssued SI on SI.Pol_No=MK.Pol_No
    and see if that works differently...

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  25. #25

    Thread Starter
    Hyperactive Member
    Join Date
    Oct 2006
    Location
    USA
    Posts
    476

    Re: How I build my SQL strings

    Quote Originally Posted by szlamany
    "Where ... IN (subquery)" stinks because each and every row in the FROM table is checked against existence in a subquery. This is not a very natural way to JOIN things together. I do use it myself sometimes - but avoid it if possible. Sub-queries in general are poor performer's...

    I believe a point was made by Kaffenils in a post last week that putting an INDEX in for a WHERE column really won't help if doing a SELECT * since it's got to use the DATA section itself for so much of the work - so it ends up going there instead and potentially ignoring the INDEX you put for the WHERE column.

    I'm not sure that an INDEX with NULL's involved and a WHERE COLX IS NOT NULL would ever work anyway - NULL's being equal to nothing type issue.

    My point from back in #19 was that you have no PRIMARY KEY that sits by itself. When you CLUSTER your primary key you are actually taking the DATA portion - the actual data rows - and ordering them in PRIMARY KEY order. So your PRIMARY KEY section physically resides on disk, in the database, with you physical DATA portion. So every access to a table that has as PRIMARY KEY that is CLUSTERED is against the PK section of the table - since that's where the data resides.

    Since your column of WHERE (ci_type) is not in order - not being ordered by the primary key - a "full scan" of the data is done to find rows matching your where clause. Since the "data" resides in the primary key (because it's clustered) then it might appear in the execution plan that it used the PK, but not in an "index" scan kind of way - but really in a table scan kind of way.

    Hope that makes more sense.
    Sort of, but not really. I hate reading about indexing because it sounds like such a pain in the arse. I still try lots of different things and they continue to NOT work, and I'm beginning to wonder what the point of indexing is at all since I've never seen it improve my DB's performance.

    Try this:

    Code:
    Create View dbo.MyKeys_V as Select Pol_no
    			From dbo.vwfeSpecialIssued
    			Where CI_Type is not null
    Then do:

    Code:
    Select * From dbo.MyKeys_V MK
          Left Join dbo.vwfeSpecialIssued SI on SI.Pol_No=MK.Pol_No
    and see if that works differently...
    It's slower than the last query you suggested. The previous one took 3 seconds to run, this one takes 5 and its execution plan looks like spaghetti. Doesn't really mean much to me.

  26. #26
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: How I build my SQL strings

    I'm struggling to come up with a way to identify the sub-set of rows you want in the 500,000 rows that exists when there appears to be no INDEX possible.

    Let's try this just to see if we can get it to work differently - since you are in a development DB, I'm guessing you can create a table to test things with...

    Code:
    Create Table MyKeys (Pol_no somedatatype Primary Key Clustered)
    
    Insert into MyKeys Select Pol_no
    			From dbo.vwfeSpecialIssued
    			Where CI_Type is not null
    Do this outside of checking the execution plan - I just want to get a table of the primary keys desired.

    Then do this in a new window - checking the execution plan.

    Code:
    Select SI.* From dbo.MyKeys MK
          Left Join dbo.vwfeSpecialIssued SI on SI.Pol_No=MK.Pol_No

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  27. #27

    Thread Starter
    Hyperactive Member
    Join Date
    Oct 2006
    Location
    USA
    Posts
    476

    Re: How I build my SQL strings

    Quote Originally Posted by szlamany
    I'm struggling to come up with a way to identify the sub-set of rows you want in the 500,000 rows that exists when there appears to be no INDEX possible.

    Let's try this just to see if we can get it to work differently - since you are in a development DB, I'm guessing you can create a table to test things with...

    Code:
    Create Table MyKeys (Pol_no somedatatype Primary Key Clustered)
    
    Insert into MyKeys Select Pol_no
    			From dbo.vwfeSpecialIssued
    			Where CI_Type is not null
    Do this outside of checking the execution plan - I just want to get a table of the primary keys desired.

    Then do this in a new window - checking the execution plan.

    Code:
    Select SI.* From dbo.MyKeys MK
          Left Join dbo.vwfeSpecialIssued SI on SI.Pol_No=MK.Pol_No
    It doesn't look any different from the first one.

    http://i16.photobucket.com/albums/b2...utionplan2.jpg

  28. #28
    MS SQL Powerposter szlamany's Avatar
    Join Date
    Mar 2004
    Location
    Connecticut
    Posts
    18,263

    Re: How I build my SQL strings

    Quote Originally Posted by disruptivehair
    It doesn't look any different from the first one.

    http://www.vbforums.com/images/ieimages/2006/11/1.jpg
    Did it run any faster?

    *** Read the sticky in the DB forum about how to get your question answered quickly!! ***

    Please remember to rate posts! Rate any post you find helpful - even in old threads! Use the link to the left - "Rate this Post".

    Some Informative Links:
    [ SQL Rules to Live By ] [ Reserved SQL keywords ] [ When to use INDEX HINTS! ] [ Passing Multi-item Parameters to STORED PROCEDURES ]
    [ Solution to non-domain Windows Authentication ] [ Crazy things we do to shrink log files ] [ SQL 2005 Features ] [ Loading Pictures from DB ]

    MS MVP 2006, 2007, 2008

  29. #29

    Thread Starter
    Hyperactive Member
    Join Date
    Oct 2006
    Location
    USA
    Posts
    476

    Re: How I build my SQL strings

    Quote Originally Posted by szlamany
    Did it run any faster?
    Nope...took three seconds.

  30. #30
    Code Monkey wild_bill's Avatar
    Join Date
    Mar 2005
    Location
    Montana
    Posts
    2,993

    Re: How I build my SQL strings

    I've recreated one of your routines using an enum as an input parameter. This will prevent misspelling a valid option, and will use intelisense so you don't need to find valid options when using it.
    VB Code:
    1. ' This function uses the tab the user is on and the value of the filter they've
    2.     ' selected to construct part of the 'WHERE' clause SQL Server will need to return
    3.     ' the appropriate data.  Example 'filter' values are York, Bankhall, CONTROL, etc.
    4.     ' This function does not actually include 'WHERE' or 'AND'; that part of the string
    5.     ' is constructed by another function.
    6.  
    7.     Public Function GetClause(ByVal columnName As Columns, ByVal strFilterValue As String) As String
    8.  
    9.         ' Check to make sure connection still exists.  If it doesn't, set it up.  If connection
    10.         ' is closed then open it.
    11.         ' Call CheckConnection
    12.  
    13.         Dim strClause As String
    14.  
    15.         ' Builds a SQL clause based on what tab the user is currently using; if the tab value
    16.         ' is "Headof" then no clause is built as no filter is actually being used.
    17.         Select Case columnName
    18.             Case Columns.HeadOf
    19.                 strClause = ""
    20.             Case Columns.Distributor
    21.                 strClause = "Distributor = " & "'" & "'" & strFilterValue & "'" & "'"
    22.             Case Columns.Site
    23.                 strClause = "Site = " & "'" & "'" & strFilterValue & "'" & "'"
    24.             Case Columns.Team
    25.                 strClause = "Team = " & "'" & "'" & strFilterValue & "'" & "'"
    26.             Case Columns.Parent
    27.                 strClause = "ParentCompany = " & "'" & "'" & strFilterValue & "'" & "'"
    28.             Case Columns.Other
    29.                 strClause = ""
    30.         End Select
    31.  
    32.         GetClause = strClause
    33.  
    34.     End Function
    35.     Public Enum Columns
    36.         HeadOf
    37.         Distributor
    38.         Site
    39.         Team
    40.         Parent
    41.         Other
    42.     End Enum

  31. #31

    Thread Starter
    Hyperactive Member
    Join Date
    Oct 2006
    Location
    USA
    Posts
    476

    Re: How I build my SQL strings

    Quote Originally Posted by wild_bill
    I've recreated one of your routines using an enum as an input parameter. This will prevent misspelling a valid option, and will use intelisense so you don't need to find valid options when using it.
    VB Code:
    1. ' This function uses the tab the user is on and the value of the filter they've
    2.     ' selected to construct part of the 'WHERE' clause SQL Server will need to return
    3.     ' the appropriate data.  Example 'filter' values are York, Bankhall, CONTROL, etc.
    4.     ' This function does not actually include 'WHERE' or 'AND'; that part of the string
    5.     ' is constructed by another function.
    6.  
    7.     Public Function GetClause(ByVal columnName As Columns, ByVal strFilterValue As String) As String
    8.  
    9.         ' Check to make sure connection still exists.  If it doesn't, set it up.  If connection
    10.         ' is closed then open it.
    11.         ' Call CheckConnection
    12.  
    13.         Dim strClause As String
    14.  
    15.         ' Builds a SQL clause based on what tab the user is currently using; if the tab value
    16.         ' is "Headof" then no clause is built as no filter is actually being used.
    17.         Select Case columnName
    18.             Case Columns.HeadOf
    19.                 strClause = ""
    20.             Case Columns.Distributor
    21.                 strClause = "Distributor = " & "'" & "'" & strFilterValue & "'" & "'"
    22.             Case Columns.Site
    23.                 strClause = "Site = " & "'" & "'" & strFilterValue & "'" & "'"
    24.             Case Columns.Team
    25.                 strClause = "Team = " & "'" & "'" & strFilterValue & "'" & "'"
    26.             Case Columns.Parent
    27.                 strClause = "ParentCompany = " & "'" & "'" & strFilterValue & "'" & "'"
    28.             Case Columns.Other
    29.                 strClause = ""
    30.         End Select
    31.  
    32.         GetClause = strClause
    33.  
    34.     End Function
    35.     Public Enum Columns
    36.         HeadOf
    37.         Distributor
    38.         Site
    39.         Team
    40.         Parent
    41.         Other
    42.     End Enum
    Hey, that's neat. I haven't really used enums before. Right now we're in the midst of a redesign test that may change some things; the DBAs keep asking us to hit a moving target so this code may change. This is cool though.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width