The INSERT Satatement Confliceted with the FOREIGN KEY Contraint - c#

I am creating a project on courier service. I got this error when I tried to enter values at run time. I have 2 insert statements, one for the sender and the other for Receiver. But the problem exists in insert statement for Sender and in LoginID. Actually, I want to add the logged user in "Sender" Table, so that I can see, how much entries, the logged user did. First, I am getting LoginID from the "Login" table using this statement
log_id = Convert.ToInt32(dt.Rows[0][0]);
Where log_id is an integer variable. And dt is a data table name
It works perfectly. I have seen it by using messagebox.
And then I created a Public Variable to use it on other forms.
public int logId
{
get { return log_id; }
}
Then I called this variable on my data entry form like this.
public StdExpIntl(int logId)
{
InitializeComponent();
logID = logId;
}
And this is my Insert Statement
Insert into Sender(CourierNo,LoginID,SenderName) values ('" + cNo.Text + "','"+logID+"', '" + Name1.Text + "')", con);
This is not the full statement, but I guess it is ok for now.
Login table
LoginID numeric(18, 0) NOT NULL
StaffID varchar(15) NOT NULL
username varchar(10) NOT NULL
password varchar(10) NOT NULL
Sender Table
CourierNo varchar(15) NOT NULL
LoginID numeric(18, 0) NOT NULL
SenderName text NOT NULL
SenderNIC numeric(18, 0) NOT NULL
SenderCountry text NOT NULL
SenderState text NOT NULL
The error is in LoginID, please someone help me.

I see the following:
the insert statement uses single quotation around each parameter to insert, including LogID. Since LogID is numeric, it would not need this, so your insert statement should look like this:
Insert into Sender(CourierNo,LoginID,SenderName) values ('" + cNo.Text + "',"+logID+", '" + Name1.Text + "');
to prevent micro-managing your queries in such a way, you can make use of parameterizing your queries.
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
using (SqlCommand command = new SqlCommand("Insert into Sender(CourierNo,LoginID,SenderName) values (#courierNo, #loginId, #senderName)",connection))
{
command.Parameters.Add(new SqlParameter("courierNo", cNo.Text));
command.Parameters.Add(new SqlParameter("loginId", logID));
command.Parameters.Add(new SqlParameter("senderName", Name1.Text));
connection.Open();
command.ExecuteNonQuery();
connection.Close();
}
}

You're setting a variable to itself.
public StdExpIntl(int logId)
{
InitializeComponent();
logID = logId;
}
You want...
public StdExpIntl(int logId)
{
InitializeComponent();
log_id = logId;
}

Try
Insert into Sender(CourierNo,LoginID,SenderName) values
('" + cNo.Text + "'," + logID + ", '" + Name1.Text + "')", con);
I have removed single quote around logID

Related

C# to mysql - inserting new row to table with foreign key

I need to insert a new row in a mysql table using C#.
The table looks like this, and contains one foreign key column.
i use the follwing code to cinnect to the database and insert data.
public virtual void addToDB()
{
try
{
//prepare for query
var cmd = MySQL.readyQuery();
//insert testdata to Vo2test
cmd.CommandText = "INSERT INTO vo2test_tb(ClientID, Weight, Methods, TimeOfDay, Date, StartResistance, Endresistance, TheoreticalMaxPulse, FatPercent3point, FatPercent7point, VO2_max, FitnessRating, HRmax, RERmax, TestTime, Raw_test_data) VALUES((SELECT UserID from user_tb WHERE UserID = '#UserID'), '#Weight', '#Method', '#Timeofday', '#Date', '#Startresistance', '#Endresistance', '#Theoreticalmaxpulse', '#Fatprocent3p', '#Fatprocent7p', '#vo2max', '#fitnessrating', '#hrmax', '#rermax', '#testtime', '#rawtestdata')";
cmd.Prepare();
//insert parameters som skal ændres:
cmd.Parameters.AddWithValue("#UserID", UserID);
cmd.Parameters.AddWithValue("#Weight", Weight);
cmd.Parameters.AddWithValue("#Method", Method);
//coverts date to 0000-00-00
string DateString = Convert.ToString(TestDate.Date.Date.Year) + "-" + Convert.ToString(TestDate.Date.Month) + "-" + Convert.ToString(TestDate.Date.Day);
cmd.Parameters.AddWithValue("#Date", DateString);
//converts time to 00:00:00.
string TimeString = Convert.ToString(TimeOfDay.Hour) + ":" + Convert.ToString(TimeOfDay.Minute) + ":00";
cmd.Parameters.AddWithValue("#Timeofday", TimeString);
cmd.Parameters.AddWithValue("#Startresisstance", StartResistance);
cmd.Parameters.AddWithValue("#Endressistance", EndResistance);
cmd.Parameters.AddWithValue("#TheoreticalMaxPulse", TheoreticMaxPulse);
cmd.Parameters.AddWithValue("#FatPercent3point", FatPercent3Point);
cmd.Parameters.AddWithValue("#FatPercent7point", FatPercent7Point);
cmd.Parameters.AddWithValue("#VO2_max", Vo2Max);
cmd.Parameters.AddWithValue("#FitnessRating", FitnessRating);
cmd.Parameters.AddWithValue("#HRmax", HRmax);
cmd.Parameters.AddWithValue("#RERmax", RERmax);
cmd.Parameters.AddWithValue("#TestTime", TimeOfDay);
cmd.Parameters.AddWithValue("#Raw_test_data", RawTestData);
cmd.ExecuteNonQuery();
//close connection
cmd.Connection.Close();
}
catch (MySqlException ex)
{
Console.WriteLine(ex.Message);
}
}
when i run it, i am told that ClientID can't be null but if i just run the sql query in Adminer it works fine.
The sub select in your insert query doesnt make sense. Why are you doing a sub select to insert a value you already have.
SELECT UserID from user_tb WHERE UserID = '#UserID'
Just insert #UserID directly.
Also you have wrapped all your # parameters in single quotes in the query string. You do not need this. Parameterization deals with the quotes for you in the background. Remove all single quotes so that it just reads:
cmd.CommandText = "INSERT INTO vo2test_tb(ClientID, Weight, Methods, TimeOfDay, Date,
StartResistance, Endresistance, TheoreticalMaxPulse, FatPercent3point, FatPercent7point,
VO2_max, FitnessRating, HRmax, RERmax, TestTime, Raw_test_data)
VALUES((SELECT ClientID from user_tb WHERE UserID = #UserID), #Weight, #Method, #Timeofday,
#Date, #Startresistance, #Endresistance, #Theoreticalmaxpulse, #Fatprocent3p, #Fatprocent7p,
#vo2max, #fitnessrating, #hrmax, #rermax, #testtime, #rawtestdata)";

Reduce the number of SqlCommands required to send information to three tables

I have the following code:
command = new SqlCommand("SELECT UserId from Users WHERE Username = N'" + userName + " AND " + userPassword + "= N'" + userPassword + "AND AccountStatus = 0");
command.CommandType = System.Data.CommandType.Text;
command.Connection = conn;
int uid = (int)command.ExecuteScalar();
if(uid > 0)
{
command = new SqlCommand("UPDATE IsOnline =" + true + " WHERE UserId = 'N" + uid);
command.ExecuteNonQuery();
command = new SqlCommand("INSERT INTO LogonHistory OUTPUT LogonHistoryId VALUES(NULL," + uid + "," + DateTime.Now + ")");
int id = (int) command.ExecuteNonQuery();
command = new SqlCommand("INSERT INTO UsersLogOnHistory VALUES(NULL," + uid + "," + id + ")");
command.ExecuteNonQuery();
IsAuthorised = true;
SendMessage(ID, ServerCommands.Success, IsAuthorised.ToString());
}
else
{
// User does not exist
SendMessage(ID, ServerCommands.Failed, IsAuthorised.ToString());
}
The first SQLCommand executed checks to see if the Username and password are correct and if their account is not suspended. It then (should) return the Row ID.
If the RowID > 0 then we have a valid logon.
Next SQLCommand updates the IsOnline status within the same table
The next SQLCommand Inserts into the LogonHistory the Users ID, and the DateTime. Now setting id with the Row Id
finally the SQLCommand is executed to insert the RowId we got from the last command and the User's Id into UserLogOnHistory. (which allows us to do a quick look up) - theoretically for updating the LogonHistory for when this user logs off.
I now realise that this is a mess!
So to the Questions:
How do I get the RowId of the table affected by the last command.
How can I optimise the queries to reduce the number of SQLCommands executed - or does this seem reasonable.
You can issue multiple TSQL commands in one batch by simply... including multiple TSQL commands. To be thorough, you should delimit them with ;, but in most (not all) cases, that is optional and it will work without.
To get the most recently inserted identity value; SCOPE_IDENTITY(). This only works for INSERT, and only with there is an IDENTITY column. In all other cases: OUTPUT.
Note; you should parameterize, but consider:
UPDATE IsOnline = 1 WHERE UserId = #uid;
DECLARE #lhid int
INSERT INTO LogonHistory (explict columns here)
VALUES(NULL,#uid, GETUTCDATE());
SET #lhid = SCOPE_IDENTITY();
INSERT INTO UsersLogOnHistory (explicit columns here)
VALUES(NULL,#uid, #lhid);
Note that you could also do the last bits with an INSERT trigger on LogonHistory, or via OUTPUT.
The number of round trips here: 1
If it was me i would put all that logic in a stored procedure, it's more easy to test and makes for better decoupling.
CREATE PROC logon
#username NVARCHAR(MAX)
, #password NVARCHAR(MAX)
, #IsAuthorized BIT OUTPUT
AS
BEGIN
SELECT #UID = UserId
FROM Users
WHERE Username = #username
AND userPasswordHash = CHECKSUM(#password);
UPDATE Users
SET IsOnline = 1
WHERE UserId = #UID;
INSERT INTO LogonHistory
VALUES(NULL,#UID,GETDATE());
INSERT INTO UsersLogOnHistory
VALUES(NULL,#UID,SCOPE_IDENTITY());
IF #UID IS NOT NULL
SET #IsAuthorized = 1;
ELSE
SET #IsAuthorized = 0;
END;
PS: please be considered for you colleagues privacy and hash their passwords.

Inserting values into table from textboxes & from another table's foreign key C#

Im trying to insert into a table values from textboxes AND to retrieve a foreign key id from another table and insert that also.
So I have a users table which contains UserId and I want this inserted into a nutrition diary which includes all the data that comes from textboxes(ie Weight, Height, Date etc)
I am retrieving the MemberId by using a session to track the username(lblRegistered)
Here is my code:
SqlConnection con = new SqlConnection("path for my connection");
con.Open();
SqlCommand cmd = new SqlCommand("select COUNT(*)FROM Members where Username='" + lblRegistered.Text + "'", con);
con.Close();
con.Open();
cmd.CommandText = "INSERT INTO Nutrition(Weight, Height, Bmi, Date, WaterIntake, CalorieIntake, MemberId) values ('" + txtWeight.Text + "','" + txtHeight.Text + "','" + txtBmi.Text + "','" + txtDate.Text + "','" + txtWater.Text + "','" + txtCalorie.Text + "', Select Users.UserId From Users where (Users.Username= '" + lblRegistered.Text + "'))";
cmd.ExecuteNonQuery();
cmd.Clone();
con.Close();
Response.Redirect("Success.aspx");
The error is close to Select Users part.
Any help would be greatly appreciated!
First thing would be to read up on parameterized SQL queries. The code you have there is completely open to SQL injection attacks.
This is a good resource for that: http://www.codinghorror.com/blog/2005/04/give-me-parameterized-sql-or-give-me-death.html
Then for the problem you would be better off using a Stored Procedure to do the work. Something along the lines of :
CREATE PROCEDURE Nutrition_Insert
#weight varchar(10),
#height varchar(10),
#bmi varchar(10),
#date varchar(10),
#username varchar(10),
//etc for your fields
AS BEGIN
DECLARE #memberId varchar(10)
SELECT #memberId = UserId From Users where Username = #username
INSERT INTO Nutrition(Weight, Height, Bmi, Date, WaterIntake, CalorieIntake, MemberId)
values (#weight, #height, #bmi, ....., #memberId)
END
Note - I've made some assumptions there as I don't know your data types, they all look like strings, but not knowing the size of the varchar used, I picked an arbitary value. Replace the (10) with the actual field size.
If you must use embedded SQL - then this is how you parameterize it. I've also fixed the insert statement to pull the MemberId from the Members table as part of the insert.
using (var conn = new SqlConnection("YOUR CONNECTION STRING"))
{
conn.Open();
using (
var cmd = new SqlCommand(
"INSERT INTO Nutrition(...fields...) SELECT #Weight, #Height, #Bmi,...., Members.MemberId FROM Members WHERE Members.Username = #Username", conn)
)
{
cmd.Parameters.AddWithValue("#Weight", txtWeight.Text);
cmd.Parameters.AddWithValue("#Height", txtHeight.Text);
...
cmd.Parameters.AddWithValue("#Username", lblRegistered.Text);
cmd.ExecuteNonQuery();
}
conn.Close();
}
You'll notice the using statements too. This will make sure your connection are disposed of cleanly.
Hope that helps.
Thanks Richard..that worked very well on the problem.
I am just trying to do the same technique on a different page but this time it will have 2 where clauses
var cmd = new SqlCommand("INSERT INTO AssignPlan(Reps, Sets, WeightOrTime, Date, MemberId, ExerciseId) Select #Reps, #Sets,#WeightOrTime,#Date, Members.MemberId From Members Where Members.Username=#name,ExerciseDisplay.ExerciseId From ExerciseDisplay Where ExerciseDisplay.ExerciseName=#Exercise", conn)
It's showing up an error from the syntax. Can this be achieved?

Checking for Primary Key assignment

I have a web application that writes to several databases for tracking employee change requests. I am running into a problem with entering in a new employee. They are first written to main Employee database before their access information is written to the other databases with EMP_ID being the primary key. When it goes to write to the other databases EMP_ID has been generated yet so it is getting entered in as 0.
To resolve this I was trying to loop and check the EMP_ID value until a value is generated but I continue to get stuck in a loop because the query returns back that no value was found.
while (int.Parse(empIDChecker) == 0)
{
dbConnection.Open();
validateIDSQLString = "SELECT EMP_ID FROM EMPLOYEE_TABLE WHERE FIRST_NAME = '" + firstNameTextBox.Text.Trim() + "' AND LAST_NAME = '" + lastNameTextBox.Text.Trim() + "'";
SqlCommand updateSQLCmd = new SqlCommand(validateIDSQLString, dbConnection);
SqlDataReader getRecords = updateSQLCmd.ExecuteReader();
try
{
empIDChecker = getRecords["EMP_ID"].ToString();
}
catch
{
empIDChecker = "0";
}
getRecords.Close();
dbConnection.Close();
}
OK, so if your insert sproc looks something like:
sp_InsertEmp
...
INSERT INTO Emp(Name, etc...)
VALUES ('Paul', etc...)
SELECT SCOPE_IDENTITY() AS EMP_ID
GO
And in your code:
SqlCommand insertCmd = new SqlCommand("sp_InsertEmp", dbConnection);
... Add parameters here and set type to StoredProcedure
SqlDataReader dr= insertCmd.ExecuteReader();
int newId;
if (dr.Read())
{
newId = dr.GetInteger(0);
}
you can use
SELECT IDENT_CURRENT(‘tablename’)
This will give you the last inserted auto increment ID of the table, you can use that to insert in other table
Check this link as well http://blog.sqlauthority.com/2007/03/25/sql-server-identity-vs-scope_identity-vs-ident_current-retrieve-last-inserted-identity-of-record/

SQLite Last Insert Rowid Does Not Work

I found several examples of how to get the last inserted row id from an sql insert call to my SQLite database, but my script threw this error:
SQLiteException
Message = "SQLite error\r\nnear \")\": syntax error"
InnerException
NULL
Below is the SQL text I sent in and how I used it. Obviously, I misunderstood something. Could someone help me out here?
I am trying to return the ID number that was just inserted.
private static int Save(Dates date, SQLiteConnection con) {
// REF: http://www.sqlite.org/c3ref/last_insert_rowid.html
int result = 0;
string sql = "INSERT INTO Dates1 " +
"(ID, TaskID, Last1) " +
"VALUES " +
"((SELECT MAX(ID) FROM Dates1)+1, #TaskID, #Last); " +
"SELECT sqlite3_last_insert_rowid(sqlite3*);";
using (SQLiteCommand cmd = new SQLiteCommand(sql, con)) {
cmd.Parameters.AddWithValue(Dates.AT_TASK, date.TaskID);
cmd.Parameters.AddWithValue(Dates.AT_LAST, date.Last.ToShortDateString());
cmd.CommandText = Dates.SQL_INSERT;
try {
result = cmd.ExecuteNonQuery();
} catch (SQLiteException err) {
result = -1;
LogError("Save(Dates, SQLiteConnection)", err);
}
}
return result;
}
FYI: I have set up the table so that ID is supposed to be auto generated using the Create SQL below, but the table only stores -1 for the ID values unless I manually insert it.
public const string SQL_CREATE = "CREATE TABLE Dates1 " +
"(ID INTEGER PRIMARY KEY AUTOINCREMENT, TaskID INTEGER, Last1 TEXT);";
To quote from the SQLite documentation:
last_insert_rowid() The last_insert_rowid() function returns the ROWID of the last row insert from the database connection which invoked the function. The last_insert_rowid() SQL function is a wrapper around the sqlite3_last_insert_rowid() C/C++ interface function.
So you need to change your statement to:
"SELECT last_insert_rowid();"
because what you did was to try and call the C API function.

Categories