views:

369

answers:

4

I've got a method that uses sp_sproc_columns to find all parameters that need to be send for a stored procedure.

My question is how can I do something similar for inline SQL querys?

I want to get a list of the parameters the query is expecting.

Would the only way achieving this will be to use Regular expression? Any examples?


Example:

sql = "SELECT * FROM tbl WHERE id = @id AND name = @name"

I need to get a list that will contain @id and @name.

A: 

I suspect you would have to fully parse the SQL. It might be more complex than you expect, especially if your SQL is rude enough to contain things like:

  • internally executing a stored procedure using named parameters; for example EXEC MyProc @foo = @localArg - here only @localArg is needed for your query
  • having a string with 'some text @foo more text' in it -perhaps due to calling sp_ExecuteSQL (@foo is not part of your query)
Marc Gravell
I've got a solution for stored procedures, I use sp_sproc_columns.This should be a solution for simple inline query's only.
CD
Lets hope the "simple query" doesn't do an EXEC, then... ;-p
Marc Gravell
So is this really just a regular expression issue? What should be the expression?
CD
A: 

Check the following code to get the Parameters Name in Inline queries:

  Dim SQL As String =  "SELECT * FROM tbl WHERE id = @id AND name = @name"

  Dim arr = SQL.Split(" "c)
  For Each str As String In arr
    If str.StartsWith("@") Then
      MessageBox.Show(str)
    End If
  Next
Wael Dalloul
Thanks. This is a possible solution, but I'm not sure its the best practice...
CD
Splitting by space isn't robust; you could have "(@foo", ",@foo","+@foo", etc
Marc Gravell
yes you are right, it's not easy to collect all the cases and put it in the split char array.
Wael Dalloul
@ could also legimately appear as part of a string in the SQL
CodeByMoonlight
A: 

In the case of the SQL Server provider, and if you are using a stored procedure, you can use the SqlCommandBuilder.DeriveParameters method.

For other cases, I've always found that the best way, if your commands are at least constant, is to use the Designer support in Visual Studio. Either create a strongly-typed DataSet and add a query, or do it the old fashioned way and drag a SqlConnection and SqlCommand onto a design surface. In either case, when you configure the CommandText to be a statement with parameters, the Designer will ask you if you want the Parameters collection filled in. The result is that it will have generated the code to create a SqlCommand with the parameters collection already created. All you'll need to do is set the parameter values, and you're all set.

John Saunders
+1  A: 

The way to use a RegularExpression isn't too hard either - if that's the way you prefer to find your parameters:

   Regex r = new Regex(@"(?<Parameter>@\w*)", RegexOptions.Compiled);

   foreach (Match m in r.Matches(sqlStatement))
   {
      if(m.Success)
      {
         string parameterName = m.Value;
      }
   }

However, this is only going to give you the parameter names - it can't possibly guess or determine the parameter type or any of the other parameter metadata - so in the end, this might be a quick, but probably also "dirty" way to do it.

Marc

marc_s
Why is it dirty? I've got a strongly typed object with all the values I'll need, and every member will have an attribute that will describe it's DB type. Does it sound dirty? Is it really a bad practice?
CD
Well, you can only extract the names of the parameters, and as Marc Gravell rightfully pointed out, this simplistic Regex can be fooled by simple edge cases - but if it's good enough for most of your cases, enjoy! ;-)
marc_s