I want to add blood group in my table. It is only storing as "A" meanwhile I want to store data as "A+".
I am using store procedure.
ALTER PROCEDURE [dbo].[spInsertBloodGroup]
#ids as int,
#des as nvarchar(2000),
#abbri as nvarchar(2000),
#Datet as datetime
AS
Begin
insert into tblbloodgroup(intSeqId,varDescription,varAbbrivation,dtCreationDate)
values ( #ids ,#des ,#abbri ,#Datet)
meanwhile my input values are coming from C# file which are written as.
string recordSave = "spInsertBloodGroup'" + seqID+ "','" + Description + "','" + Name + "','" + dateModed + "'";
Consider using an SqlCommand to call your stored procedure, instead of doing manual string concatenation.
var sp = new SqlCommand("spInsertBloodGroup", conn)
{
CommandType = CommandType.StoredProcedure
};
sp.Parameters.Add("#ids", SqlDbType.Int, seqID);
sp.Parameters.Add("#des", SqlDbType.NVarChar, Description);
sp.Parameters.Add("#abbri", SqlDbType.NVarChar, Name);
sp.Parameters.Add("#Datet", SqlDbType.Int, dateModed);
sp.ExecuteNonQuery();
Although, I have to ask why you've created a stored procedure that mimics an insert statement? Why not just create an SqlCommand for the Insert and call it directly? Does the stored procedure do additional things that you aren't showing us?
Related
I have an sql query that I need change to parameters so I can avoid sql injection.
adapter.SelectCommand.CommandText = #"SELECT c.*,(Select Initials FROM users WHERE User_ID = c.CreatedByUser) AS CreatedBy, (SELECT Initials FROM users WHERE User_ID = c.ModifiedByUser) AS ModifiedBy FROM currency c WHERE c.Company_ID = " + Company_ID + " AND c.CurrencyCode = '" + Code.Replace("'", "''") + "' ORDER BY c.Description
adapter.SelectCommand.Parameters.Add(new MySqlParameter("company_ID", Company_ID));
adapter.SelectCommand.Parameters.Add(new MySqlParameter("code", Code));
I know for Company_ID I need to change it to WHERE c.Company_ID = ?company_ID but I am not sure what to do for c.CurrencyCode = '" + Code.Replace("'", "''") + "'
I just don't know how to change the Code.Replace part, since its not a simple as company_ID
As per here
Try using (for odbc for example):
cmd.Parameters.Add("?CURRENCY", OdbcType.VarChar, Code.Replace("'", "''"))
Odbc approach
OdbcCommand cmd = sql.CreateCommand();
cmd.CommandText = "SELECT UNIQUE_ID FROM userdetails WHERE USER_ID IN (?, ?)";
cmd.Parameters.Add("?ID1", OdbcType.VarChar, 250).Value = email1;
cmd.Parameters.Add("?ID2", OdbcType.VarChar, 250).Value = email2;
For oracle:
//create SQL and insert parameters
OracleCommand cmd = new OracleCommand("insert into daily_cdr_logs (message) values (:_message)", con);
cmd.Parameters.Add(new OracleParameter("_message", msg));
For mysql:
cmd = new MySqlCommand("SELECT * FROM admin WHERE admin_username=#val1 AND admin_password=PASSWORD(#val2)", MySqlConn.conn);
cmd.Parameters.AddWithValue("#val1", tboxUserName.Text);
cmd.Parameters.AddWithValue("#val2", tboxPassword.Text);
cmd.Prepare();
So a parameterized query (to me at least) generally means that you have created a stored procedure on your database and then use your code to execute the stored procedure while passing in the relevant parameters.
This has a couple of benefits
DRY - you don't have to repeat the query in code, you can just call the execute method and pass in the appropriate parameters
Helps prevent SQL injection - You can only modify the parameters which hopefully will be sanitized before being passed to the query
Here is how to create a stored procedure according to MSDN
and
Here is how to execute a a stored procedure according to MSDN
If you are determined to do it via LINQ, MSDN has what you are looking for here
EDIT: It seems you are concerned about sql-injection (which is good!), here is an article (again from MSDN) that covers that topic pretty extensively
I have the answer. c.CurrencyCode = '" + Code.Replace("'", "''") + "' simply changes to c.CurrencyCode = ?code
I'm trying to convert the following stored procedure into a query, so that I can use it in SQL Server CE
USE TestResults
GO
CREATE PROCEDURE uspInsertNewTest
(#DeviceSerialNumber nvarchar(50),
#DeviceType nvarchar(50),
#ElapsedTime int)
AS
BEGIN
INSERT INTO [TestResults].[dbo].[Tests]([Date], [Device], [DeviceType], [ExecutionTimeMs])
OUTPUT INSERTED.TestId
VALUES (GETDATE(), #DeviceSerialNumber, #DeviceType, #ElapsedTime)
END
GO
From the above script, all I can understand is that it takes three input parameters
DeviceSerialNumber
DeviceType
ElapsedTime
but it'll update 5 columns in the table Tests including Date and TestId.
Since I can't use stored procedures in SQL Server CE, I've converted the above script into a string query,
string queryString = "INSERT INTO Tests ([Date], [Device], [DeviceType], [ExecutionTimeMs]) VALUES (#Date, #DeviceSerialNumber, #DeviceType, #ElapsedTime)"
Now how to include OUTPUT INSERTED.TestId into the string( queryString ) ?
There's a similar question here, but it doesn't help my problem
Thanks!
You can use ##IDENTITY to return the last inserted identity value:
string queryString = "INSERT INTO Tests " +
"([Date], [Device], [DeviceType], [ExecutionTimeMs]) " +
"VALUES (#Date, #DeviceSerialNumber,#DeviceType, #ElapsedTime); " +
"SELECT ##IDENTITY;"
When you execute your query, you need to set it up to return a single value using the ExecuteScalar method:
var newIdentity;
// set up the queryString variable & command using the above
newIdentity = cmd.ExecuteScalar();
This assumes that the column TestId is an identity column.
Though I accepted Tanner's answer, but I ended up doing like this,
string queryString = "INSERT INTO Tests " + "([Date], [Device], [DeviceType], [ExecutionTimeMs]) " +
"VALUES (#Date, #DeviceSerialNumber,#DeviceType, #ElapsedTime)";
string queryString2 = "SELECT ##IDENTITY";
DbCommand command = factory.CreateCommand ();
command.CommandText = queryString;
// Added Parameters here
command.ExecuteNonQuery ();
command.CommandText = queryString2;
object testId = command.ExecuteScalar ();
So I had to split the query into two string & run ExecuteNonQuery with the first string and run ExecuteScalar with the second string.
I have been trying to add a column programmatically in ASP.NET to modify the tables in SQL Server.
Please see the following code:
string suppliernotxt = supplieridlist[1].ToString();
//SqlCommand cmd2 = new SqlCommand("ALTER TABLE [ProductNormalDB] ADD suppliernotxt nvarchar(20) NULL", con);
SqlCommand cmd2 = new SqlCommand("ALTER TABLE ProductNormalDB ADD #supplierlist nvarchar(20) NULL", con);
cmd2.Parameters.AddWithValue("#supplierlist", suppliernotxt);
//cmd2.Parameters.AddWithValue("#supplierlist", suppliernotxt.ToString());
//cmd2.Parameters["#supplierlist"].Value = supplieridlist[x];
cmd2.ExecuteNonQuery();
supplieridlist is an array that acquires all the column names to add into the SQL Server database. For some reason the parametrized method is not working and shows the following error:
Incorrect syntax near '#supplierlist'.
The basic idea is to have a user select from a check box the name of the suppliers, based on the selected number of suppliers the array will create the supplier names for ex. if we selected 3 suppliers, the array will save "Supplier1", "Supplier2", "Supplier3" and then the SqlCommand is supposed to alter the table and add the new columns.
You cannot use parameters to express the name of columns.
Parameters could only be used to express values for WHERE clause or for INSERT or UPDATE statements.
You could use string concatenation for your query text, passing the string value to a stored procedure or use some form of dynamic sql.
Please be very carefull with these kind of approaches because if you don't keep absolute control on the values passed to your code you will be exposed to Sql Injection.
Adding as an example of Dynamic SQL execution, but still vulnerable to SQL Injection
string suppliernotxt = supplieridlist[1].ToString();
string execSQL = "DECLARE #sup nvarchar(15); " +
"SET #sup = '" + suppliernotxt + "'; " +
"EXEC ('ALTER TABLE ProductNormalDB ADD ' + #sup + ' nvarchar(20) NULL')"
SqlCommand cmd2 = new SqlCommand(execSQL, con);
cmd2.ExecuteNonQuery();
As you can see, even with Dynamic SQL there is nothing that prevent an SQL Injection attack passing via the suppliernotxt variable
EDIT As explained in the comments below from #RBarryYoung, a good improvement on the SQL Injection problem for this case of dynamic sql could be the usage of the QUOTENAME function to obtain an Unicode string with the required delimiters around the input string
string execSQL = "DECLARE #sup nvarchar(15); " +
"SET #sup = QUOTENAME('" + suppliernotxt + "'); " +
"EXEC ('ALTER TABLE ProductNormalDB ADD ' + #sup + ' nvarchar(20) NULL')"
I know this question has been asked several times and I read those with no luck :( So I am asking it again with my code.
I have created a stored procedure to update a database table.
Stored procedure:
CREATE PROCEDURE usp_PettyCash_EditExpenseInfo
(
#ExpenseID bigint,
#ExpenseName varchar(100),
#SAPCode varchar(50),
#MaxLimit decimal,
#ExpenseType varchar(50)
)
AS
BEGIN
UPDATE t_ExpenseInfo
SET ExpenseName = #ExpenseName,
SAPCode = #SAPCode,
MaxLimit = #MaxLimit,
ExpenseType = #ExpenseType
WHERE
ExpenseID = #ExpenseID
END
GO
But when I call this from code behind with below code, it gives the exception similar to
Error in converting from nvarchar to bigint
Code behind:
oOleDbCommand.Parameters.AddWithValue("#ExpenseName", oInputExpense.ExpenseName.ToString());
oOleDbCommand.Parameters.AddWithValue("#SAPCode", oInputExpense.SAPCode.ToString());
oOleDbCommand.Parameters.AddWithValue("#MaxLimit", Convert.ToDecimal(oInputExpense.MaxLimit));
oOleDbCommand.Parameters.AddWithValue("#ExpenseType", oInputExpense.ExpenseType.ToString());
oOleDbCommand.Parameters.AddWithValue("#ExpenseID", Convert.ToDouble(oInputExpense.ExpenseID.ToString()));
I also tried this:
oOleDbCommand.CommandText = "UPDATE t_ExpenseInfo SET ExpenseName='" + oInputExpense.ExpenseName.ToString() + "', SAPCode='" + oInputExpense.SAPCode.ToString() + "', MaxLimit=" + oInputExpense.MaxLimit + ", ExpenseType='" + oInputExpense.ExpenseType.ToString() + "' WHERE ExpenseID=" + oInputExpense.ExpenseID + "";
this DIRECT command runs OK from SQL Query Analyzer from from code behind this also give an "Access Violation" error.
I am really confused about what to do? Please help !
is there any particular reason why you're using OleDbCommand instead of the "native" SQL Server SqlCommand ??
I would try this:
using(SqlConnection conn = new SqlConnection("(add your connection string here)"))
using(SqlCommand cmd = new SqlCommand("dbo.usp_PettyCash_EditExpenseInfo", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
// add parameters with defined type!
cmd.Parameters.Add("#ExpenseID", SqlDbType.BigInt).Value = .....;
cmd.Parameters.Add("#ExpenseName", SqlDbType.VarChar, 100).Value = ".....";
cmd.Parameters.Add("#SAPCode", SqlDbType.VarChar, 50).Value = ".....";
cmd.Parameters.Add("#MaxLimit", SqlDbType.Decimal, 15, 2).Value = 100.00;
cmd.Parameters.Add("#ExpenseType", SqlDbType.VarChar, 50).Value = "......";
// open connection, call stored procedure, close connection
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}
Basically, I prefer using the native SqlConnection/SqlCommand over the old, legacy OleDb stuff, and I also prefer to explicitly specify what type my parameters are - don't rely on ADO.NET or some other part figuring it out automagically - when it has to guess, it can get it wrong, and error like the one you see might occur. If you define it yourself, you're in control!
Try Convert.ToInt64(...) instead of Convert.ToDouble(oInputExpense.ExpenseID.ToString())
I collect the query in SQL Profiler and find out that OleDB doesn't care about the name of parameter, but it cares about order of given parameters.
In your case ExpenseName is given as first parameter and it tried to convert it to ExpenseId (first parameter in your stored procedure).
Here is query from SQL Profiler:
exec usp_PettyCash_EditExpenseInfo N'ExpenseName',N'SAP',21.209999084472656,N'a',1
Try to change order of given parameters. I hope it help.
Currently I am using the 1st part. But I have checked both are working :)
OleDbCommand.Parameters.Add("#ExpenseID", OleDbType.BigInt).Value = Convert.ToInt64(oInputExpense.ExpenseID);
OleDbCommand.Parameters.Add("#ExpenseName", OleDbType.VarChar).Value = Convert.ToString(oInputExpense.ExpenseName);
OleDbCommand.Parameters.Add("#SAPCode", OleDbType.VarChar).Value = Convert.ToString(oInputExpense.SAPCode);
OleDbCommand.Parameters.Add("#MaxLimit", OleDbType.Decimal, 2).Value = Convert.ToDecimal(oInputExpense.MaxLimit);
OleDbCommand.Parameters.Add("#ExpenseType", OleDbType.VarChar).Value = Convert.ToString(oInputExpense.ExpenseType);
//OleDbCommand.Parameters.AddWithValue("#ExpenseID", Convert.ToInt64(oInputExpense.ExpenseID.ToString()));
//OleDbCommand.Parameters.AddWithValue("#ExpenseName", oInputExpense.ExpenseName.ToString());
//OleDbCommand.Parameters.AddWithValue("#SAPCode", oInputExpense.SAPCode.ToString());
//OleDbCommand.Parameters.AddWithValue("#MaxLimit", Convert.ToDecimal(oInputExpense.MaxLimit));
//OleDbCommand.Parameters.AddWithValue("#ExpenseType", oInputExpense.ExpenseType.ToString());
I have been working on this school assignment and have gotten to a point at which I have been stuck for a few days now. My ASP.net web page is supposed to allow the user to create an account and login. However, no matter how many times I fill in the Create Account form, it doesn't seem to get added to the database.
Here is my User class, which holds the createAccount Method
public class Userr
{
//Constructor for the Account Creation method(createAccount)
public string createAccount(string strFname, string strLname, string strUname, string address, string city, string state, string phone, string zip, string email,string password)
{
string i="";
string storedProcText = ("INSERT INTO User Values('#ID," +strUname +"','"+strFname +"','"+ strLname +"','"+address +"','"+city +"','"+state+"','"+zip+"','"+phone+"','"+ email +"','"+ password );
ArrayList parms = null;
DataAccess dataAccess = new DataAccess();
int result = dataAccess.insertUpdateData(parms,storedProcText );
i =result.ToString();
return i;
}
public string Login(string strUsername, string strPassword)
{
DataAccess objDA = new DataAccess();
int result = objDA.LoginUser(strUsername, strPassword);
}
}
Here is my method for updating(stored in the dataAccess object/class
//Constructor for the update method
public int insertUpdateData(ArrayList items, String strProcedureName)
{
int i = 0;
string strConn = WebConfigurationManager.ConnectionStrings["TicketsConnectionString"].ConnectionString;
SqlConnection myConnection = new SqlConnection(strConn);
string sqlText = strProcedureName;
SqlCommand myCommand = new SqlCommand(sqlText);
myCommand.Connection = myConnection;
myCommand.CommandType = CommandType.StoredProcedure;
try
{
using (myConnection)
{
myConnection.Open();
i = myCommand.ExecuteNonQuery();
//grdData.DataSource = myReader;
// grdData.DataBind();
}
}
catch (Exception err)
{
}
return i;
}
The User table contains the follwing fields in order: ID, UserID, FirstName,LastName, Address, City, State, Zip,Phone,EmailAddress,Password
Is my SQL statement wrong, or what? I am at the end of my rope here.
So, off the bat, I see a few issues:
You set your myCommand.CommandType = CommandType.StoredProcedure but, the syntax you provided is not a stored proc. A stored proc would take a name value list of params, which is null in your case.
Lets say you didn't mean to use stored procs, in which case, your sql syntax is incorrect. You don't need the #ID parameter, unless you are passing it in (in which case, you didn't set it). It should be something like this (without knowing the structure of your table):
string storedProcText = ("INSERT INTO User Values("'" +strUname +"','"+strFname +"','"+ strLname +"','" + address +"','"+city +"','"+state+"','"+zip+"','"+phone+"','"+ email +"','"+ password + "'");
This is given that the values you are inserting matches your table exactly. If not, you will need to specify the table field names in your query as well, like so:
string storedProcText = ("INSERT INTO User(username, firstName, lastName, field4, field5, field6) Values("'" +strUname +"','"+strFname +"','"+ strLname +"','" + address +"','"+city +"','"+state+"','"+zip+"','"+phone+"','"+ email +"','"+ password + "'");
The way to do this using stored procs is this:
SqlParameter[] parameters = {
new SqlParameter("#param1", SqlDbType.NVarChar, 50),
new SqlParameter("#param2", SqlDbType.VarChar, 100),
new SqlParameter("#param3", SqlDbType.VarChar, 100),
new SqlParameter("#param4", SqlDbType.VarChar, 100),
new SqlParameter("#param5", SqlDbType.VarChar, 100),
new SqlParameter("#param6", SqlDbType.VarChar, 100)
};
parameters[0].Value = strFname;
parameters[1].Value = strLname;
.........
.........
[all the parameters you need]
You need to create a stored proc, also (obviously)
And then you call your dataaccess layer just like you are doing.
Steps for making this work:
1) Don't catch and swallow every exception. The exception will tell you what you are doing wrong here.
2) As Caspar Kleijne points out, you need to put the password in quotes.
3) As I point out, you need to add a parenthesis.
4) You should also use parameterized SQL queries
5) You probably shouldn't be passing the ID,
Here's the corrected SQL string for #2 and #3:
string storedProcText = ("INSERT INTO User Values('#ID,"
+strUname +"','"+strFname +"','"
+ strLname +"','"+address +"','"
+city +"','"+state+"','"
+zip+"','"+phone+"','"
+ email +"','"+ password
+"')" );
It'll take some refactoring to use parameterized queries, and this is a homework project, so I'll leave that as an exercise for you.
So, to start from the beginning, have you stepped through this code with the debugger and determined if it's throwing an exception or returning zero rows modified?
The most worrisome thing is the insertion of the #ID column. If this is an Identity column you shouldn't be inserting this value. If it's not, I don't see you assigning a value to it anywhere.
EDIT:
So as has been mentioned by others here you have some structural issues in you query.
I took your code and threw it in a quick project and here's what your statement looks like.
INSERT INTO User Values('#ID,UserName','FirstName','LastName','123 Some Street','SomeTown','State','54555','555-444-3333','email#email.com','ITS_A_SECRET!
Notice the end of the query. The password field isn't escaped with a closing ' and the param list is not closed with a closing bracket.
A second problem is that #Id field. Is your column in the database an identity field? (It should be) If so, just remove that.
Now, here's the real kicker. Is your table name User? That's a reserved word in SQL server so you'll get errors in your query as is. Format you query like the following and it will work.
string storedProcText = ("INSERT INTO [dbo].[User] Values('" + strUname + "','" + strFname + "','" + strLname + "','" + address + "','" + city + "','" + state + "','" + zip + "','" + phone + "','" + email + "','" + password + "')");
The other issue, as mentioned is that you have the command type set to Stored Procedure when you are not using one.
Modifying you command type to text:
myCommand.CommandType = CommandType.Text;
After I made these modifications and ran your code I ended up with a record in the database.
The most important thing to check right now is that ID field. Is it an identity column? Make sure it is and then remove it from your statement.
In the insert you are trying to insert #ID which first of all most likely would be an identity column, and unless you set IDENTITY_INSERT ON on that table, will throw an exception, second, even if it was not an identity column, you are not providing the parameter definition for the #ID parameter to the command.
Try removing #ID from the insert statement, and pass in everything else, but ID.
As a side note, your SQL Statement is prone to SQL Injection attacks since you're concatenating sql command string and values provided by user into one string. I would recommend using parameters instead the actual values and then adding parameters to the sql command later.
I cannot post everything as a comment , but can you do one thing..
put a break point and take the contents of this string
string storedProcText = ("INSERT INTO User Values('#ID," +strUname +"','"+strFname +"','"+ strLname +"','"+address +"','"+city +"','"+state+"','"+zip+"','"+phone+"','"+ email +"','"+ password );
and paste the value of storeProcText directly in the database and see if it can successfuly run and create a record for you.
break and debug should fix your problem
Please Comment out this statement:
myCommand.CommandType = CommandType.StoredProcedure’;
You can use a sql script directly.