If the query is a stored procedure, you can use SqlCommandBuilder.DeriveParameter
s (see How can I retrieve a list of parameters from a stored procedure in SQL Server). However that unfortunately only works for CommandType=StoredProcedure
In SQL Server 2012 (and above) you can use sp_describe_undeclared_parameters
(see https://msdn.microsoft.com/en-us/library/ff878260.aspx)
Doesn't seem like there is any alternative for lower versions other than parsing the SQL query text directly (regex, or possibly using the SQLDOM that ships with SSDT (or via nuget): https://blogs.msdn.microsoft.com/arvindsh/2013/04/04/using-the-transactsql-scriptdom-parser-to-get-statement-counts/ )
Edit: simple F# example of finding parameters using the Microsoft.SqlServer.TransactSql.ScriptDom
nuget:
#r "Microsoft.SqlServer.TransactSql.ScriptDom"
open System.IO
open System.Collections.Generic
open Microsoft.SqlServer.TransactSql.ScriptDom
let query = @"select * from dbo.Customers where FirstName=@FirstName"
let parser = new TSql120Parser(true)
let errors : ref<IList<ParseError>> = ref(null)
let frag = parser.Parse(new StringReader(query), errors) // the actual work
frag.ScriptTokenStream
|> Seq.filter (fun f -> f.TokenType = TSqlTokenType.Variable)
|> Seq.iter (fun t -> (printfn "Type = %A; Name = %s" t.TokenType t.Text))
outputs
Type = Variable; Name = @FirstName
...however if the script involves temporary variables you can easily get false positives, eg:
declare @temp nvarchar(50) = @FirstName
select * from dbo.Customers where FirstName=@temp
...finds @temp twice, and @FirstName