I've recently been trying to figure out a way to get parameterized queries to work and i think i'm almost there but seem to be getting an error when executing my query
Here's the code
Dim LogData2 As sterm.MarkData = New sterm.MarkData()
Dim query As String = ("Select * from openquery (db, 'SELECT * FROM table WHERE investor=#investor')")
Dim cmd As New SqlCommand(query)
cmd.Parameters.AddWithValue("#investor", 34)
Dim drCode2a As DataSet = LogData2.StermQ3(query)
I've debugged it and it doesn't seem to be putting the parameter into the query.
"Select * from openquery (db, 'SELECT * FROM table WHERE investor=#investor')"
That's what i get when i debug the line Dim drCode2a As DataSet = LogData2.StermQ3(query)
Any ideas what i'm doing wrong?
SOLUTION
Here's how I solved my problem
Dim conn As SqlConnection = New SqlConnection("server='h'; user id='w'; password='w'; database='w'; pooling='false'")
conn.Open()
Dim query As New SqlCommand("DECLARE #investor varchar(10), #sql varchar(1000) Select #investor = 69836 select #sql = 'SELECT * FROM OPENQUERY(db,''SELECT * FROM table WHERE investor = ''''' + #investor + ''''''')' EXEC(#sql)", conn)
dgBookings.DataSource = query.ExecuteReader
dgBookings.DataBind()
Thanks for the help
Ok Jamie taylor I will try to answer your question again.
You are using OpenQuery becuase you are probably using a linked DB
Basically the problem is the OpenQuery Method takes a string you cannot pass a variable as part of the string you sent to OpenQuery.
You can format your query like this instead. The notation follows servername.databasename.schemaname.tablename. If you are using a linked server via odbc then omit databasename and schemaname, as illustrated below
Dim conn As SqlConnection = New SqlConnection("your SQL Connection String")
Dim cmd As SqlCommand = conn.CreateCommand()
cmd.CommandText = "Select * db...table where investor = #investor"
Dim parameter As SqlParameter = cmd.CreateParameter()
parameter.DbType = SqlDbType.Int
parameter.ParameterName = "#investor"
parameter.Direction = ParameterDirection.Input
parameter.Value = 34
Related
I am trying to store the value of an identity value from table after inserting it into a row.
I want to store the value in currentID so I can store the value in another table which could be added more than once.
Any help or advice would be great!
Dim currentID As Integer
Dim cmd As New System.Data.SqlClient.SqlCommand
cmd.CommandType = System.Data.CommandType.Text
cmd.CommandText = "INSERT INTO table (Databasevalue) VALUES ('" + formvalue + "');"
cmd.Connection = sqlconninsertDB
sqlconninsertDB.Open()
cmd.ExecuteNonQuery()
**currentID = [get and store value]**
sqlconninsertDB.Close()
You can try adding this SELECT to your command:
cmd.CommandText = "INSERT INTO table (Databasevalue) VALUES ('" + formvalue + "'); SELECT SCOPE_IDENTITY()"
And execute query like this:
Dim currentID as Integer = cmd.ExecuteScalar()
Instead of .ExecuteNonQuery()
Side note: Try not to use string concatenations when constructing inline-commands. Rather look into parametrized queries.
With Sql Server you could pass two sql commands separating them with a semicolon.
The second command is a SELECT SCOPE_IDENTITY() and this returns the last ID inserted in this scope.
You could execute both commands and retrieve the result with ExecuteScalar
Please, take note to use a parameterized query instead of a string concatenation to avoid Sql Injection attacks and parsing problems.
Dim currentID As Integer
Dim cmd As New System.Data.SqlClient.SqlCommand
cmd.CommandType = System.Data.CommandType.Text
cmd.CommandText = "INSERT INTO table (Databasevalue) VALUES (#formval); " +
"SELECT SCOPE_IDENTITY()"
cmd.Connection = sqlconninsertDB
cmd.Parameters.AddWithValue("#formval", formValue)
sqlconninsertDB.Open()
currentid = cmd.ExecuteScalar()
sqlconninsertDB.Close()
I have the following SQL Statement written in SQL Server 2008 which isn't returning a value for the OUTPUT Parameter even though there is data in the table. I added static values and ran the query alone and it produced a record so I am not sure if it has something to do with my Stored Procedure or my VB.NET Code.
ALTER Procedure [dbo].[GetGenInfo_Delete01_01_22]
#IDX int,
#FPath varchar(100) OUTPUT
AS
Begin
SELECT #FPath = FilePath FROM GENINFO_E1_01_22 WHERE ID = #IDX
DELETE
FROM GenInfo_E1_01_22
WHERE ID = #IDX
END
My VB Code
Using con As New SqlConnection(connstr)
Using cmd As New SqlCommand()
cmd.CommandType = CommandType.StoredProcedure
cmd.CommandText = "GetGenInfo_Delete01_01_22"
cmd.Parameters.Add("IDX", ID)
cmd.Parameters.Add("#FPath", SqlDbType.VarChar, 100)
cmd.Parameters("#FPath").Direction = ParameterDirection.Output
cmd.Connection = con
con.Open()
GridView1.DataSource = cmd.ExecuteReader()
GridView1.DataBind()
con.Close()
End Using
End Using
An output parameter does not show up in the result set. So you can't read it with ExecuteReader().
You can read it like:
Dim result as String = cmd.Parameters("#FPath").Value
I have the below stored procedure in SQL Server 2008 which is not generating any errors in SQL, but is generating one in the web application which states "'GetGenInfo_Delete01_01_22' expects parameter '#FPath', which was not supplied". I am fairly novice at SQL, but what I am trying to do is return a field to VB.NET before the row is deleted. Any suggestions would be very helpful.
ALTER Procedure [dbo].[GetGenInfo_Delete01_01_22]
#IDX int,
#FPath varchar(100) OUTPUT
AS
Begin
SELECT #FPath = (SELECT FilePath FROM GenInfo_E1_01_22 Where ID=#IDX)
DELETE
FROM GenInfo_E1_01_22
WHERE ID = #IDX
END
Here is the VB code calling the stored proc
Using con As New SqlConnection(connstr)
Using cmd As New SqlCommand()
cmd.CommandType = CommandType.StoredProcedure
cmd.CommandText = "GetGenInfo_Delete01_01_22"
cmd.Parameters.Add("IDX", ID)
Dim returnParameter = cmd.Parameters.Add("#FPath", SqlDbType.VarChar)
returnParameter.Direction = ParameterDirection.ReturnValue
cmd.Connection = con
con.Open()
GridView1.DataSource = cmd.ExecuteReader()
GridView1.DataBind()
con.Close()
End Using
End Using
You're creating parameter returnParameter, but you're not adding it to the parameters collection. Use cmd.Parameters.Add(returnParameter) prior to DB Call.
You could add an FPath parameter to cmd. Do it like this:
SqlParameter fpath = new SqlParameter();
fpath.Direction = ParameterDirection.Output;
fpath.ParameterName = "#FPATH";
cmd.Parameters.Add(p);
I'm having some trouble writing a query using variables. Here's my code
Dim bondnumber as String = "69836"
Dim PasswordCheck As String = "DECLARE #investor varchar(10),
#thepassword varchar(20), #linkedserver2 varchar(25), #sql varchar(1000) "
PasswordCheck += "SELECT #investor = '" & bondnumber & "',
#linkedserver2 = 'binfodev', "PasswordCheck += "#sql = 'SELECT * FROM ' +
#linkedserver2 + ' WHERE bondno = ''#investor'' ' EXEC(#sql)"
It doesn't seem to be passing the variables properly in the query and i'm not sure where i'm going wrong
any ideas?
What is the problem you are seeing specifically? More info would help.
What I can tell, is that you're code translates to a long line of SQL (substituting '69836' for bondnumber)
DECLARE #investor varchar(10), #thepassword varchar(20), #linkedserver2 varchar(25), #sql varchar(1000) SELECT #investor = '69836', #linkedserver2 = 'binfodev', #sql = 'SELECT * FROM ' + #linkedserver2 + ' WHERE bondno = ''#investor'' ' EXEC(#sql)
I'll bet if you execute that in a query window it will fail. Try adding ; at the end of each logical statement.
Have you considered just making this code a stored procedure and passing params to this? Code like this is pretty hazardous (SQL Injection), hard to read, and just a bit ugly in general.
Sample Stored Procedure Code:
CREATE PROCEDURE dbo.usp_MyStoredProcedure
#Param1 INT = NULL
AS
SELECT * FROM MyTable Where Col1 = #Param1
#Jamie - Well I personally tend to find it is much clearer to break things a part a little bit although its not technically necessary. I am just saying to build your parameter variables separately and then add them as parameterized (something like the following):
Dim sql As String = "SELECT * FROM #LinkedServer WHERE bondno = #BondNumber"
Dim c As New SqlConnection("Your Connection String Here")
Dim cmd As SqlCommand = c.CreateCommand()
With cmd
.CommandType = CommandType.Text
.CommandText = sql
.Parameters.Add(New SqlParameter("#LinkedServer", SqlDbType.VarChar)).Value = "binfodev"
.Parameters.Add(New SqlParameter("#BondNumber", SqlDbType.VarChar)).Value = "69836"
End With
Dim dt As New DataTable
Dim da As New SqlDataAdapter(cmd)
da.Fill(dt)
I have this code
UPDATE OPENQUERY (db,'SELECT * FROM table WHERE ref = ''"+ Ref +"'' AND bookno = ''"+ Session("number") +"'' ')
How would I prevent SQL Injections on this?
UPDATE
Here's what i'm trying
SqlCommand cmd = new SqlCommand("Select * from Table where ref=#ref", con);
cmd.Parameters.AddWithValue("#ref", 34);
For some reason everything I try and add it doesn't seem to work I keep getting SQL Command mentioned below.
The error is this
'SqlCommand' is a type and cannot be used as an expression
I'm taking over someone else's work so this is all new to me and I would like do things the right way so if anyone can provide any more help on how to make my query above safe from SQL injections then please do.
UPDATE NO 2
I added in the code as VasilP said like this
Dim dbQuery As [String] = "SELECT * FROM table WHERE ref = '" & Tools.SQLSafeString(Ref) & "' AND bookno = '" & Tools.SQLSafeString(Session("number")) & "'"
But I get an error Tools is not declared do I need to specify a certain namespace for it to work?
UPDATE
Has anyone got any ideas on the best of getting my query safe from SQL injection without the errors that i'm experiencing?
UPDATE
I now have it so it work without the parameters bit here's my updated source code any idea why it won't add the parameter value?
Dim conn As SqlConnection = New SqlConnection("server='server1'; user id='w'; password='w'; database='w'; pooling='false'")
conn.Open()
Dim query As New SqlCommand("Select * from openquery (db, 'Select * from table where investor = #investor ') ", conn)
query.Parameters.AddWithValue("#investor", 69836)
dgBookings.DataSource = query.ExecuteReader
dgBookings.DataBind()
It works like this
Dim conn As SqlConnection = New SqlConnection("server='server1'; user id='w'; password='w'; database='w'; pooling='false'")
conn.Open()
Dim query As New SqlCommand("Select * from openquery (db, 'Select * from table where investor = 69836') ", conn)
dgBookings.DataSource = query.ExecuteReader
dgBookings.DataBind()
The error i'm getting is this
An error occurred while preparing a query for execution against OLE DB provider 'MSDASQL'.
And it's because it isn't replacing the #investor with the 69836
Any ideas?
SOLUTION
Here is how I solved my problem
Dim conn As SqlConnection = New SqlConnection("server='h'; user id='w'; password='w'; database='w'; pooling='false'")
conn.Open()
Dim query As New SqlCommand("DECLARE #investor varchar(10), #sql varchar(1000) Select #investor = 69836 select #sql = 'SELECT * FROM OPENQUERY(db,''SELECT * FROM table WHERE investor = ''''' + #investor + ''''''')' EXEC(#sql)", conn)
dgBookings.DataSource = query.ExecuteReader
dgBookings.DataBind()
Now I can write queries without the worry of SQL injection
Try using a parameterized query here is a link http://www.aspnet101.com/2007/03/parameterized-queries-in-asp-net/
Also, do not use OpenQuery... use the this to run the select
SELECT * FROM db...table WHERE ref = #ref AND bookno = #bookno
More articles describing some of your options:
http://support.microsoft.com/kb/314520
What is the T-SQL syntax to connect to another SQL Server?
Edited
Note: Your original question was asking about distributed queries and Linked servers. This new statement does not reference a distributed query. I can only assume you are directly connecting to the database now. Here is an example that should work.
Here is another reference site for using SqlCommand.Parameters
SqlCommand cmd = new SqlCommand("Select * from Table where ref=#ref", con);
cmd.Parameters.Add("#ref", SqlDbType.Int);
cmd.Parameters["#ref"] = 34;
Edited:
Ok Jamie taylor I will try to answer your question again.
You are using OpenQuery becuase you are probably using a linked DB
Basically the problem is the OpenQuery Method takes a string you cannot pass a variable as part of the string you sent to OpenQuery.
You can format your query like this instead. The notation follows servername.databasename.schemaname.tablename. If you are using a linked server via odbc then omit databasename and schemaname, as illustrated below
Dim conn As SqlConnection = New SqlConnection("your SQL Connection String")
Dim cmd As SqlCommand = conn.CreateCommand()
cmd.CommandText = "Select * db...table where investor = #investor"
Dim parameter As SqlParameter = cmd.CreateParameter()
parameter.DbType = SqlDbType.Int
parameter.ParameterName = "#investor"
parameter.Direction = ParameterDirection.Input
parameter.Value = 34
Use parameters instead of concatenating your SQL query.
Assuming your database engine being SQL Server, here's a piece of code which I hope will help.
Using connection As SqlConnection = new SqlConnection("connectionString")
connection.Open()
Using command As SqlCommand = connection.CreateCommand()
string sqlStatement = "select * from table where ref = #ref and bookno = #bookno";
command.CommandText = sqlStatement
command.CommandType = CommandType.Text
Dim refParam As SqlDataParameter = command.CreateParameter()
refParam.Direction = ParameterDirection.Input
refParam.Name = "#ref"
refParam.Value = Ref
Dim booknoParam As SqlDataParameter = command.CreateParameter()
booknoParam.Direction = ParameterDirection.Input
booknoParam.Name = "#bookno"
booknoParam.Value = Session("number")
Try
Dim reader As SqlDataReader = command.ExecuteQuery()
' Do your reading job here...'
Finally
command.Dispose()
connection.Dispose()
End Try
End Using
End Using
To sum it all up, avoid SQL statement concatenation at all cost, and use parameterized quesries!
Here is an interesting link that brings you through SQL injection problem resolution on MSDN:
How To: Protect From SQL Injection in ASP.NET
use sqlparameters like:
SqlCommand cmd = new SqlCommand("Select * from Table where id=#id", con);
cmd.Parameters.AddWithValue("#id", 34);
you can use parameterized queries.
http://www.functionx.com/aspnet/sqlserver/parameterized.htm
SqlCommand cmd = new SqlCommand("Select * from Table where ref=#ref", con);
cmd.Parameters.AddWithValue("#ref", 34);
it does not work because it is written in C#, not VB.
Try something like
Dim cmd As New SqlCommand("Select * from Table where ref=#ref", con)
cmd.Parameters.AddWithValue("ref", 34)
My preferred way is to let Visual Studio handle it all by creating a DAL:
http://www.asp.net/data-access/tutorials/creating-a-data-access-layer-cs
Use LINQ. It parametrizes queries automatically.
Check out ORM as an alternative (very good way to go if you are building something medium-sized or big). It takes a little time to configure it, but then development becomes VERY fast. You choose from the native, Linq to SQL or Entity Framework, OR, try any other ORM which works with .NET.