I am using mysql connector C++. There is an auto_increament column in my table, I want to get the insert id when I perform an insert action. Does someone know how to get it? Thanks.
My code is something like:
conn->setAutoCommit(0);
pstmt.reset(conn->prepareStatement(insertStr.c_str()));
int updateCount = pstmt->executeUpdate();
conn->commit();
If the API of the library you are using does not provide a method to retrieve the last_insert_id (which seems to be the case for the C++ Connector) you can always do a query
SELECT LAST_INSERT_ID();
which gives you the "value representing the first automatically generated value successfully inserted for an AUTO_INCREMENT column as a result of the most recently executed INSERT statement." See here for the explanation of MySQL's documentation
UPDATE:
I found this post from a user who is saying the if you do not use auto_increment on your field you can use
SELECT ##identity AS id;
Related
I'm writing an ODBC class to connect to a remote SQL Server database. I have most of it working.
The class has the ability to generate queries such as the following:
UPDATE Customers SET Id=?,Name=?,TaxId=?,ContactFName=?,ContactLName=?,Phone_Office=?,Phone_Mobile=?,Phone_Home=?,Email=?,Website=?,Address1_Physical=?,Address2_Physical=?,City_Physical=?,State_Physical=?,Zip_Physical=?,Address1_Billing=?,Address2_Billing=?,City_Billing=?,State_Billing=?,Zip_Billing=?,StartingBalance=?,Discount=?,BillingSequence=?,BillingCategory=?,ShowOnReport=?,Active=?,CreateDate=?
As you can see, it's an UPDATE query. Yet, running this query gives me an error:
Microsoft ODBC Driver 17 for SQL Server (SQL Server) : ReturnCode: -1 : Violation of PRIMARY KEY constraint 'PK_Customers'. Cannot insert duplicate key in object 'dbo.Customers'. The duplicate key value is (82). (State: 23000, NativeError: 2627) : The statement has been terminated. (State: 01000, NativeError: 3621)
I'm confused why I'm getting an error about inserting when I'm doing an update. Has anyone seen this?
Notes:
Id is the primary key. I first read all column values from the database, and then update those I want to change. The ID does not change.
The error above was put together by my code, but is based on the messages returned by SQLGetDiagRec().
There's no WHERE clause on the UPDATE statement, so it's trying to update EVERY SINGLE ROW in the database, and since ID is one of the columns being changed, it's trying to set every row's ID to the same value. This is resulting in an attempt to create a duplicate primary key.
Make sure your UPDATE statement has an appropriate WHERE clause... like "WHERE ID = ?"... and it's probably best practice to NOT include the ID in that UPDATE statement if it's not changing.
That is the message you should expect when an UPDATE statement violates a primary key. EG
use tempdb
go
drop table if exists t
create table t(id int primary key)
insert into t(id) values (1),(2)
go
update t set id = 2 where id = 1
--Msg 2627, Level 14, State 1, Line 11
--Violation of PRIMARY KEY constraint 'PK__t__3213E83F127C5D76'. Cannot insert duplicate key in object 'dbo.t'. The duplicate key value is (2).
--The statement has been terminated.
In the UPDATE I see a field called ID. If you are making a change to the ID and it's the primary key then the DBMS will fuss because you are trying to store duplicate keys.
i am using c++ 4.8 ( available 4.9) and pqxx driver ver. 4.0.1.
postgresdb is latest stable.
My problem is all about complexity and resource balance:
I need to execute insert to database (and there is optionally pqxx::result) and id in that table id is based on nextval(table_seq_id)
Is is possible to get id of inserted row as a result? There is a workaround on this to ask db about currentvalue in sequence and just insert query with currentvalue+1 (or +n) but this will require to do "insert and ask" chain.
Db should be able to store more than 6K large requests /per.sec. so i would like to ask about id as infrequent as possible. Bulk insert is not an option.
As documented here, you can add a RETURNING clause to the INSERT query, to return values from the inserted row(s). They give an example similar to what you want, returning an ID:
INSERT INTO distributors (did, dname) VALUES (DEFAULT, 'XYZ Widgets')
RETURNING did;
I have been searching for a while on how to get the generated auto-increment ID from an "INSERT . INTO ... (...) VALUES (...)". Even on stackoverflow, I only find the answer of using a "SELECT LAST_INSERT_ID()" in a subsequent query. I find this solution unsatisfactory for a number of reasons:
1) This will effectively double the queries sent to the database, especially since it is mostly handling inserts.
2) What will happen if more than one thread access the database at the same time? What if more than one application accesses the database at the same time? It seems to me the values are bound to become erroneous.
It's hard for me to believe that the MySQL C++ Connector wouldn't offer the feature that the Java Connector as well as the PHP Connector offer.
An example taken from http://forums.mysql.com/read.php?167,294960,295250
sql::Statement* stmt = conn->createStatement();
sql::ResultSet* res = stmt->executeQuery("SELECT ##identity AS id");
res->next();
my_ulong retVal = res->getInt64("id");
In nutshell, if your ID column is not an auto_increment column then you can as well use
SELECT ##identity AS id
EDIT:
Not sure what do you mean by second query/round trip. First I thought you are trying to know a different way to get the ID of the last inserted row but it looks like you are more interested in knowing whether you can save the round trip or not?
If that's the case, then I am completely agree with #WhozCraig; you can punch in both your queries in a single statement like inser into tab value ....;select last_inserted_id() which will be a single call
OR
you can have stored procedure like below to do the same and save the round trip
create procedure myproc
as
begin
insert into mytab values ...;
select last_inserted_id();
end
Let me know if this is not what you are trying to achieve.
Our C++ application is able to get collation related column metadata from SQL Server using OLEDB API’s (using DBCOLUMN_COLLATINGSEQUENCE, DBCOLUMN_TDSCOLLATION, etc.), but I need to use ODBC as our application has to be cross platform. We are using ODBC API SQLColAttribute to read rowset metadata, but this API does not have any identifiers which can return the collation name.
I tried using SQL_CA_SS_COLUMN_COLLATION (defined in sqlncli.h) as an identifier, but SQLColAttribute only returns “Collation Name” as the collation.
I also tried using SQLGetStmtAttr followed by SQLGetDescField, using the same identifier, and I got "Collation Name" back.
I have scoured all of MSDN for answers, but haven’t been able to find any. I can get the collation name from INFORMATION_SCHEMA.COLUMNS, but that will not work for calculated columns returned by queries.
I am looking for a clean way to get collation information from result set metadata using ODBC. Any ideas?
This query will return the collation_name for each column present in the current database.
SELECT o.name AS ObjectName, c.name AS ColumnName, c.collation_name
FROM sys.columns c
INNER JOIN sys.objects o ON c.object_id = o.object_id
INNER JOIN sys.types ty ON c.system_type_id = ty.system_type_id
WHERE o.is_ms_shipped = 0
AND ty.collation_name IS NOT NULL
AND ty.name <> 'sysname';
I have a simple database and want to update an int value. I initially do a query and get back a ResultSet (sql::ResultSet). For each of the entries in the result set I want to modify a value that is in one particular column of a table, then write it back out to the database/update that entry in that row.
It is not clear to me based on the documentation how to do that. I keep seeing "Insert" statements along with updates - but I don't think that is what I want - I want to keep most of the row of data intact - just update one column.
Can someone point me to some sample code or other clear reference/resource?
EDIT:
Alternatively, is there a way to tell the database to update a particular field (row/col) to increment an int value by some value?
EDIT:
So what is the typical way that people use MySQL from C++? Use the C api or the mysql++? I guess I chose the wrong API...
From a quick scan of the docs it appears Connector/C++ is a partial implementation of the Java JDBC API for C++. I didn't find any reference to updateable result sets so this might not be possible. In Java JDBC the ResultSet interface includes support for updating the current row if the statement was created with ResultSet.CONCUR_UPDATABLE concurrency.
You should investigate whether Connector/C++ supports updateable resultsets.
EDIT: To update a row you will need to use a PreparedStatement containing an SQL UPDATE, and then the statement's executeUpdate() method. With this approach you must identify the record to be update with a WHERE clause. For example
update users set userName='John Doe' where userID=?
Then you would create a PreparedStatement, set the parameter value, and then executeUpdate().