This question already has answers here:
How to use a variable for the database name in T-SQL?
(4 answers)
Closed 10 years ago.
I can't change the database file size with a C# query. For some reason I get an exception: "Incorrect syntax near '#databaseName'.
This is the code that executed the query:
command = connection.CreateCommand();
command.CommandText = #"
ALTER DATABASE #databaseName
MODIFY FILE
(NAME = #databaseFile, SIZE = #newSize)
";
dbParam = command.CreateParameter();
dbParam.ParameterName = "databaseFile";
dbParam.Value = dbFileName;
command.Parameters.Add(dbParam);
dbParam = command.CreateParameter();
dbParam.ParameterName = "newSize";
dbParam.Value = newSize;
command.Parameters.Add(dbParam);
dbParam = command.CreateParameter();
dbParam.ParameterName = "databaseName";
dbParam.Value = databaseName;
command.Parameters.Add(dbParam);
command.ExecuteNonQuery();
Now there might be several problems. Firstly the database is on a different machine so wouldn't the db file path be different?
Some things cannot be parameterized. That includes things like table and column names in DML, but includes most of DDL. It is not expecting, and cannot process, parameters in this scenario.
To check this; just run it in SSMS, declaring the variables ahead of time and giving them values. You will find the error message is the same. If it doesn't work in SSMS it is very unlikely to work from ADO.NET.
Related
This question already has answers here:
A table name as a variable
(10 answers)
Closed 1 year ago.
I am building a sql query string like this:
var sqlDailyDataForOption = #"select underlying_symbol, quote_date
FROM [#val6]
Later I add the command line parameters thus:
command.Parameters.AddWithValue("#val6", o.underlying_symbol + "_1545");
I get an exception when I try to execute the query string:
using (SqlDataReader reader = command.ExecuteReader())
{
- $exception {"Invalid object name '#val6'."} System.Data.SqlClient.SqlException
However, if I hardwire the value o.underlying_symbol + "_1545" it works fine.
Is it that command-parameters can't be dynamically created in a FROM ?
You would have to use dynamic SQL and safely inject the value of the dynamic object into the statement. I'm not a C# developer, but I suspect it'll look something like this:
var sqlDailyDataForOption = #"DECLARE #SQL nvarchar(MAX) = N'SELECT underlying_symbol, quote_date FROM dbo.' + QUOTENAME(#var6) + N';'; EXEC sys.sp_executesql #SQL;"
command.Parameters.Add("#Var6", SqlDbType.NVarChar, 128).Value = o.underlying_symbol + "_1545"
try this
var val16=o.underlying_symbol + "_1545";
var sqlDailyDataForOption = $"select underlying_symbol, quote_date FROM [{val16}]";
but please remember about possibility sql script injection attack in this case and check val16 for malicious words like delete.
This question already has answers here:
Call a stored procedure with parameter in c#
(7 answers)
Closed 5 years ago.
I've got a stored procedure that runs just fine if I execute it on my server and if I build an execute statement with my parameters (e.g. string sql = "Exec Get_Data '" + St + " ' ...". However, as soon as I try:
string strQS = "Exec Get_Data #param1,#param2,#param3,#param4..."
using (SqlConnection conSQL = new SqlConnection(connectionString))
{
using (SqlCommand cmdSQL = new SqlCommand(strQS, conSQL))
{
conSQL.Open();
cmdSQL.Parameters.AddWithValue("#param1", SqlDbType.VarChar).Value = St;
cmdSQL.Parameters.AddWithValue("#param2", SqlDbType.VarChar).Value = Loc;
...
I get the following error:
Column name or number of supplied values does not match table definition.
Obviously if I can run it before I use a parametrized query I don't have anything wrong with my column names, but something with how my values are being treated. All my variables are of type string and the SQL Server is expecting all parameters to by of type varchar...Any ideas?
You need to change your command type to StoredProcedure.
And then drop the EXEC and all the parameters from your string.
cmdSQL.CommandType = CommandType.StoredProcedure;
string strQS = "Get_Data"
This question already has answers here:
SqlCommand with Parameters
(3 answers)
Closed 8 years ago.
Hi this is my query
SELECT StraightDist FROM StraightLineDistances
WHERE (FirstCity='007' AND SecondCity='017');
How can I pass this in to sql statement?
I want to replace the city numbers '007' and '017' with variables
string destcity;
string tempcityholder1;
What I tried is this
SqlCommand mybtncmd2 = new SqlCommand("SELECT StraightDist FROM StraightLineDistances WHERE (FirstCity='" + tempcityholder1 + "' AND SecondCity='" + destcity + "');", mybtnconn2);
it didn't give me the expected output.
But when i tried with the original sql as given below it worked.
SqlCommand mybtncmd2 = new SqlCommand("SELECT StraightDist FROM StraightLineDistances WHERE (FirstCity='007' AND SecondCity='017');", mybtnconn2);
Can anyone point me the error here?
or a better solution.
This is for a personal application, security is not a must, so no need of parametrized queries. And I don't know how to implement parametrized queries with multiple parameters. If anyone can explain how to use a parametrized query it's great and I would really appreciate that. But just for the time being I need to correct this.
Any help would be great..
OK if with parametrized query
MY Work looks like this
SqlConnection mybtnconn2 = null;
SqlDataReader mybtnreader2 = null;
mybtnconn2 = new SqlConnection("");
mybtnconn2.Open();
SqlCommand mybtncmd2 = new SqlCommand("SELECT StraightDist FROM StraightLineDistances WHERE (FirstCity='007' AND SecondCity='017');", mybtnconn2);
mybtnreader2 = mybtncmd2.ExecuteReader();
while (mybtnreader2.Read())
{
MessageBox.Show(mybtnreader2.GetValue(0) + "My btn readre 2 value");
}
Can anyone give me a solution which doesn't complicate this structure.
If I use a parametrized query how can I edit
mybtnreader2 = mybtncmd2.ExecuteReader();
This statement?
This is the way to use parametrized queries:
string sqlQuery="SELECT StraightDist FROM StraightLineDistances WHERE (FirstCity= #tempcityholder1 AND SecondCity=#destcity);"
SqlCommand mybtncmd2 = new SqlCommand(sqlQuery, mybtnconn2);
mybtncmd2.Parameters.AddWithValue("tempcityholder1", tempcityholder1 );
mybtncmd2.Parameters.AddWithValue("destcity", destcity);
It's always good practice to use parameters, for both speed and security. A slight change to the code is all you need:
var mybtncmd2 = new SqlCommand("SELECT StraightDist FROM StraightLineDistances WHERE FirstCity=#City1 AND SecondCity=#City2;", mybtnconn2);
mybtncmd2.Parameters.AddWithValue("#City1", "007");
mybtncmd2.Parameters.AddWithValue("#City2", "017");
Use prepared statements: it's both easy and secure.
command.CommandText =
"INSERT INTO Region (RegionID, RegionDescription) " +
"VALUES (#id, #desc)";
SqlParameter idParam = new SqlParameter("#id", SqlDbType.Int, 0);
SqlParameter descParam =
new SqlParameter("#desc", SqlDbType.Text, 100);
You really won't do this, because this is an open door to SQL injection.
Instead you should use Stored Procedures for that approach.
In case your not familiar with SQL injection, let's make it clear:
Assume that you have a database with a table called 'T_USER' with 10 records in it.
A user object has an Id, a Name and a Firstname.
Now, let's write a query that select a user based on it's name.
SELECT * FROM T_USER WHERE Name= 'Name 1'
If we take that value from C#, this can really take unexpected behaviour.
So, in C# code we will have a query:
string queryVal;
var command = "SELECT * FROM T_USER WHERE Name = '" + queryVal + "'";
As long as the user is nice to your application, there's not a problem.
But there's an easy way to retrieve all records in this table.
If our user passes the following string in QueryVal:
demo' OR 'a' = 'a
Then our query would become:
SELECT * FROM T_USER WHERE Name = 'demo' OR 'a' = 'a'
Since the second condition is always true, all the records are retrieved from this table.
But we can even go further:
If the same user uses the following value in queryVal:
demo'; DELETE FROM T_USER--
The full query becomes:
SELECT * FROM T_USER WHERE Name = 'demo'; DELETE FROM T_USER--'
And all our records our gone.
And we can even go further by dropping the table:
queryVal needs to be:
demo'; DROP TABLE T_USER--
I think you get it. For more information google on Sql Injection:
I'm trying to execute a prepared sql query which updates CLOB fields in an Oracle 10g database (10.2.0.1).
If I execute the following query from inside SQL Developer and supply the values for the placeholders, there is no prblem. If I however execute it through an OracleCommand (Oracle.DataAccess.dll, version 1.102.0.1 (I think), .NET Framework 3.5),
I get the error message below. Note that we are not using the default oracle client as we require bulk insertion. The given ODP version and .NET Framework version are unfortunately a hard requirement and we may not change that.
Query:
UPDATE master_table
SET description = :description,
modification_notes = :modification_notes
WHERE master_id = :master_id;
Error:
ORA-00932: inconsistent datatypes: expected - got CLOB
Further Inormation:
Parameters are assigned as follows:
var param_description = new OracleParameter(":description", OracleDbType.Clob);
param_description.Value = "Test";
I have tried the following things:
insert to_clob() into the SQL query
assign a Oracle.DataAccess.Types.OracleClob object to the parameter.
I have also found the following description, but I would really want to be able to keep the prepared query.
How to insert CLOB field in Oracle using C#
Is it possible to do this through a prepared query?
I've attached a complete example which produces the error. DESCRIPTION and MODIFICATION_NOTES are two columns of type CLOB in the database.
Input data:
connection: OracleConnection to the database
master_id: primary key to filter for
Code:
Disclaimer: I typed the following example by hand, there might be mistakes which are not in the actual code
var query = "UPDATE master_table " +
"SET description = :description " +
" modification_notes = :modification_notes " +
"WHERE master_id = :master_id";
var param_master_id = new OracleParameter(":master_id", OracleDbType.Int64);
param_master_id.Value = master_id;
var param_description = new OracleParameter(":description", OracleDbType.Clob);
param_description.Value = "Test1";
var param_master_id = new OracleParameter(":modification_notes", OracleDbType.Clob);
param_description.Value = "Test2";
IDbCommand command = new OracleCommand(query, connection);
command.parameters.Add(param_master_id);
command.parameters.Add(param_description);
command.parameters.Add(param_modification_notes);
command.ExecuteNonQuery(); // this line throws an exception
You need to set this to true if you want to bind by name. Default is bind by the order of the parameter added.
cmd.BindByName = true;
Edit: My answer below applies for typical use of Clobs where the size is greater than 32k (what they were designed for). If you know you will always be binding less than 32k bytes, or 16k characters in the usual case of unicode you can bind as Varchar2 and free yourself from having to create a temporary lob.
--
Keep in mind that a LOB in an oracle column is really a LOB Locator, a pointer to the actual data. Before you can update a CLOB column with that Lob Locator, you need to create and populate a temporary CLOB first.
In the ODP.NET samples directory in your Oracle Home there should be a LOB directory, in there it looks like samples5.cs might be a good place to start. Here is a snippet from it:
// Set the command
OracleCommand cmd = new OracleCommand(
"update multimedia_tab set story = :1 where thekey = 1");
cmd.Connection = con;
cmd.CommandType = CommandType.Text;
// Create an OracleClob object, specifying no caching and not a NCLOB
OracleClob clob = new OracleClob(con, false, false);
// Write data to the OracleClob object, clob, which is a temporary LOB
string str = "this is a new story";
clob.Write(str.ToCharArray(), 0, str.Length);
// Bind a parameter with OracleDbType.Clob
cmd.Parameters.Add("clobdata",
OracleDbType.Clob,
clob,
ParameterDirection.Input);
try
{
// Execute command
cmd.ExecuteNonQuery();
See the accepted answer for the actual solution.
[Edit: Former suspected answer]:
After several days of testing and debugging I found the solution which was so far away from everything I considered:
Apparently, you need to bind all Clob fields first before binding anything else - even when using actual placeholders instead of using :1, :2 etc.
Changing the bind order (i.e. the order of the AddParameter calls) fixed it.
Try This :
string Query3 = " DECLARE " +
"str varchar2(32767); " +
" BEGIN " +
" str := '" + base64ImageRepresentationLogo + "'; " +
" update map_general_settings set value=str where DESC_AR='LOGO_IMG' ; END; ";
command.CommandText = Query3;
command.ExecuteNonQuery();
This question already has answers here:
Avoiding SQL injection without parameters
(21 answers)
Closed 9 years ago.
If I change my select from
String insSQL2
= "select * from Produtos where nome = '" + txtBuscaNome.Text + "'"
To
String insSQL2
= "select * from Produtos where nome = ''" + txtBuscaNome.Text + "''"
Will it prevent sql injection?
No.
SQL injection isn't about creatively using quote characters. It's about treating input as data instead of as code. Take a look at a classic SQL injection vulnerability:
"SELECT * FROM Users WHERE Id = " + someValue;
It may intuitively look like you're using someValue as a data value, but you're actually using it as actual SQL code. The SQL engine doesn't see this as a value parameter, it sees it as part of the command being executed. That code should just be a value, but it can be anything. And you'd be executing whatever code is supplied.
Thinking of it in this way, it becomes clear that you should never execute user-supplied code in your application.
The alternative is to treat the user input as values in pre-defined code. That way you control the complete scope of the code and users are only supplying values. Which would look more like this:
"SELECT * FROM Users WHERE Id = #id";
Now the SQL engine sees that parameter (#id) and expects you to supply a value for that parameter. In ADO.NET it might look something like:
someCommand.Parameters.AddWithValue("#id", someValue);
Now the SQL engine knows that this is a data value and not code, so it treats it as data instead of executing it.
No, it won't prevent sql injection.
Use parameterized sql:
var insSQL2 = "select * from Produtos where nome = #nome";
var connection = new SqlConnection(/* connection info */);
var command = new SqlCommand(insSQL2, connection);
command.Parameters.AddWithValue("#nome", txtBuscaNome.Text);