I have a SQLite Connection Object and a command object. I insert a row in my table using the ExecuteNonQuery function. How do I get the value of the autoincrement column (ID) from this?
Code for creating database:
creationQuery = "CREATE TABLE IF NOT EXISTS MyTable ( ID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT ,MyCol1 NVARCHAR, MyCol2 NVARCHAR)";
My code for inserting values in the DB:
public void InsertIntoDB(string[] vals){
// Global connection objects (This is in an API so every time a new instance of these are created)
connObj = CreateConnection();
cmdObj = connObj.CreateCommand();
cmdObj.CommandText = "INSERT INTO MyTable ('MyCol1',MyCol2) VALUES( '" + vals[0] + "','" + vals[1] + "')";
int id = -1;
try{
cmdObj.ExecuteNonQuery();
id = (int)cmdObj.Parameters["id"].Value; // tried "#id" as well
}catch(Exception ex){
throw ex;
}
}
This code is inserting correctly. But throws an exception ( System.ArgumentOutOfRangeException) in the line where I'm trying to get the ID. Whats going on/ How do i solve this?
EDIT 1: Inside the try block, I added code to just run another query "Select max(ID) from MyTable":
try
{
cmdObj.ExecuteNonQuery();
cmdObj.CommandText = "Select Max(id) from MyTable";
SQLiteDataReader myReader = cmdObj.ExecuteReader();
while (myReader.Read())
{
id = (int)myReader["id"];
}
Console.WriteLine(id);
}
This code throws the same Exception.
select last_insert_rowid();
And you will need to execute it as a scalar query.
string sql = #"select last_insert_rowid()";
long lastId = (long)command.ExecuteScalar(sql); // Need to type-cast since `ExecuteScalar` returns an object.
Related
I'm trying to update a column, which is a foreign key, I'm trying to set it to a "NULL" value but the error says "ERROR 1452: Cannot add or update a child row: a foreign key constraint fails. "
try
{
con.Open();
MySqlCommand cmd = new MySqlCommand(
"UPDATE tblcdsummary
set PersonalInfoID = '" + DBNull.Value.ToString() +
"' WHERE CDID = '" + looplabel2.Text + "'", con);
cmd.ExecuteNonQuery();
con.Close();
}
catch (Exception x)
{
MessageBox.Show(x.Message);
}
Do you know what is the result of DBNull.Value.ToString()?
It is an empty string. This means that if a relationship exists between these two tables then you are trying to relate the updated record to a record on the second table based on an empty string.
Of course, if the related table has no record with its primary key set to an empty string, your update will fail.
If you want to set that field to NULL then write it explicitly (no quotes)
MySqlCommand cmd = new MySqlCommand(
#"UPDATE tblcdsummary
set PersonalInfoID = NULL
WHERE CDID = #id", con);
cmd.Parameters.Add("#id", MySqlDbType.VarChar).Value = looplabel2.Text;
Of course this works only if you allow NULL to be stored in PersonalInfoID column
PS. I have also changed your code to use a parameterized query. It is the only correct way to build sql command texts.
Don't concatenate strings. It is a really big error (Search for Sql Injection)
you need to first update value of this key in its actual table(ie. table reffered using this key)
Is there a way to retrieve the latest inserted guid in access with C#?
I tried this: Created a table Cars with a field Id of type autonumber, replicationID and a field Name varchar(250).
var command = myConnection.CreateCommand();
command.Connection.Open();
command.CommandText = "INSERT INTO Cars(Name) VALUES ('Pagani')";
command.ExecuteNonQuery();
command = context.Database.Connection.CreateCommand();
command.CommandText = "SELECT ##Identity";
Console.WriteLine(command.ExecuteScalar());
command.Connection.Close();
The issue which I am getting is:
Console.WriteLine(command.ExecuteScalar());
always shows 0
EDIT
To create the table you can use this statement over the C# OleDb connection (I think that from MS Access query does not work)
CREATE TABLE [Cars] (
[Id] guid not null DEFAULT GenGUID(),
[Name] text null
);
ALTER TABLE [Cars] ADD CONSTRAINT [PK_Cars_6515ede4] PRIMARY KEY ([Id])
I know this is not exactly what you are asking for, but let me suggest an alternative solution which might solve your underlying problem.
Create the GUID in C# and pass it to your insert:
var newGuid = Guid.NewGuid();
var command = myConnection.CreateCommand();
command.Connection.Open();
command.CommandText = "INSERT INTO Cars(Id, Name) VALUES (?, 'Pagani')";
command.Parameters.AddWithValue("#Id", newGuid); // Note: OleDb ignores the parameter name.
command.ExecuteNonQuery();
Console.WriteLine(newGuid);
GUIDs are unique. It really doesn't matter whether it is generated by your application or by the Access database driver.
This option is in all respects superior to reading the GUID afterwards:
You only need one database access.
It's less code.
It's easier.
And you can still omit the GUID in your INSERT in cases where you don't need to know the GUID - no need to change existing code.
If SELECT ##IDENTITY does not work for "ReplicationID" AutoNumber fields then the most likely way to retrieve such a value for a new record is to use an Access DAO Recordset insert, like this:
// required COM reference:
// Microsoft Office 14.0 Access Database Engine Object Library
var dbe = new Microsoft.Office.Interop.Access.Dao.DBEngine();
Microsoft.Office.Interop.Access.Dao.Database db = dbe.OpenDatabase(
#"C:\Users\Public\Database1.accdb");
Microsoft.Office.Interop.Access.Dao.Recordset rst = db.OpenRecordset(
"SELECT [Id], [Name] FROM [Cars] WHERE FALSE",
Microsoft.Office.Interop.Access.Dao.RecordsetTypeEnum.dbOpenDynaset);
rst.AddNew();
// new records are immediately assigned an AutoNumber value ...
string newReplId = rst.Fields["Id"].Value; // ... so retrieve it
// the returned string is of the form
// {guid {1D741E80-6847-4CB2-9D96-35F460AEFB19}}
// so remove the leading and trailing decorators
newReplId = newReplId.Substring(7, newReplId.Length - 9);
// add other field values as needed
rst.Fields["Name"].Value = "Pagani";
// commit the new record
rst.Update();
db.Close();
Console.WriteLine("New record added with [Id] = {0}", newReplId);
which produces
New record added with [Id] = 1D741E80-6847-4CB2-9D96-35F460AEFB19
You can try like this using the OUTPUT :
INSERT INTO myTable(myGUID)
OUTPUT INSERTED.myGUID
VALUES(GenGUID())
You can try like this:
string str1 = "INSERT INTO Cars(Name) VALUES ('Pagani')";
string str2 = "Select ##Identity";
int ID;
using (OleDbConnection conn = new OleDbConnection(connect))
{
using (OleDbCommand cmd = new OleDbCommand(str1, conn))
{
conn.Open();
cmd.ExecuteNonQuery();
cmd.CommandText = str2;
ID = (int)cmd.ExecuteScalar();
}
}
I have two tables (Primary_Table and Secondary_table). Primary_Table contains primary key which is a foreign key for Secondary_table. Whenever I insert a new row into Primary_table I need to take its primary key and insert it into secondary_table. I am facing difficulties in taking primary key as a parameter. I need help on this.
string connString = "Database=MyServerDB;Server=ATLW732FV000169\SQLEXPRESS;Integrated Security=True;connect timeout = 30";
SqlConnection myConnection = new SqlConnection(connString);
try
{
myConnection.Open();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
using (SqlCommand command = new SqlCommand("INSERT INTO Primary_Table (TransactionType, Country) "VALUES (#transactionType, #country);" +
"INSERT INTO Secondary_table (BookingID,TripID) VALUES (#bookingID, #tripID);" , myConnection))
{
// declaring Primary_Table paramteres
command.Parameters.AddWithValue("#transactionType", "S");
command.Parameters.AddWithValue("#country", "US");
// declaring Secondary_table parameters
command.Parameters.Add("#bookingID", *****); // Not sure how to insert bookingID (priamry key) into Secondary Table
command.Parameters.AddWithValue("#tripID", "tr");
try
{
Int32 lines = command.ExecuteNonQuery();
Console.WriteLine("Lines affected " + lines);
}
catch (SqlException ex)
{
Console.WriteLine(ex.Message);
}
}
Define a trigger AFTER INSERT on Primary_Table that will take primary key of inserted data and insert it in to secondary_table.
Do this:
After your first insert -
DECLARE #var int
#var = select top 1 [pk] from table1 order by pk desc
This will get you the most recent record from table1 with #var being the pk, then simply...
insert into table2 ([fk]) values (#var)
This is easiest to do inside a stored procedure, which is considered best practice anyways (don't do inline SQL in your .NET code ever).
you can insert in to primary and secondary table via one storedprocedure in sql :
declare #Primary_Id int
INSERT INTO Primary_Table (TransactionType, Country) VALUES (#transactionType, #country)
set #Primary_Id =##identity
INSERT INTO Secondary_table (BookingID,TripID) VALUES (#bookingID, #Primary_Id)
and then in code :
command.CommandType= CommandType.StoredProcedure;
I have a series of data that need to be written into SQL, what should I do to check the data in SQL to prevent same data inserted into table?
Example data to be inserted:
David
James
John
If the 4th data is John again, I want the system to skip the duplicate record (John).
So far I have:
SqlConnection myCnn = new SqlConnection(cnn);
String _state = "Insert into CamNo1(platename, date, camID, path, filename) OUTPUT INSERTED.platename values(#msg, getdate(), #camID, #path, #filename)";
SqlCommand _Query = new SqlCommand(_state, myCnn);
_Query.Parameters.AddWithValue("#msg", msg);
_Query.Parameters.AddWithValue("#camID", camID);
_Query.Parameters.AddWithValue("#path", imageFile);
_Query.Parameters.AddWithValue("#filename", name);
try
{
myCnn.Open();
string checkname = (string)_Query.ExecuteScalar();
myCnn.Close();
getcheckname = checkname;
Console.WriteLine("OK");
}
catch (Exception)
{
}
i got the string value checkname that is last inserted, what should i do check the data?
First, you can prevent a duplicate from ever occurring in the table by using a unique index or constraint. An index/constraint can work in concert with the suggestions below. If you only use a unique index and not one of the below solutions, inserting a duplicate record will throw an error and you will need to handle that on the other end.
Additionally, I would probably insert the data via a stored procedure that checks to see if the row already exists. To do that, you can use either a MERGE statement, as shown in this pseudo code:
create procedure MyProcedure
(
#Name nvarchar(100),
...
)
as
merge MyTable
using
(
select #Name,...
) as source (Name, ...)
on MyTable.Name = source.Name
when not matched then
insert (Name,...) values (source.Name,...)
when matched then
update set Name = #Name,...
or, you could check for the records existence and insert or update manually:
create procedure MyProcedure
(
#Name nvarchar(100),
...
)
as
if not exists (select * from MyTable where Name = #Name)
begin
insert into MyTable (Name,...) values (#Name,...)
end
else
begin
update MyTable
set ...
where Name = #Name
end
If you do not want duplicate data, you should consider enforcing that at the DB level with a UNIQUE CONSTRAINT or a UNIQUE INDEX
SQL Server 2008 also has a MERGE statement you could use to check for matched records. This could be helpful if you want to update an existing record.
If you want to prevent duplicate data from being inserted, you could use a unique index or unique constraint on those fields.
If you want to just run a hard insert statement, but have it do nothing if a value exists, something like this should work. I tested this on a local database I have:
declare #subject as varchar(100);
set #subject = 'hello'
insert into Subjects ([name])
select #subject
where not exists (select 1 from Subjects where [name] = #Subject)
Try This Easy way
{
DataSet ds = New DataSet();
SqlConnection myCnn = New SqlConnection(cnn);
myCnn.Open();
SqlCommand _Query = New SqlCommand("Select *FROM CamNo1 where platename='" + Console.ReadLine + "' ", myCnn);
SqlDataAdapter sda = New SqlDataAdapter(_Query);
sda.Fill(ds);
Int i = ds.Tables[0].Rows.Count;
If (i > 0) Then
{
MessageBox.Show("platename" + Console.WriteLine + "Already Exists ");
ds.Clear();
}
Else
{
SqlConnection myCnn = New SqlConnection(cnn);
String _state = "Insert into CamNo1(platename, date, camID, path, filename) OUTPUT INSERTED.platename values(#msg, getdate(), #camID, #path, #filename)";
SqlCommand _Query = New SqlCommand(_state, myCnn);
_Query.Parameters.AddWithValue("#msg", msg);
_Query.Parameters.AddWithValue("#camID", camID);
_Query.Parameters.AddWithValue("#path", i`enter code here`mageFile`);
_Query.Parameters.AddWithValue("#filename", Name);
Try
{
myCnn.Open();
String checkname = (String)_Query.ExecuteScalar();
myCnn.Close();
getcheckname = checkname;
Console.WriteLine("OK");
}
Catch (Exception)
{
}
}
}
At the moment I'm writing a small conversion program, it will convert the primary key strategy to the using of GUIDs in stead of integers. This is a simple client induced requirement and I can't change that.
I've added a substitute pk candidate of the RAW(16) to every table in the database and filled each record with a SYS_GUID().
I did the same for the FKs, I added a substitute column for each FK.
Now I'm in the process of linking the FKs to their PKs, by querying the parent table I get the guid/new key for the specific row, after that I want to insert into the substitute candidate FK in the child table.
Somewhat like this:
sqlString = "SELECT PK FROM " + t+ " WHERE " + fkcol+ " = " + childValue;
OracleDataReader guidReader = GetDataReader(sqlString);
while (guidReader.Read())
{
sqlString = "UPDATE T SET FK = " + guidReader["PK"];
}
Debugging this sqlString gets me the following value:
UPDATE SIS_T_USER SET FK_C_EMPLOYEE_ID
= System.Byte[]
Now, how do I go forth and save this as a nice guid in my oracle database?
EDit how:
OracleCommand command = new OracleCommand(sqlString, this.oracleConnection);
command.CommandType = CommandType.Text;
OracleParameter op1 = new OracleParameter("guid", OracleDbType.Raw);
op1.Value = guidReader["PK"];
command.Parameters.Add(op1);
try
{
command.ExecuteNonQuery();
}
catch (OracleException oex)
{
Console.WriteLine("Unable to update: {0}", oex.Message);
}
Why don't you just do this all on Oracle side?
MERGE
INTO sis_t_user s
USING employee e
ON (s.integer_fk = e.integer_pk)
WHEN MATCHED THEN
UPDATE
SET s.guid_fk = e.guid_pk
Try this code:
sqlString = "UPDATE T SET FK = '" + (new Guid((byte[])guidReader["PK"])).ToString() + "'";
Basically, you just need to create guid from bytes and then convert it to string.
There is Guid constructor that allows it: http://msdn.microsoft.com/en-us/library/90ck37x3(v=VS.100).aspx.