![]() |
Click here to advertise with us
|
|
|||||||
| Database General Discussion General discussion on database related topics |
![]() |
|
|
LinkBack | Thread Tools | Display Modes |
|
|||
|
There are times when parameter queries won't work. They are not very flexible.
Let's say you make a custom query dialog, for flexible reporting. User enters one/more parameters: one/more customer names, a dollar amount, less than or greater than (e.g. order amounts <$100, or >$100), and one of several possible sort orders. You can build that complex query easily and briefly by building up a SQL string, but unless I'm mistaken, parameters won't do it. (Well, I suppose you could have many different parameterized queries, depending on which parameters the user chooses to supply, but that grows huge fast with permutations) Also, the example you give is ugly code; bad primarily for being a classic jumble. The embedded functions ought to be separated out, assigned to temporary variables; this would ease both reading and debugging. It seems to me that although parameters are more technically correct, and will avoid a few types of problems, they're not nearly as elegant (quick and tidy and self-contained) as building the sql string. It doesn't take much to build the sql string correctly and safely, anyway. |
|
||||
|
Parameters are the the input values (and types) of a query and only that. What you are talking about is dynamically build a query, which may be valid in some cases. But never (never ever!) mix the value in that build, add it as a parameter.
Code:
'default command
Dim cmd As New SqlCommand("SELECT * FROM something")
'add condition
cmd.CommandText &= " WHERE part = @part"
'add parameter
cmd.Parameters.Add("@part", SqlDbType.NText)
'set parameter value
cmd.Parameters("@part").Value = SomeTextBox.Text
__________________
Some useful links: Learning videoes, Code Samples, WMI Code Creator, MSDN, The Code Project, WindowsClient.net, ASP.net, W3 Schools, Regular-Expressions.info, GDI+ FAQ
How to format posts with code blocks etc - present the problem/post properly ![]() |
|
|||
|
John,
"Never (never ever!)" are very strong words. You give no reason or explanation. Passed parameters are a feature in ADO, which talk to a feature in (generic) SQL server. Just because the features exist doesn't make an imperative to use them. As I see it, SQL is an ancient language which was updated a couple decades ago to include parameter-passing. But again, just because the feature is there doesn't give it any advantage over more traditional (and less verbose, less cryptic) ways of using parameters. I could be wrong, but I don't know of any compelling reason to avoid old-fashioned string building. I think that IF the failure to use formal parameter passing caused:
...then it would be good to avoid the simpler way, at least in some cases. But it appears to me that this edict of style generates from a devotion to Microsoft's database technology of the week, not from any compelling reason. For example, in Access (JET) it was advisable to use formal parameters, because there was a performance hit with freeform queries. But if it's a rare routine that does it, or a small database, it doesn't matter. I think the base imperative is do whatever is simpler and more brief (if it won't cause problems). I'm not saying your way is bad. It's probably widely preferred for enterprise projects. But I don't see any reason why it's an issue for "never", much less "never (never ever!)". PS: If you get a chance, check out Cache. See the demo videos. Here's a technology that makes a joke of SQL. I think it's pretty important to remember that the whole massive architecture of ADO is built around ancient and outdated technology; important to keep perspective on ideas of "correct". |
|
|||||||||||||
|
Quote:
Quote:
Quote:
Quote:
a) convert your value from string to native datatype and do the relevant comparison b) convert every value in the table from native type to string, then do a string comparison Do you even know what it's doing? Another way to present this as daft, is to tell me, what date is this: "030201" Cmon.. what is it? 1st Feb 2003? 1st Feb 1903? 2nd Mar 2001? 2nd Mar 1901? Here's an even more stupid one: "191211" 11th Dec 1919? 11th Dec 2019? If the format was "yyyyMd" that could even be the 1st Jan 1912. Representing a Date as a String is silly.. it leads to your "unpredictable bugs" list entry. Parsing it leads to your performance hit. Converting all dates in a million row table to strings really leads to a performance hit. Take your app to america where the users date format is different leads to your incompatibility. Quote:
Quote:
![]() Quote:
Quote:
Quote:
![]() Quote:
![]() Quote:
Quote:
Quote:
|
|
|||||
|
Quote:
Quote:
Quote:
Quote:
Quote:
I don't envy you for putting your pride in intense conformity to excessive structure. I'm not interested in fighting with you. I said what I had to say, I stand by it, and perhaps it will be educational for others, as you said. |
|
|||||||
|
Sure it does; youre asserting that String suits every need and specialist data types are unnecessary.. You also didnt actually respond to the point
Quote:
Quote:
Quote:
Quote:
Converting between strings and datetimes Leaving datetimes as they are ? Quote:
Addiitonally, though the concept may be new to you, it's is well encapsulated too. In your strive to "mkae things simpler" you might actually be making things more complex because youre filling your button handler code full of SQL statements - statements that may look pretty in your eyes, but they are in the wrong place, unsafe, slow and inefficient. Quote:
Stick around the forums and read a little - you might come around to liking this parameterisation lark ![]() Quote:
|
|
|||
|
I do agree that parametrized queries are the best way... Most of the time... But I don't think programming has any invariable truth that no one must stray from. Here are a few examples I can think of where I would consider the alternative.
You want to use the filter from a DataView as the WHERE clause for your query. If you do control the filter on the Dataview, you can insure it always has a syntax that won't break the SQL and use it when it is simpler to do so. You need to parse a single WHERE clause out of a whole form's worth of filters, some empty, some not. You want to use a JOIN on a few other tables only when the additional data is actually used by a filter (I can only guess there might be a notable performance gain from this, but performance issues are difficult to guess right). Obviously, this is bad : Code:
Dim oc as New OracleCommand( _
"SELECT a || '" & TextBox1.Text & "' as Thing FROM table1 " & _
"WHERE col1 = '" & TextBox2.Text.Replace("'"c, "''") & "' OR c" & _
"ol3 LIKE '" & TextBox3.Text & "%' AND col4date = #" & _
dateTimePicker1.Value.ToString("MM/dd/yyyy HH:mm:ss") & "#" & _
" AND someListCol5 NOT IN('" & TextBox6.Text.Split(","c)(0) & "'," & _
"'" & s & "','" & CInt(iText).ToString("000") &"')")
Code:
dim conditionBuilder as new StringBuilder()
if (txtFilterA.Text.Length > 0) then
AddCondition(conditionBuilder, "a = '" + txtFilterA.Text.replace("'", "''") + "'")
endif
if (txtFilterB.Text.Length > 0) then
AddCondition(conditionBuilder, "b = '" + txtFilterB.Text.replace("'", "''") + "'")
endif
' Lots of conditions
return "SELECT a FROM SomeTable " + conditionBuilder.ToString()
Code:
private sub AddCondition(conditionBuilder as StringBuilder, newCondition as String)
if (conditionBuilder.Length > 0) then
conditionBuilder.Append(" AND (")
else
conditionBuilder.Append("WHERE (")
endif
conditionBuilder.Append(newCondition)
conditionBuilder.Appent(")");
end sub
Don't think I actually recommend anyone to start concatenating Strings for fun, but the parametrized query might force you to build a gigantic SQL Query that can accommodate the various null values for non existent filters out of the 20 filters you may have. That means a single String that's defined over 10 - 20 lines. Did you forget to put a space on the line break? Lots of things can go wrong. Less that the String concatenation, obviously, but still. On the other hand, this method allows you to set the conditions you need in bits of 30 - 40 characters each. You can step through each line and see when the condition went wrong which makes it easier to debug than the parametrized query. I admit it lacks typed parameters which would avoid your having to think about the " ' " character around and within strings and I have yet to work with dates that way. I haven't had the time to look at how the current parametrized queries do that yet, maybe you can use a Microsoft provided method somewhere. Otherwise you can just add value formatting static methods in the SqlBuilder class.
__________________
The human mind's capability to comprehend abstract concepts is limited to the vocabulary it can use to describe it. The more precise the building blocks, the more complex the thoughts that can emerge... Sounds like the evolution of programming languages doesn't it? |
|
||||
|
Quote:
Mmhhhh, but answer me (i.e. defy) this: If youre capable of concatenating a string on strSql &= "colName = '" & txtCol.Text & "'" Youre certainly capable of concatenating a parameter on: strSql &= "colName = @colname" cmd.Parameters.Add("@colName", txtCol.Text - I wont wind on about datatypes and the foolishness of trying to represent everything as a string yet again, but that's a major consideration for parameters. You say there are no invariable truths, and for the most part, I agree, but one thing you should never do, because there is no good reason for it, and no situation that requires it, is use string-value concatenation to build a query SQL. String-parameter concatenation fine, but string-value concat; just dont do it! I'll give you that as an invariable truth. the only time it will actually fail is when something is not parameterisable, and in that case, there are a raft of reasons why we typically dont do that kind of thing (we prepare queries that the db can plan ahead) (Are you sure you thought your argument through?) ps; when youre concatting your where clauses on, its far more trick to just to this: strSql = "SELECT * FROM table WHERE 1=1" strSql &= " AND col = @col" .. strSql &= " AND col10 = @col10" |
|
|||
|
Quote:
And you still cannot see the values in the SQL query to debug it. Say you use a combo box to tell which color to look for and the default value "unknown" should be removed from the search because it is a special data (somehow). Now, you forgot to put the code for that says "Unknown" is actually null and you accidentally run the query with the value whatever the other search criteria are. The only info you have is that the search always return zero records. You run the search with no filter and look at the query in the SqlCommand just before it is run. Would you rather see : Code:
SELECT Name FROM MyTable WHERE (Name = @Name OR @Name IS NULL) AND (Color = @Color OR @Color IS NULL) AND (SomethingElse = @SomethingElse OR @SomethingElse IS NULL) ... ORDER BY Name Or isn't easier to look at this : Code:
SELECT Name FROM MyTable WHERE (Color = 1) It is true that parametrized query produce clean code to use and create, but you reach a similar point of simplicity by encapsulating the query creation in an object. Add a few static methods to convert the DateTime object or raw String to a String ready for adding to the query and you got something that is nearly as clean as the parametrized query. Without the complexity in debugging and the limitations. -- One more situation I would think about this is when you want the user to use a CheckedListBox to check the categories he want to search for. Parametrizing a query like this : Code:
SELECT name FROM MyTable WHERE CategoryId IN {@CategoryId1, @CategoryId2, ... @CategoryIdN}
Code:
SELECT name FROM MyTable WHERE CategoryId IN @CategoryIdList -- Quote:
__________________
The human mind's capability to comprehend abstract concepts is limited to the vocabulary it can use to describe it. The more precise the building blocks, the more complex the thoughts that can emerge... Sounds like the evolution of programming languages doesn't it? Last edited by Stonkie; 05-11-2008 at 2:38 AM. |
![]() |
| Bookmarks |
| Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
| Thread Tools | |
| Display Modes | |
|
|