2010-03-04 45 views
0

在手冊頁上; http://dev.mysql.com/doc/refman/5.0/en/mysql-insert-id.html 據說「返回前一個INSERT或UPDATE語句爲AUTO_INCREMENT列生成的值」。mysql_insert_id()問題與MySQL 5.0.67 + Windows + VC++ 2008

問題是,更新後它並不適合我。

真正的需求是,我試圖更新表中的一行(用「WHERE」條件更新),然後,如果某一行確實已更新,請獲取它的完整詳細信息。 所以首先我更新,然後我需要它的id來獲取它的詳細信息與SELECT語句。

下面是一個例子代碼顯示問題:

#define _WIN32_WINNT 0x0400 
#define WIN32_LEAN_AND_MEAN 
#include <windows.h> 

#include <stdio.h> 
#include <conio.h> 

#include <winsock.h> 

#include "C:/Program Files (x86)/MySQL/MySQL Server 5.0/include/mysql.h" 
#pragma comment(lib, "C:/Program Files (x86)/MySQL/MySQL Server 5.0/lib/opt/libmysql.lib") 

void main() 
{ 
MYSQL *conn = mysql_init(NULL); 
if(conn == NULL) 
    throw "error"; 
if(mysql_real_connect(
    conn, 
    "127.0.0.1", 
    "user", "passwd", 
    NULL, 
    0, 
    NULL, 
    0) != conn) 
    throw "error"; 

int nRet = 0; 

char szInsert[] = "INSERT INTO db_transation_test.tbl_transactions SET amount=71, ses=72"; 
nRet = mysql_real_query(conn, szInsert, sizeof(szInsert)); 
if(nRet != 0) 
{ 
    printf("%s\n", mysql_error(conn)); 
    throw; 
} 
my_ulonglong inserted_id = mysql_insert_id(conn); 

///////// the real issue of my post starts here ///////// 

char szUpdateTemplate[] = "UPDATE db_transation_test.tbl_transactions SET amount=123 WHERE id_transaction=%lld"; 
char szUpdate[1024]; 
nRet = sprintf_s(szUpdate, sizeof(szUpdate), szUpdateTemplate, inserted_id); 
nRet = mysql_real_query(conn, szUpdate, nRet); 
if(nRet != 0) 
{ 
    printf("%s\n", mysql_error(conn)); 
    throw; 
} 
my_ulonglong updated_id = mysql_insert_id(conn); // returns ZERO instead of 'inserted_id' :(

_getch(); 
} 

如何使這個mysql_insert_id()函數工作,在這種情況下,或者如何更新和一個statament選擇?

請注意,我在這個例子中插入一行所以它會做出一些列的你,所以你可以看到..

謝謝!編輯: 看看我對這個問題的最新回覆。我給出了更爲清晰的描述。

+0

是的,這是一個問題。 我希望有另一種方式來實現它,否則執行一個查詢,其中包括更新和上一次更新的選擇...查看我的意思? – Poni 2010-03-04 13:38:19

+0

我很想知道誰在討厭我的問題:) – Poni 2010-03-04 14:08:53

回答

0

您的UPDATE語句不會導致自動增量ID的生成,因此在更新後調用mysql_insert_id是沒有意義的。

正如文檔所說,mysql_insert_id()用於生成自動遞增值的插入語句,或直接調用LAST_INSERT_ID(expr)^的update/insert語句。

您已經在插入語句後立即提取了inserted_id,您不需要再次獲取它。

編輯,你顯然是在問別的東西。

您有類似 UPDATE db_transation_test.tbl_transactions SET amount=123 WHERE username=someone;

,你想獲取該該查詢更新任何行的主鍵?這是你真正的問題嗎?

如果是這樣。否。運行單獨的選擇查詢來獲取該ID。

0

波尼,我覺得mysql_affected_rows()是你的函數:

mysql_affected_rows()函數可以被執行 語句的mysql_query後立即調用()或mysql_real_query()。如果 是UPDATE,DELETE或INSERT,它將返回 更改,刪除或插入最後一條語句的行數。對於SELECT語句, mysql_affected_rows()與mysql_num_rows()類似。

+0

這給出了受影響的行數。 我需要該受影響行的ID。 – Poni 2010-03-04 13:40:25

+0

你告訴mysql當你做了哪一行更新:WHERE id_transaction =%lld。所以你已經知道你正在更新的行的id。 – nos 2010-03-04 13:41:46

+0

哈哈。 是的,但在這個例子中。 請參閱備註: /////////我的帖子的真正問題從這裏開始///////// 想象一下真實世界的代碼從那裏開始,但是我更新了使用登錄/密碼參數而不是身份證。 – Poni 2010-03-04 13:45:01

0

如果update語句修改了可自動增加的值,mysql_insert_id將只返回更新語句上的一個id。據推測,如果你已經基於它做了更新,你就有了id,所以只需在更新之後進行基於id的選擇即可。

編輯:我不是建議你在更新時修改id列,我只是說這是mysql_insert_id將返回更新查詢值的唯一情況。

迴應評論:那麼你應該做的是選擇先通過登錄/密碼來獲得該行的ID,然後通過該行的ID做你的更新從選擇

+0

正如我試圖解釋的,在現實世界中,我沒有id,我使用登錄/密碼參數進行更新。 – Poni 2010-03-04 13:41:29

+0

我在回答中回覆了您的評論。我希望這有幫助。 – 2010-03-04 13:46:17

+0

如果我不會看到任何「明亮」的想法,我可能會做類似的事情。比我目前的解決方案更密集。謝謝你! – Poni 2010-03-04 13:53:53

0

的結果您的UPDATE語句不會導致生成自動增量的ID,因此在更新後調用mysql_insert_id是沒有意義的。

正如文檔所說,mysql_insert_id()用於生成自動遞增值的插入語句,或直接調用LAST_INSERT_ID(expr)^的update/insert語句。

您已經在插入語句後立即提取了inserted_id,您不需要再次獲取它。

+0

在現實世界中,我不插入任何行。 我正在使用某些登錄/密碼參數進行更新。 – Poni 2010-03-04 13:43:24

0

爲了澄清,忘了我最初發布的代碼 - 這是我需要更簡單的方法:

首先,我更新: UPDATE db_test.tbl_test SET owner_id = 55 WHERE登錄='USER_NAME 'AND passwd ='password'AND owner_id = -1

然後我檢查是否有更新的行,用mysql_affected_rows()這樣做。如果它是一個(不能更多,因爲字段「登錄」是唯一的),那麼我想獲得這個行的ID,而不是做另一個SELECT。

這背後的邏輯是什麼? 這將是一個多玩家數據庫商店,並且有幾個服務器。 我需要以某種方式強制玩家一次只能登錄一次。 這是通過鎖定帳戶完成的; 「-1」的「owner_id」表示免費賬戶,而如果不是則該玩家已經在玩。

希望現在更清楚一點。