Is that correct way of reading data from table then insert into table ?
I am trying to read the max number or rec_id to create seq column the +1 to insert my data record into same table
//Opening the connection with Oracle Database
OracleConnection conn = new OracleConnection(oradb);
conn.Open();
//Create the oracle statment and insert data into oracle database
OracleCommand cmd1 = new OracleCommand();
cmd1.Connection = conn;
cmd1.CommandText = "SELECT NVL (MAX (rec_id), 0) + 1 FROM backup_check";
OracleDataReader dr = cmd1.ExecuteReader();
dr.Read();
label1.Text = dr.GetString(0);
conn.Dispose();
OracleCommand cmd = new OracleCommand();
cmd.Connection = conn;
//OracleTransaction trans = conn.BeginTransaction(); -- add rollback in case of transaction not complate for some reason
cmd.CommandText = "insert into my table(" + "'" + v_rec_id + "'" + ",OFFICE_CODE,DUMP_NAME,DUMP_STATUS,SYSTEM,CHECK_DATE)values(null,null," + "'" + keyword + "'" + ",'0','abc',sysdate)";
cmd.ExecuteNonQuery();
//Closing the connection with oracle databae
conn.Dispose();
First of all, you should forget to use the MAX function to retrieve the next value to insert in an 'so called autoincrement column'. The problem arises from the fact that your code running on one machine cannot prevent another user from another machine to execute the same code concurrently with yours. This could result in both users receiving the same MAX result and thus creating invalid duplicate keys.
In Oracle you should mark your table to have a SEQUENCE for your primary key (REC_ID)
Something like this (writing here on the fly not tested now....)
CREATE TABLE myTable
(
rec_id NUMBER PRIMARY KEY
.... other columns follow
);
CREATE SEQUENCE myTable_seq MINVALUE 1 START WITH 1 INCREMENT BY 1 CACHE 20;
CREATE OR REPLACE TRIGGER myTable_trg
BEFORE INSERT ON myTable
for each row
begin
select myTable_seq.nextval into :new.rec_id from dual;
end;
At this point, when you try to insert a new record the triggers kicks in and calculate the next value to assign to your primary key.
The C# code is simplified a lot and becomes:
string cmdText = #"insert into myTable
(OFFICE_CODE,DUMP_NAME,DUMP_STATUS,SYSTEM,CHECK_DATE)
values(null,:keyw,'0','abc',sysdate)";
using(OracleConnection conn = new OracleConnection(oradb))
using(OracleCommand cmd = new OracleCommand(cmdText, conn))
{
conn.Open();
//using(OracleTransaction trans = conn.BeginTransaction())
//{
cmd.Parameters.AddWithValue(":keyw",keyword);
cmd.ExecuteNonQuery();
// trans.Commit();
//}
}
No need to read anything before, command text not concatenated avoid SQL Injection, closing and disposing is automatic exiting from the using block....
Related
Complete Code For stopping user from using same User Names
if (IsPostBack)
{
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["RegistrationConnectionString"].ConnectionString);
string checkuser = "select count(*) from UserDataTable where UserName='" +
username.Text + "'";
SqlCommand com = new SqlCommand(checkuser, con);
int temp = Convert.ToInt32(com.ExecuteScalar().ToString());
if (temp == 1)
{
Response.Write("User Already Exists");
}
con.Close();
}
}
The above code is for stopping people to use the same UserName that
is already used to register
But unfortunately it does not stop them from registration with the existing
username, hence they can still use the same User Name.
Code For Button1_Click
This is the code for my submit button
try
{
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["RegistrationConnectionString"].ConnectionString);
con.Open();
//inserting data to database
string insertQuery = "insert into [UserDataTable] (UserName,Email,Password,Country) values (#username, #email, #password, #country)";
SqlCommand com = new SqlCommand(insertQuery, con);
com.Parameters.AddWithValue("#username", username.Text);
com.Parameters.AddWithValue("#email", email.Text);
com.Parameters.AddWithValue("#password", password.Text);
com.Parameters.AddWithValue("#country", DropDownList1.SelectedItem.ToString());
com.ExecuteNonQuery();
Response.Redirect("Manager.aspx");
Response.Write("You're Now Registered");
con.Close();
}
catch(Exception ex)
{
Response.Write("Error:"+ex.ToString());
}
My DataBase
My database that i created
CREATE TABLE [dbo].[UserDataTable] (
[Id] INT NULL,
[UserName] NVARCHAR (50) NULL,
[Email] NCHAR (50) NULL,
[Password] NCHAR (20) NULL,
[Country] NCHAR (15) NULL
My Problem/Question:
why is it not stopping them from using the existing Username
i wrote this code by dissecting other codes that i saw online, So if it seems strange and weird I apologize its my first time using C#
Hope this helps in understanding my problem
Software:Visual Studio 2017
Try running that query and seeing what you get back. It's possible that you're getting different results than you expect.
I'd recommend changing:
if (temp == 1)
to:
if (temp > 0)
which should weed out cases where a username is already in the database twice.
Also, as other people have mentioned in comments, you definitely want to be using parameters. Here is your code converted to use parameters:
string checkuser = "select count(*) from UserDataTable where UserName = #userName";
SqlCommand com = new SqlCommand(checkuser, con);
com.Parameters.Add(new SqlParameter("#userName", username.Text));
int temp = Convert.ToInt32(com.ExecuteScalar());
Firstly get rid of SQL-Injection :
string checkuser = "select * from UserDataTable where UserName=#uname";
Then use either a DataTable or a DataReader.Let's use DataReader for instance :
////Firstly,we generally declare the connection as con for easy-recognition
SqlConnection con = new SqlConnection;
con = "connectionstringhere";
///then we use the sqlCommand which we generally declare as cmd
SqlCommand cmd = new SqlCommand(checkuser,con);
cmd.Parameters.Add("#uname",SqlDbType.Varchar).Value = usernameStringHere
///then we use a datareader(note: A datareader is better than DataAdapter regarding performance
SqlDataReader dr;
dr = cmd.ExecuteReader;
///Then we check if any row exists in the dataReader after we filter the database
If dr.Hasrows
{
////Wont save data
}
The above code will get the job done.
Or you can simply go with ExecuteScalar
SqlCommand cmd = new SqlCommand("SELECT COUNT(*) from UserDataTable where userNme=#uname",con)
cmd.Parameters.Add("#uname",SqlDbType.VarChar).Value = usernamestringhere
int count = (int)cmd.ExecuteScalar;
If(count > 0)
{
///eon't save data
}
Summary : You had two issues :
1 . Sql-Injection - which i clearly explained how to fix
2 . using temp == 1 instead of temp > 0..
Hope this helps you
99.9999999% chance "UserName" is not a primary key.
Just run a select to see if there are multiple users with the input "UserName".
a quick fix
change
select count(*) from...
to
select top 1 1 from...
It will always return 1 if there is anything matches, NULL if not.
I want to insert email in Table with only one column. I tried on 2 way. First time I tried with commandText and second time I tried with parapeters. But the both solution give me the same error.
System.Data.OleDb.OleDbException: 'Syntax error in INSERT INTO statement.'
I don't see any error in INSERT STATEMENT. Maybe the problem is in TABLE?
using (OleDbCommand cmd = new OleDbCommand())
{
cmd.Connection = conn;
cmd.CommandText = "SELECT COUNT (email) FROM [User] WHERE [email] LIKE '" + userEmail + "';";
conn.Open();
int count = Convert.ToInt32(cmd.ExecuteScalar()); // This passed
if (count == 0)
{
string query = #"INSERT INTO User (email) VALUES (#email)";
string cmdText= #"INSERT INTO User (email) VALUES ('"+userEmail+"')";
OleDbCommand command = new OleDbCommand(cmdText, conn);
// command.Parameters.AddWithValue("#email", "userEmail");
// command.CommandText = query;
command.ExecuteNonQuery(); // I GOT ERROR HERE
}
conn.Close();
}
User is a keyword. You should INSERT INTO [USER] instead
string cmdText= #"INSERT INTO User (email)) VALUES ('"+userEmail+"')";
you have one ')' too many after (email)
I am writing a sample application to insert data into a SQL Server database using C#. Data is not persisting in the database.
Below is my code:
conn.Open();
SqlCommand cmd = conn.CreateCommand();
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = "Insert into Record (ID,Name) values ('" + txtId.Text + "' , '" + txtName.Text + "')";
cmd.ExecuteNonQuery();
//cmd.Clone();
conn.Close();
The values are not persisted. There is no error when I insert the values. When I changed my command to:
"Insert into Database.dbo.Record (ID,Name) values ('"
it throws an exception:
Incorrect syntax near the keyword 'Database'.
Why is my SQL Server database not being updated?
Your code as is, is possibly open to SQL injection - you should use parameters.
Also check the table names and primary keys, e.g. if ID is an Identity column it is automatically generated when you insert, so then you'll just INSERT INTO Record (Name) VALUES ('Bob')
Otherwise if ID is a primary key you'll likely have to check you are not trying to insert duplicates.
Please use parameters! (adjust the SqlDbType's if needed)
You should also use a using statement over the connection to properly dispose resources, and ideally use a transaction for updates:
string sqlQuery = "INSERT INTO Record (ID, Name) VALUES (#id, #name); ";
using (SqlConnection conn = new SqlConnection(connectionString)) {
conn.Open();
SqlTransaction tran = conn.BeginTransaction();
try {
SqlCommand command = new SqlCommand(sqlQuery, conn, tran);
SqlParameter in1 = command.Parameters.Add("#id", SqlDbType.NVarChar);
in1.Value = txtId.Text;
SqlParameter in2 = command.Parameters.Add("#name", SqlDbType.NVarChar);
in1.Value = txtName.Text;
command.ExecuteNonQuery();
tran.Commit();
} catch (Exception ex) {
tran.Rollback();
//...
}
}
I have two tables, one containing names, and one containing rates and other data that is lined to each name. After I insert a new name into table A, I want to get the newly auto generated PK to now use to insert into my other table B with rates.
How can I do this? I read about scope_identity online but I'm not sure how to use it.
This is what I have so far:
SqlConnection con = new SqlConnection(pubvar.x);
SqlCommand command = con.CreateCommand();
command.CommandText ="Insert into A values('" +Name + "')";
SqlCommand command2 = con.CreateCommand();
command2.CommandText = "Insert into B values(....)";
SELECT SCOPE_IDENTITY();
con.Open();
command.ExecuteNonQuery();
con.Close();
Considering the case you've described, I don't see any need to return the identity from the database. You can simply issue both statements in one command:
using (var cnx = new SqlConnection(pubvar.x))
using (var cmd = new SqlCommand
{
Connection = cnx,
CommandText = #"
insert into A (Name) values (#name)
insert into B (A_ID, Rate) values (scope_identity(), #rate)
",
Parameters =
{
new SqlParameter("#name", name),
new SqlParameter("#rate", .5m) //sample rate
}
})
{
cnx.Open();
cmd.ExecuteNonQuery();
}
i m trying to retrieve the Specialization ID from a table called Specializationtbl, using C# MSVS 2008 and the table includes SpecializationName and SpecializationID beside some other rows and my question is related to some error " No Data to present ", the command goes as bellow:
SqlCommand READSpecID = new SqlCommand("SELECT * FROM Specializationtbl WHERE SpecializationName='" + comboBox1.Text + "'" , DBcnction);
DBcnction.Open();
SqlDataReader ReadSpecID_ = READSpecID.ExecuteReader();
ReadSpecID_.Read();
int SpecID_ = Convert.ToInt16(ReadSpecID_["SpecID"].ToString());
DBcnction.Close();
i also tried to Select the "SpecID" instead of all the rows, but cant seem to seal the query correctly and keep receiving "No data present " error, any idea where am i making the mistake?
1) Try opening DBcnction before assigning the value to READSPecID
DBcnction.Open();
SqlCommand READSpecID = new SqlCommand("SELECT * FROM Specializationtbl WHERE SpecializationName='" + comboBox1.Text + "'" , DBcnction);
2) Run the command in SSMS:
SELECT * FROM Specializationtbl WHERE SpecializationName ='yourvalue'
and see if any results are returned
3) Check comboBox1.Text has a value in it
4) Validate the contents of comboBox1.Text (Or use paremetrised queries or a stored procedure) to ensure you do not become a victim of SQL Injection: http://en.wikipedia.org/wiki/SQL_injection
Refactor to solve your TWO problems:
Your SQL injection problem when building your SQL statement.
Use ExecuteScalar if you only need one value.
Implement using blocks.
string retVal;
using (var conn = new SqlConnection(SomeConnectionString))
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "SELECT SpecID FROM Specializationtbl WHERE SpecializationName= #Name";
cmd.Parameters.AddWithValue("#Name", comboBox1.Text);
conn.Open();
retVal = cmd.ExecuteScalar().ToString();
}
int specID = int.Parse(retVal);
If you really needed more than one value from your statement:
using (var conn = new SqlConnection(SomeConnectionString))
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "SELECT SpecID, Value2 FROM Specializationtbl WHERE SpecializationName= #Name";
cmd.Parameters.AddWithValue("#Name", comboBox1.Text);
conn.Open();
var dr = cmd.ExecuteReader();
while (dr.Read())
{
Customer c = new Customer {
ID = dr["SpecID"].ToString(),
Value = dr["Value2"].ToString(),
};
}
}
Need to first test if there are any rows. I suspect the query is returning zero rows.
if (ReadSpecID_.HasRows)
{
ReadSpecID_.Read();
}